Bir çalışma sayfası kılavuzunun üzerinde yüzen her şey (bir grafik, bir logo, bir damga, bir açıklama kutusu) bir çizim nesnesidir ve bir çizim nesnesi iki şeyle tanımlanır: ne olduğu ve nereye çapalandığı. İnsanların yanlış yaptığı kısım çapadır. Bir grafik bir hücrede yaşamaz; satır ve sütun aralığına iğnelenmiş bir dikdörtgende oturur ve çizdiği veri, çapanın hiç haberdar olmadığı ayrı bir A1 başvuru kümesidir. Çerçeveyi taşırsınız, çizim yerinde kalır. Altına satır eklersiniz, çerçeve onlarla birlikte aşağı kayar. Bu iki koordinat sistemini birbirine karıştırmamak, çizim kodunun düzgün davranmasının neredeyse tamamıdır
HotXLS, XLS ve XLSX dosyalarını Excel otomasyonu olmadan okuyup yazan yerel bir Object Pascal kütüphanesidir ve iki dosya biçimi çizimleri farklı sakladığı için iki ayrı çizim modeli taşır. BIFF8 .xls biçimi grafikleri kendilerine ayrılmış sayfalarda, yüzen şekilleri ise çalışma sayfasına iliştirilmiş bir OfficeArt akışında tutar. OOXML .xlsx biçimi ise bir grafiği kılavuzun içine, bir hücre dikdörtgenine çapalanmış olarak gömebilir; aynı türden yüzen resimler ve şekiller de onun yanında durur. Nesne modeli bu ayrımı yansıtır ve yazmaya değer başarısızlıkların tamamı, bir biçimin kurallarını diğerine uygulamaktan doğar
Hangi kap neyi tutabilir
Kap tercihi her grafik kodundan önce gelmelidir, çünkü kullanılabilir nesne türleri ikisi arasında farklıdır:
- XLS (BIFF8): grafikler,
Sheetskoleksiyonu üzerindekiAddChartSheetile oluşturulan özel grafik sayfalarında yaşar. Resimler, metin kutuları, dikdörtgenler, ovaller ve çizgiler, çalışma sayfasınınShapeskoleksiyonuyla yönetilen OfficeArt şekilleridir. Normal bir çalışma sayfası kılavuzunun içine grafik gömmek için API yoktur - XLSX (OOXML): grafikler
TXLSXWorksheet.AddChartile doğrudan bir çalışma sayfasına, bir hücre dikdörtgenine çapalanarak gömülebilir ya daTXLSXWorkbook.AddChartSheetile özel bir grafik sayfasına yerleştirilebilir. GörüntülerAddImageya daAddImageFromFileile, yüzen etiketler iseAddTextBoxile girer
Dolayısıyla "sayıların yanında grafiği olan bir gösterge sayfası" diye ifade edilen bir gereksinim, aslında .xlsx gereksinimidir. Bunu .xls içinde ancak grafiği kendi sayfasına iterek yaklaşık olarak karşılayabilirsiniz; bu da kullanıcının dosyada nasıl gezindiğini ve kodunuzun nasıl davranması gerektiğini değiştirir. XLS tarafındaki AddChartSheet çağrısının döndürdüğü sayfa bir kılavuz değil, bir grafik alt akışıdır: ona Cells.Item ile yazmak, hatasız üretilen ama Excel tarafından açılışta atılan tutarsız bir çizim akışı doğurur. Grafik öylece yok olur ve derleme günlüğünde nedenini söyleyen hiçbir şey yoktur. Dönen sayfayı yalnızca grafik olarak ele alın; "grafik kayıp" bildirimlerinin tüm sınıfı ortadan kalksın
Bir XLSX çalışma sayfasına grafik gömme
XLSX yolu manevra alanı olan yoldur ve girişteki iki koordinat sisteminin somutlaştığı yer burasıdır. AddChart çağrısına verilen çapa dikdörtgeni çalışma sayfası satır ve sütunlarıyla ifade edilir ve grafik çerçevesinin nerede oturacağını sabitler. Veri serisi ise sayfa adını içeren mutlak A1 başvurularıyla ifade edilir. Bunlar birbirinden bağımsızdır: çerçeveyi sayfanın öbür ucuna taşıyabilirsiniz, yine aynı hücreleri çizer
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Chart: TXLSXChart;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Sales');
Sheet.Cells[1, 1].Value := 'Region';
Sheet.Cells[1, 2].Value := 'Revenue';
Sheet.Cells[2, 1].Value := 'East';
Sheet.Cells[2, 2].Value := 1184350;
Sheet.Cells[3, 1].Value := 'Central';
Sheet.Cells[3, 2].Value := 902210;
Sheet.Cells[4, 1].Value := 'West';
Sheet.Cells[4, 2].Value := 1010675;
// Çerçeve 6..22 satırlarına, 1..8 sütunlarına çapalanır
Chart := Sheet.AddChart(xlsxChartColumn, 'Revenue by Region', 6, 1, 22, 8);
Chart.AddSeries('Revenue', 'Sales!$A$2:$A$4', 'Sales!$B$2:$B$4');
Chart.ValueAxisTitle := 'USD';
Sheet.AddImageFromFile(1, 5, 'logo.png');
Book.SaveAs('dashboard.xlsx');
finally
Book.Free;
end;
end;
Isıran argüman, AddSeries çağrısına verilen aralık dizesidir. Bu bir değişmezdir, çağrı anında yakalanır ve sonradan yirmi satır daha veri ekleyebileceğinizden haberi yoktur. Onu, veri yazıldıktan sonra hesapladığınız bir satır sayısından kurun, asla öncesinden değil. Dağılım ve kabarcık grafikleri aynı iki argümana farklı anlamlar yükler: kategori aralığı artık X değerlerini, değer aralığı ise Y değerlerini sağlar ve kabarcık yarıçapı, dönen TXLSXChartSeries üzerindeki BubbleSizeRange ile ayarlanan üçüncü bir başvurudan gelir. Sütun ve çubuk ailesinden çıktığınızda çağrıyı "kategoriler, değerler" değil "X, Y, boyut" diye okuyun
TXLSXChartType; sütun, çubuk, çizgi, pasta, alan, halka, dağılım, kabarcık ve radar çizimlerini kapsar ki bu da gündelik raporlama dağarcığını karşılar. Çevresinde kılavuz olmayan tam sayfa bir grafik için Book.AddChartSheet, IsChartSheet özelliği true olan bir sayfa döndürür. Bu, eski grafik sayfasının .xlsx karşılığıdır ve aynı beklentiyi taşır: ona hücre içeriği yazmayın
Görüntüler bayt olarak girer ve EMU cinsinden boyutlanır
Resim eklemek için iki aşırı yükleme vardır ve bunları karıştırmak, kod incelemesinde en sık görünen görüntü hatasıdır. AddImage(ARow, ACol, AData, AFormat), AData içinde zaten kodlanmış resim baytlarını ister: bir PNG, JPEG, GIF ya da BMP dosyasının ham içeriğini. Ona bir dosya yolu verirseniz, hiçbir görüntüleyicinin çözemeyeceği kırk baytlık bir dize saklamış olursunuz ki bu da dağıtımdan sonra hata ayıklamak istemeyeceğiniz kırık görüntü simgesi bildiriminin ta kendisidir. Kaynak diskteki bir dosyaysa bunun yerine AddImageFromFile çağırın ve baytları okumayı, biçimi sınıflandırmayı kütüphaneye bırakın
Sonra boyutlandırma gelir. DrawingML piksel cinsinden ölçmez; bir inçin 914400 EMU ettiği ve 96 DPI değerinde bir pikselin 9525 EMU ettiği İngiliz Metrik Birimleri cinsinden ölçer. TXLSXImage nesnesi WidthEMU ve HeightEMU alanlarını açığa çıkarır, dolayısıyla 180 x 60 piksel işlenmesi gereken bir logo 1714500 x 571500 EMU ister. Bu dönüşümü adlandırılmış bir sabite koyun ve hesabı ona göre yapın. Kodun içine serpiştirilmiş 1714500 gibi sihirli sayılar okunmazdır ve biri hedef DPI değerini ilk değiştirdiğinde sessizce yanlışa döner. Bu arada çapa satırı ve sütunu 1 tabanlıdır; 0 tabanlı EMU aritmetiğine değil, hücre API bileşeninin geri kalanına uyar
Eski XLS dosyalarında grafik sayfaları ve şekiller
BIFF8 tarafında zengin AddChartSheet aşırı yüklemesi grafik türünü, eksen başlıklarını ve her kaydın bir ad ile dize olarak bir kategori ve değer aralığı tuttuğu açık bir TXLSChartSeriesInfo kayıt dizisini alır. Yüzen şekiller ayrı bir konudur: grafik sayfasına değil, veri çalışma sayfasının kendisine, onun Shapes koleksiyonu üzerinden girer
var
Book: IXLSWorkbook;
Data, Trend: IXLSWorksheet;
Series: array[0..0] of TXLSChartSeriesInfo;
begin
Book := TXLSWorkbook.Create; // arayüz sayımlı: Free çağırmayın
Data := Book.Sheets.Add;
Data.Name := 'Data';
Data.Cells.Item[1, 1].Value := 'Month';
Data.Cells.Item[1, 2].Value := 'Units';
Data.Cells.Item[2, 1].Value := 'Apr';
Data.Cells.Item[2, 2].Value := 1530;
Data.Cells.Item[3, 1].Value := 'May';
Data.Cells.Item[3, 2].Value := 1721;
Series[0].Name := 'Units';
Series[0].Categories := 'Data!$A$2:$A$3';
Series[0].Values := 'Data!$B$2:$B$3';
Trend := Book.Sheets.AddChartSheet('Trend', xlsChartTypeLine,
'Units sold', 'Month', 'Units', Series);
// Trend bir grafik alt akışıdır: üzerinde asla hücre yöntemi çağırmayın
Data.Shapes.AddTextBox('Source: ERP nightly export', 6, 1, 8, 4);
Data.Shapes.AddPicture('approved-stamp.bmp');
Book.SaveAs('trend.xls');
end;
Burada iki yaşam süresi ayrıntısı önemlidir ve ikisi ters yönlere çeker. TXLSWorkbook, IXLSWorkbook arayüzü üzerinden tutulur ve başvuru sayımlıdır, dolayısıyla onun üzerinde kendiniz Free çağırmanız çift serbest bırakmayı tetikler. Önceki bölümlerdeki TXLSXWorkbook ise düz bir nesnedir ve bir try..finally içinde serbest bırakılmalıdır. XLSX tarafında eksik bir Free çağrısını işaretleyen kod gözden geçiren, XLS tarafında var olan bir tanesini işaretlemek zorundadır; aynı birim içinde iki biçimle birden çalışırken bu gerçek bir tökezleme noktasıdır. Şekil yardımcılarının kendileri ise tektiptir: AddRectangle, AddOval ve AddLine, çizimlerden bir bölgeyi temizlemek için de DeleteInRange; hepsi satır ve sütun çiftleriyle çapalanır, dolayısıyla üzerlerine satır ekleyen bir şablon onları kılavuzla birlikte kaydırır
Eski dosyalarda bir özellik daha ekmeğini çıkarır. TXLSPicture.TransparentColor, seçtiğiniz bir arka plan rengini bir bit eşlemden maskeler; BIFF işlemesi PNG saydamlığını hiç öğrenmemiş bir biçimde dikdörtgen olmayan bir damgayı (bir "Approved" mührü, bir filigran) kılavuzun üzerine böyle bırakırsınız. Damganın hangi renge göre hazırlandığını ayarlayın, çevresindeki dikdörtgen kaybolsun
Tema renkleri BIFF8 gidiş dönüşünden sağ çıkmaz
OOXML çizim dolguları bir tema rengi yuvasını gösterebilir; bir .xlsx dosyasının tamamını temasını değiştirerek yeniden renklendirmenin ucuz olmasının nedeni budur. BIFF8 çizim kayıtlarında böyle bir yuva yoktur. HotXLS bir XLS çizimine tema rengi uyguladığında rengi değişmez bir RGB değerine çözer ve onu saklar; geldiği tema dizini, dosya yazıldığı anda kaybolur ve yeniden açmak onu geri getiremez. Bu özellikle beyaz etiketli raporlama araçlarını, yani aynı üretilmiş belgeyi birçok müşteri için yeniden markalayan türü yakalar. Tema ile RGB eşlemesini kendi yapılandırmanızda tutun ve kaydedilmiş bir .xls dosyasından geri okumayı beklemek yerine her üretimde yeniden uygulayın
Başarımla ilgili bağlantılı bir karar da ortaya çıkar. XLS cephesine, büyük bir eski dosyadan istediğiniz tek şey hücre verisiyse çizim katmanını tümüyle ayrıştırmayı atlaması söylenebilir; bunun için _DisableGraphics değerini true yapmak yeterlidir ve bu, toplu okumalardan gerçek süre kısar. Yakalayan kısım kalıcıdır: böyle açılmış bir çalışma kitabının bellekte OfficeArt akışı yoktur, dolayısıyla onu kaydetmek çizimleri yok eder. Bayrağı salt okunur analitik işlere saklayın. Geniş başarım tablosu HotXLS içinde büyük çalışma kitabı başarımı üzerine notlarımızda yer alır
Kılavuz değişirken çapaları kararlı tutmak
Raporlar nadiren üretildikleri boyutta kalır ve girişteki çapa modeli kendini burada amorti eder. XLSX cephesinin yapısal işlemleri (InsertRows, DeleteRows ve sütun karşılıkları) bağımlı katmanları hücrelerle birlikte taşır. Birleştirilmiş bölgeler, köprüler, açıklamalar, dondurulmuş bölmeler, süzgeç aralıkları, koşullu biçimler, doğrulamalar, tablolar, tanımlanmış adlar ve bu konu açısından görüntü ile grafik çapaları hep birlikte yolculuk eder. 1. satıra çapalanmış bir logo, altına on satır girdiğinde üstte kalır. Veri bloğunun altına çapalanmış bir grafik çerçevesi, blok büyüdükçe aşağı kayar. Yeniden yazılmayan tek şey, ekleme gerçekleşmeden önce değişmez olarak yakaladığınız her aralık dizesidir, çünkü o yalnızca metindir ve kütüphanenin ona dönmek için bir nedeni yoktur. Bu, bir şablon doldurma için güvenli sırayı belirler: önce veriyi yazın ve biçimlendirin, grafikleri oluşturup görüntüleri yerleştirmeyi ise son geçiş olarak yapın; her aralık dizesi de eklemelerden önceki değil, sonraki satır sayılarından türetilsin
İki küçük araç yerleştirme takımını tamamlar. XLS tarafındaki TXLSTextBox.SetArea, var olan bir metin kutusunu ya da otomatik şekli yeni bir hücre dikdörtgenine yeniden çapalar ki bir altbilgi bloğu kaydığında bu, onu silip yeniden oluşturmaktan iyidir. AddPicture çağrısının bit eşlem aşırı yüklemesi ise isteğe bağlı bir saydamlık bayrağıyla canlı bir TBitmap alır, dolayısıyla kendi VCL kodunuzun çizebildiği her şey (bir gösterge, bir mini grafik şeridi, yerleşik listede bulunmayan bir grafik türü) önce geçici bir dosya yazmadan doğrudan sayfaya damgalanabilir
Grafikler ve görüntüler neredeyse her zaman halihazırda yapılandırılmış bir raporun son katmanıdır; temiz oturup oturmayacaklarına da bu yüzden altyapı karar verir. Bir grafiğin başvuracağı veriyi doldurma konusu şablon güdümlü rapor üretimi yazısında, çapalarınızın altındaki kılavuzu kararlı tutmak ise birleştirilmiş hücreler ve düzen denetimi yazısında ele alınmaktadır. Eksiksiz sınıf ve yöntem belgeleri HotXLS Delphi Bileşeni ürün sayfasında bulunur