Teknik Makale

HotXLS ile Çalışma Sayfalarına Grafik Nesneleri Gömme

HotXLS bir grafiği, ayrılmış bir chart sheet'e koymak yerine doğrudan çalışma sayfasına, bir hücre aralığına sabitlenmiş olarak yerleştirebilir. BIFF8 terimleriyle bu, tip 5 OBJ kaydı taşıyan bir çizim şekli yazmak ve grafik alt akışını sayfa kayıt akışının sonuna park etmek demektir; Excel'in ürettiği düzen de tam olarak budur, okuyucunun onu bulmayı beklediği yer de

Ayrım, operasyonel rapor üreten herkesi ilgilendirir. Chart sheet, tek bir manşet görseli için iyi bir evdir. Aylık bölgesel döküm ise grafiği özetlediği sayıların yanında, aynı sayfada, ait olduğu hücre bloğuna boyutlandırılmış olarak ister; böylece okuyucu sekme değiştirip bağlamını kaybetmek yerine bir kez kaydırır

Okuma çoktan oradaydı, yazma değildi

Asimetriyi adlandırmaya değer; çünkü işi o şekillendirir. HotXLS gömülü grafikleri zaten okuyabiliyordu: çalışma sayfası kayıt akışı bir grafik alt akışı olarak işaretli BOF içerdiğinde çözümleyici bağlam değiştirir, grafik kayıtlarını toplar ve kapanış EOF'unda onları OBJ kaydının tanıttığı çizim şekline geri verir. Bu yol, kütüphanenin açtığı her Excel kökenli çalışma kitabı tarafından kullanılmıştı

Eksik olan üretim tarafıydı ve bunun faydalı sonucu, yeni yazıcının isabet ettireceği kesin bir spesifikasyonunun olmasıydı: mevcut okuyucunun zaten yeniden bağladığı bayt düzenini üretmek. İkili format özelliği için, değiştiremediğiniz bağımsız yazılmış bir okuyucudan daha iyi bir kabul kriteri yoktur

Bir gömülü grafik nelerden oluşur?

Üç parça anlaşmak zorundadır. Çizim katmanı bir host-control şekli koyar, nesne katmanı common object data'sında nesne tip 5 bildiren bir OBJ kaydı koyar, kayıt akışı da grafik alt akışının kendisini koyar. OBJ kaydındaki option bayrakları, Excel'in bir grafik çerçevesi için yazdıklarıdır: positioned, locked, automatic line ve automatic fill; kullanıcı tıkladığında gömülü grafiği yerli bir grafik gibi davranan da bunlardır

HotXLS, bir BIFF8 grafik alt akışını üç anlaşan parça üzerinden Delphi çalışma sayfasına bağlar: çizim katmanı host-control şekli, common object data'sında nesne tip 5 bildiren OBJ kaydı ve sayfa kayıt akışının sonuna park edilen grafik kayıt zinciri; grafik BOF çözümleyici bağlamını değiştirir, kapanış EOF kayıtları yeniden bağlar
Üç katman tek gömülü grafiği taşır: çizim şekli onu sabitler, OBJ kaydı onu bir grafik host'u olarak tipler ve sayfa akışının sonundaki grafik alt akışı, okuyucunun yeniden bağladığı kayıtları sağlar

Çıpaya bir not düşmeye değer; çünkü off-by-one böceklerinin yaygın bir kaynağıdır. HotXLS API'si, kütüphanenin geri kalanıyla uyumlu olarak tek tabanlı satır ve sütun numaraları alır; dosyaya yazılan client anchor ise sıfır tabanlıdır. Dönüşüm AddChartObject içinde gerçekleşir, böylece çağıranlar her yerde kullandıkları koordinat sisteminde kalır; ama hex dökümünü kendi çağrısıyla karşılaştıran herkes, o sınırın hangi tarafını okuduğunu hatırlamalıdır

var
  Book: TXLSWorkbook;
  Sheet: TXLSWorksheet;
  Series: array[0..1] of TXLSChartSeriesInfo;
