Delphi'den biçimlendirilmiş bir Excel raporu üretmenin güvenilir yolu, bir tasarımcının halihazırda oluşturduğu bir çalışma kitabından başlamaktır. Finans ekibinden biri faturayı Excel'de düzenler: logo, sütun başlıkları, ayrıntı bandındaki kenarlıklar, kalın yazılmış toplamlar satırı ve para birimi biçimleri. Kodunuz o dosyayı açar, canlı verileri tasarımcının bunun için ayırdığı hücrelere bırakır ve sonucu kaydeder. Görünüm onlara, sayılar ise size aittir. Excel'i çalıştırmadan XLS ve XLSX çalışma kitaplarını okuyan ve yazan yerel bir Delphi ve C++Builder kütüphanesi olan HotXLS, bu yaklaşımın ihtiyaç duyduğu üç işlemi size sunar: metnine göre bir hücreyi aramak, stilleri ve formülleri bozulmamış bir aralığı kopyalamak ve altındaki her şeyin verilerle birlikte aşağı kayması için satır eklemek
Şablon düzenlemelerinde ayakta kalan bir oluşturucu ile ilk düzenlemede bozulan bir oluşturucuyu ayıran tek kural, hücreleri asla doğrudan satır ve sütun numaralarıyla adreslememektir. Şablon, diğer insanların düzenlediği bir belgedir. Finans ekibi bir vergi satırı ekler, logo satırının yüksekliğini artırır, adres bloğunu yeniden sıralar ve dosya biçimi size hiç yardımcı olmaz: Satır 10'un hala geçen çeyrekte ifade ettiği şeyi ifade edip etmediğine bakılmaksızın bir BIFF veya OOXML kaydı başarıyla tamamlanır. İlk ayrıntı satırını sabit kodlu bir satır 10'a yazan bir oluşturucu, birisi ayrıntı bölümünün üzerine bir blok eklediğinde satır ögelerini yanlış hücrelerin üzerine basacak ve artık verileri kapsamayan bir toplamlar aralığını toplayacaktır. Hiçbir şey hata fırlatmaz, her kaydetme işlemi başarılı döner ve tek sinyal bir müşterinin yanlış faturayı fark etmesidir
Her koordinatı bir yer tutucu belirtece (token) sabitleyin
Çözüm, şablonun kendi koordinatlarını taşımasını sağlamaktır. Tasarımcı, oluşturucunun dokunması gereken hücrelere {{CUSTOMER}}, {{DATE}} ve {{DETAIL_START}} gibi belirteçler (tokens) yazar ve oluşturucu çalışırken her konumu bu belirteçleri bulduğu yere göre hesaplar. Düzen düzenlemeleri artık önemli değildir çünkü belirteç bulunduğu hücreyle birlikte hareket eder. Sözleşmenin ikinci yarısı ise başarısızlık kuralıdır: Gerekli bir belirteç eksikse, herhangi bir müşteri verisi dosyaya ulaşmadan önce iş durdurulur. Sapmış bir şablon, teslim edilmiş bir belge değil, başarısız bir iş bildirimi üretmelidir
Belirteçleri bulma: FindText ve ReplaceText
Her iki HotXLS sınıf ailesi de çalışma sayfası düzeyinde arama sunar. FindText, metni eşleşen ilk hücrenin satır ve sütununu döndürür ve büyük-küçük harf duyarlılığı ekleyen bir aşırı yüklemesi vardır. ReplaceText her oluşumu değiştirir ve kaç tanesini değiştirdiğini döndürür. İkisi, sahip olma eğiliminde olduğunuz iki tür belirteci kapsar: Bir kez bulup yanına yazdığınız müşteri adı gibi tek bir çıpa; rapor tarihi gibi tam olarak bir kez görünmesi gereken ve sayasını değiştirip kontrol ettiğiniz bir belirteç. XLSX tarafında, kendisini bu şekilde sabitleyen bir doldurma işlemi şuna benzer:
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
R, C: Integer;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open('invoice-template.xlsx') <> 1 then
raise Exception.Create('Cannot open invoice template');
Sheet := Book.Sheets[0]; // TXLSXSheets.Items is 0-based
if not Sheet.FindText('{{CUSTOMER}}', R, C) then
raise Exception.Create('Template drift: {{CUSTOMER}} anchor missing');
Sheet.Cells[R, C].Value := 'ACME Corp';
if Sheet.ReplaceText('{{DATE}}',
FormatDateTime('yyyy-mm-dd', Date)) = 0 then
raise Exception.Create('Template drift: {{DATE}} token missing');
// detail expansion and save follow below
finally
Book.Free;
end;
end;
İki ayrıntı önemlidir. İlk olarak, FindText ve ReplaceText bir hücrenin metin değerini eşleştirir; bir formül dizesinin içine gömülmüş bir belirteç onlar için görünmezdir, bu nedenle yer tutucu belirteçler düz hücrelerde olmalıdır, asla formüllerin içinde değil. İkinci olarak, değiştirme sayısı sizin sapma dedektörünüzdür. Tam olarak bir adet {{DATE}} belirteci içermesi gereken ancak sıfır değiştirme bildiren bir şablon düzenlenmiştir ve o anda bir istisna fırlatmak, sessiz düzen sapmasını görünür bir hataya dönüştüren şeydir
Stilleri veya formülleri kaybetmeden ayrıntı satırını kopyalama
Bir faturanın ayrıntı bölümü verilerle birlikte büyür. Değerleri doğrudan örnek satırın altındaki boş satırlara yazmak tasarımcının hazırladığı her şeyi; kenarlıklar, sayı biçimlerini ve satır başına formülleri çöpe atar. Tüm bunları koruyan kalıp, şablonda tam olarak biçimlendirilmiş bir örnek satır bırakmak ve bunu her bir öge için kopyalamaktır. CopyRange tek bir çağrıda stilleri ve formülleri çoğaltır, ardından oluşturucu yalnızca değer hücrelerinin üzerine yazar
const
DetailRow = 10; // the formatted sample row in the template
var
I: Integer;
begin
// Open space before the totals block first, so the SUM range
// below the detail band stretches together with the data.
if Length(Items) > 1 then
Sheet.InsertRows(DetailRow + 1, Length(Items) - 1);
for I := 0 to High(Items) do
begin
if I > 0 then // clone styles + formulas from the sample row
Sheet.CopyRange(DetailRow, 1, DetailRow, 5, DetailRow + I, 1);
Sheet.Cells[DetailRow + I, 1].Value := Items[I].Name;
Sheet.Cells[DetailRow + I, 2].Value := Items[I].Qty;
Sheet.Cells[DetailRow + I, 3].Value := Items[I].UnitPrice;
Sheet.Cells[DetailRow + I, 4].Formula :=
Format('B%d*C%d', [DetailRow + I, DetailRow + I]); // no '=' prefix
end;
end;
Formül atamasını yakından izleyin. XLSX Formula özelliği ifadeyi başında eşittir işareti olmadan alırken, XLS arayüzü Value aracılığıyla atanan '=B10*C10' ifadesini bekler. İki kuralı karıştırmak, sınıf aileleri arasında en yaygın taşıma hatasıdır ve şikayet etmeden başarısız olur: Hücre yalnızca Excel'in metin olarak gösterdiği bir sabit dizgeyi tutar. Şablon, ayrıntı bandını birleştirilmiş başlık satırlarıyla süslüyorsa, birleştirilmiş bir alanın yalnızca sol üst hücresinin bir değer taşıdığını unutmayın. Düzen odaklı rapor şablonlarında birleştirilmiş hücreler hakkındaki yardımcı makaledeki düzen kuralları, birleştirme bölgelerinin neden veri bandının tamamen dışında kalması gerektiğini açıklar
InsertRows neleri taşır ve neleri geride bırakır?
Toplamlar bloğunun önüne satır eklemek, ayrıntı bölümü büyüdükçe SUM aralığının genişlemesini sağlayan şeydir. XLSX tarafında, InsertRows hücrelerle birlikte uzun bir bağımlı yapılar listesini aşağı taşır: birleştirilmiş aralıklar, satır yükseklikleri, köprüler, yorumlar, dondurulmuş bölmeler, otomatik filtre aralıkları, koşullu biçimlendirmeler, veri doğrulamaları, tablolar, tanımlanmış adlar ve resim ile grafik çıpaları. Bu listede belleğe alınmaya değer bir sınır vardır: Formülün yeniden yazılması yalnızca aynı sayfa içindeki referanslara ulaşır. Özet sayfasındaki taşınan bölgeyi işaret eden bir formül eski koordinatlarını korur ve sessizce yanlış hücreleri okur; bu nedenle sayfalar arası çekilen toplamlar çalışma kitabı düzeyindeki adlarla daha güvenli ifade edilir. Tanımlanmış adlar ve sayfalar arası formüller hakkındaki yardımcı makale bu kalıbı ele almaktadır
Eski XLS biçimi sınırı daha zor bir yere çeker. HotXLS; pivot tabloları, sorgu tablolarını ve harici veri bağlantılarını BIFF dosyalarında ham bayt blokları olarak tutar. Değişmeden açılır ve kaydedilirler ancak modellenmezler, bu nedenle satır ekleme onlara asla dokunmaz. Genişleyen bir ayrıntı bloğunun altına bir pivot tablo yerleştiren bir şablon, pivot kaynak dikdörtgeni verilerin dışına taşarken hiçbir uyarı vermeden kaydedilir. Çözüm savunmacı değil yapısal olmaktır: Pivot ve sorgu içeriğini oluşturucunun asla satır eklemediği sayfalarda tutun; böylece bayatlama gerçekleşemez
Teslimattan önce yeniden hesaplayın veya neden atladığınızı bilin
HotXLS, SaveAs sırasında formülleri değerlendirmez. Bir kişi dosyayı açtığında Excel her şeyi yeniden hesaplar (bunu yönlendirmeniz gerekiyorsa XLS arayüzü CalculationMode ve RecalcOnSave sunar), bu nedenle bir insan gelen kutusuna yönelik bir raporun sizden daha fazlasına ihtiyacı yoktur. Çalışma kitabı başka bir programı beslediği anda durum değişir. CSV dışa aktarımı formülleri düz metin olarak yazar ve onları asla hesaplamaz; önbelleğe alınmış değerlere güvenen herhangi bir alt ayrıştırıcı bayat sayılar veya boşluklar okuyacaktır. Bu yollar için, yüklü çalışma kitabına karşı rastgele bir ifadeyi değerlendiren ve sonucu geri veren Calculate ile sunucuda hesaplama yapın:
var
Total: Variant;
LastDetail: Integer;
begin
LastDetail := DetailRow + Length(Items) - 1;
Total := Book.Calculate(Format('SUM(Invoice!D%d:D%d)',
[DetailRow, LastDetail]));
if (not VarIsNumeric(Total)) or
(Abs(Total - ExpectedTotal) > 0.005) then
raise Exception.Create('Invoice total does not match the order record');
if Book.SaveAs('invoice-2026-0611.xlsx') <> 1 then
raise Exception.Create('Save failed: check output path and permissions');
end;
Kaydetmeden önce hesaplanan toplamı sipariş kaydına karşı kontrol etmek, iyi bir getirisi olan ucuz bir sigortadır. Yanlış bir faturayı başarısız bir işe dönüştürür. Bir operatör başarısız bir işi saniyeler içinde yeniden deneyebilir; müşterinin gelen kutusuna gitmiş yanlış bir fatura ise bir müşteri temsilcisine bir özüre ve düzeltmeye mal olur
İki sınıf ailesi, tek algoritma
Aynı mantık biçimler arasında taşınabilir ancak aynı kod taşınamaz. Eski .xls için TXLSWorkbook arayüz tabanlıdır, referans sayımlıdır, 1 tabanlı sayfa dizinine sahiptir ve asla elle serbest bırakılmaz (free). .xlsx için TXLSXWorkbook, yukarıda gösterilen formül kuralı ve 0 tabanlı sayfa dizini ile bir try..finally bloğu içinde serbest bırakmanız gereken düz bir nesnedir. FindText, ReplaceText, CopyRange ve InsertRows her iki tarafta da mevcuttur, bu nedenle sabitleme-kopyalama-yeniden hesaplama yapısı temiz bir şekilde taşınır. Pratik tavsiye, süreç hattı (pipeline) başına tek bir biçime bağlı kalmak veya oluşturucu boyunca farkı dağıtmak yerine iki nesne yaşam döngüsünü kendi ince bir adaptörünüzün arkasına gizlemektir
Bu kalıbın ürettiği rapor türü için boyut nadiren önemlidir. Biçimlendirilmiş bir satırı birkaç bin kez kopyalamak mevcut donanımlar için hiçbir şey değildir. Kaydetme yolu yalnızca bir ayrıntı bandı altı haneli satırlara ulaştığında darboğaz haline gelir ve bu noktada StreamingWrite ayarını yapmak, çalışma sayfası XML'ini arabelleğe almak yerine doğrudan çıktı paketine gönderir; sunucu toplu işleri için akışlı yazmalar hakkındaki makale bu ödünün ne zaman yapılmasına değer olduğunu kapsar. Grafikler de düzenin geri kalanı gibi davranır: XLSX tarafında, InsertRows üzerlerinde çalıştığında hem grafik çıpası hem de serisi referansları hareket eder, böylece toplamlar satırının altındaki bir grafik doğru verilere bağlı kalır; XLS tarafında ise grafikler kendi grafik sayfalarında bulunur ve pivot tablolar gibi asla kaymaz. Bu, sunum sayfalarını oluşturucunun genişlettiği sayfadan uzak tutmak için bir başka nedendir
Bu sabitleme-kopyalama-yeniden hesaplama yaklaşımı, kodunuz ne söylediğine sahip olurken bir tasarımcının çalışma kitabının nasıl göründüğüne sahip olmasına izin verir ki bu da genellikle oluşturulan Excel çıktısını korumaya değer kılan şeydir. Burada gösterilen arama, kopyalama ve ekleme çağrıları, teslimat öncesi toplam kontrolü için kullanılan formül motoruyla birlikte Delphi ve C++Builder için HotXLS Bileşeni ile birlikte gönderilmektedir