begin
  Book := TXLSWorkbook.Create(nil);
  try
    Book.LoadFromFile('regional-sales.xls');
    Sheet := Book.Sheets[0];

    FillChar(Series, SizeOf(Series), 0);
    Series[0].Name := 'Actual';
    Series[0].Categories := 'Data!$A$2:$A$13';
    Series[0].Values := 'Data!$B$2:$B$13';
    Series[0].DataLabels.ShowValue := True;
    Series[0].HasDataLabels := True;

    Series[1].Name := 'Target';
    Series[1].Categories := 'Data!$A$2:$A$13';
    Series[1].Values := 'Data!$C$2:$C$13';
    Series[1].SecondaryAxis := True;

    // Bu sayfada E2:M20'ye sabitlendi, tek tabanlı (one-based)
    Sheet.AddChartObject(xlsChartTypeColumn, 'Regional sales',
      'Month', 'Amount', Series, 2, 5, 20, 13);

    Book.SaveToFile('regional-sales-charted.xls');
  finally
    Book.Free;
  end;
end;

Seri dizisi üzerindeki FillChar süs değildir. TXLSChartSeriesInfo, her biri bir boolean ile kapılı birkaç isteğe bağlı alt kayıt taşır: veri etiketleri, seri başına stil, trend çizgileri ve hata çubukları; stack üzerinde yarım ilklendirilmiş bir kayıt, yayıcıya kimsenin kurmadığı bayrakları teslim eder. Diziyi sıfırlayın, sonra niyet ettiğiniz alanları kurun

Gömülü yol hangi seri referanslarını kabul eder?

Aynı çalışma kitabı içindeki düz A1 tarzı aralıkları; kısıt bir gözden kaçma değil kasıtlıdır. Her referans, çalışma kitabı sayfa listesine karşı çözümlenir ve grafik kayıtlarının ihtiyaç duyduğu external reference indeksine çevrilir. Adlandırılmış bir aralık ya da harici çalışma kitabı referansı, sıfır uzunlukta parse edilmiş ifade taşıyan bir placeholder'a düşer; grafik temiz yazılır ama o özel seri, siz onu bir aralığa işaret edene kadar veri kaynağından yoksundur

Gömülü BIFF8 grafik yolunda HotXLS seri referans kabulü: aynı çalışma kitabı içindeki Data!$B$2:$B$13 gibi A1 tarzı aralıklar sayfa listesine karşı çözümlenip grafik kayıtlarının ihtiyaç duyduğu external reference indeksine dönüşür; adlandırılmış aralıklar ve harici çalışma kitabı referansları ise sıfır uzunlukta parse edilmiş ifadeyle placeholdera düşer, ikisi de AddChartSheet kapsamında
Yalnızca aynı çalışma kitabı içindeki düz A1 tarzı aralıklar grafik serisi referanslarına derlenir; geri kalan her şey, yeniden işaret edilene kadar placeholder olarak temiz yazılır ve tam yol AddChartSheet üzerindedir

Nedeni, açık bir mühendislik takasıdır. Tam referans derleme yolu chart-sheet rotasında, çalışma sayfası koleksiyon katmanının içinde sarmalı olarak vardır ve onu temizce dışarı çıkarmak, pratikte nadir bir vaka için yüz satırlık çözümleme mantığını çoğaltmak demekti. Gömülü bir grafik neredeyse her zaman kendi sayfasındaki ya da kardeş bir veri sayfasındaki hücreleri çizer. Adlandırılmış ve harici referanslar chart-sheet yolunda AddChartSheet üzerinden karşılanır; hiçbir şey erişilemez değildir, yalnızca başka bir giriş noktasından ulaşılır

Seri modelindeki geri kalan her şey iki rotada da aynı çalışır. İkincil eksen bağlaması, seri başına çizgi, dolgu ve marker stilleri, trend çizgileri, hata çubukları ve veri etiketlerinin tümü TXLSChartSeriesInfo'nun parçasıdır ve aynı şekilde yazılır; böylece bir grafik tanımı, yalnızca çağrı değişerek gömülü nesne ile chart sheet arasında gezebilir. İkincil eksen bayrağının ardındaki axis-group mekaniği, BIFF yazımında ikincil eksen grupları makalesinde ele alınır

Grafik başlığı neden iki karakter okundu?

Çünkü bayt sayısı beklenen yere karakter sayısı geçilmiştir ve BIFF Unicode dizgeleri bu hatayı yazmayı kolay, görmeyi zor kılar. Kısa bir BIFF Unicode dizgesi bir karakter sayısı ve bir flags baytıyla başlar; flags baytı, yükün karakter başına bir bayt mı iki bayt mı olduğunu söyleyen high-byte bitini taşır. 16 bitlik yükü, karakter sayısını bayt uzunluğu sanarak okursanız dizgenin tam yarısını alırsınız: Sales adlı bir seri Sa olarak geri döner ve grafik başlığı da aynı şekilde kırpılır; çünkü başlıklar ile seri etiketleri aynı decode yolunu paylaşır

Bu kusuru dikkat çekici yapan şey, aynı kayıt ailesinde üç kez tekrar etmiş olmasıdır: bir kez trendline adlarında, bir kez pivot chart adlarında, bir kez de grafik başlıklarında. Her olay, yeni bir özellikte taze bir böcek gibi göründü. Üçü de aynı eksik çarpma işlemiydi. Sonunda konuyu kapatan kural mekaniktir ve yargısız uygulanmalıdır: bu dizgelerden birini okuduğunuzda önce high-byte bayrağına bakın ve tampona dokunmadan önce karakter sayısını yük genişliğiyle çarpın. Kayıt düzeyindeki ayrıntılar XLUnicodeString karakter sayıları ve high-byte bayrağının decode edilmesi makalesindedir

// Gömülü grafik, çizim katmanını imgeler ve şekillerle paylaşır; bu
// yüzden sayfadaki mevcut çizim korunur. AddChartObject, oluşturulan
// nesnenin indeksini döndürür
var
  ObjIndex: Integer;
begin
  ObjIndex := Sheet.AddChartObject(xlsChartTypeLine, 'Trend',
    'Week', 'Units', Series, 2, 8, 18, 16);
  if ObjIndex < 0 then
    raise Exception.Create('chart object was not created');
end;

Gömülü grafiklerin alternatiflere karşı konumu

Üç rota vardır ve farklı sorulara cevap verir. Gömülü bir grafik nesnesi, verisinin yanında, çalışma sayfası üzerinde durmaya aittir ve çoğu raporun istediği de budur. Chart sheet, tekli sunum görseline uyar ve tam referans derleme yolunu verir. Yüklü bir dosyadaki mevcut grafiği dokunulmadan korumak, çalışma kitabı kimsenin bir kütüphaneye yeniden yorumlatmak istemediği biçimlendirmeyle Excel'den gelmişse doğru cevaptır; o geçişli davranış korunan ChartML ve kombinasyon grafikleri makalesinde anlatılır

Gömülü grafik çizim katmanını kullandığı için aynı sayfadaki imgeler ve şekillerin yerine geçmez, onlarla bir arada yaşar; katmanın genel modeli HotXLS'te grafikler, imgeler ve çizimler makalesinde ele alınır. Üç rota da HotXLS Delphi spreadsheet bileşeni içinde gelir; seçim, kütüphanenin neyi ifade edebildiğiyle değil raporun nasıl görünmesi gerektiğiyle ilgilidir

Saklamaya değer olan metodolojik noktadır. Bir ikili format özelliğinin mevcut bir okuyucusu varken yazıcıyı spesifikasyonun kendi okumanıza değil, okuyucuya karşı kurun. Okuyucu, gerçek uygulamaların gerçekten ürettiği dosyalarla yıllarca teması kodlar; spesifikasyonun gevşek ifade ettiği kısımlar dahil. Onu tatmin eden bir yazıcı, Excel'i de tatmin etmeye çok daha yakındır