Teknik Makale

Delphi'de HotXLS Birleştirilmiş Hücreler ve Rapor Şablon Düzeni

Yeni açılmış bir rapor şablonunun hücrelerini dolaştığınızda (iterate), birleştirilmiş bir başlık sızıntı gibi davranır. A1'i okursunuz ve "Quarterly Statement" elde edersiniz; gözle görülür şekilde aynı başlık altında yer alan B1 ila F1'i okursunuz ve hiçbir şey elde edemezsiniz. Başlığı yamamak için C1'e bir değer yazarsınız ve bu ekranda asla görünmez. Izgara verilerinizi kaybetmedi. Tam olarak bir birleştirmenin (merge) ne anlama geldiğini yapıyor: Hem XLS hem de XLSX'te, birleştirilmiş bir dikdörtgen tek bir hücrenin, yani sol üst çıpanın (anchor) içeriğini işler ve geri kalanını değerleri tutan ancak asla göstermeyen kapalı alan olarak ele alır. Excel kullanıcıları bunu deneme yanılma yoluyla öğrenir. Bir rapor oluşturucu bunu bir kural olarak kodlamalıdır, çünkü oluşturulan kodda belirti, izini sürecek hiçbir istisna (exception) içermeyen boş bir bölgedir. Hem Excel biçimlerini Delphi ve C++Builder'dan okuyan hem de yazan yerel bir Object Pascal kütüphanesi olan HotXLS, birleştirme tablosunu, bir destek biletinde yeniden keşfetmek yerine kurala karşı programlama yapabileceğiniz kadar açık bir şekilde ortaya koyar

Tek değer, tek çıpa

Birleştirme, şekil değiştirmeyen bir ızgaranın üzerine katmanlanmış bir görüntüleme talimatıdır. Kapsanan her hücre, dosyada kendi yuvası olarak var olmaya devam eder; birleştirme kaydı yalnızca bir tüketiciye çıpanın içeriğini dikdörtgen boyunca boyamasını söyler. Bu ayrım, herhangi bir düzen kodu yazmadan önce içselleştirmeye değer üç davranışı tetikler: Kapsanan bir hücreyi okumak, kendi saklanan değerini döndürür; bu, oluşturduğunuz bir başlık için genellikle boştur, bu nedenle birleştirilmiş bir başlığı inceleyen herhangi bir kodun çıpayı çözümlemesi ve okuması gerekir. Kapsanan bir hücreyi okumak, kendi saklanan değerini döndürür; bu, oluşturduğunuz bir başlık için genellikle boştur, bu nedenle birleştirilmiş bir başlığı inceleyen herhangi bir kodun çıpayı çözümlemesi ve okuması gerekir. Kapsanan bir hücreye yazmak dosya düzeyinde başarılı olur ve hiçbir yerde görünmez; bu, başlangıçtaki görünmez başlık tuzağıdır. Ve bir bölgenin birleştirmesini çözmek, tüm bu süre boyunca altında ne oturuyorsa onu ortaya çıkarır, dolayısıyla kapalı alana yazılan başıboş bir değer, birisinin birleştirmeyi çözdüğü gün görünür bir kusura dönüşür

İki cephe, iki birleştirme deyimi

XLSX tarafında bu tablo birinci sınıf bir nesnedir. Sheet.MergedCells; Add('A1:C1'), FindAt(Row, Col), DeleteAt ve Items özelliklerini taşır ve en çok kullandığınız çağrı FindAt'tir: Ona herhangi bir koordinat verin ve o hücreyi kapsayan birleştirilmiş bölgeyi veya hücre tek başına duruyorsa nil döndürür. Bu tek arama, doğru birleştirme yönetiminin her iki yarısının da (güvenli okuma ve yazma koruması) temelidir ve her ikisi de daha sonra gösterilecektir

HotXLS, klasik BIFF8 .xls motorunu ve OOXML .xlsx motorunu ayrı nesne modelleri olarak tutar ve farklı kurallardan türedikleri için birleştirmeyi farklı şekilde ifade ederler. XLS arayüzü Excel COM deyimini takip eder: İki bağımsız değişkenli dizinli bir özellikten bir aralık alır ve değeri elde edeceğiniz geometriye karar veren bir OleVariant ile Merge çağrısı yaparsınız

var
  Book: IXLSWorkbook;   // interface-counted: no manual Free
  Sh: IXLSWorksheet;
begin
  Book := TXLSWorkbook.Create;
  Sh := Book.Sheets[1];                 // XLS sheet collection is 1-based
  Sh.Range['A1', 'F1'].Merge(False);    // False = one merged block
  Sh.Cells.Item[1, 1].Value := 'Quarterly Statement';
  Sh.Range['A3', 'F4'].Merge(True);     // True = merge across: one merge per row
  Book.SaveAs('layout.xls');
end;

Merge işlevinin bağımsız değişkeni insanların hata yaptığı kısımdır. İki satırlık bir aralıkta, Merge(True) iki bağımsız tek satırlık birleştirme üretir; bu Excel'in "Merge Across" (Boyunca Birleştir) özelliğidir ve satırlarının ayrılabilir kalması gereken yığılmış bir başlık bandı için tam olarak istediğiniz şeydir. Merge(False) tüm dikdörtgeni tek bir blokta birleştirir. Aralık ayrıca bir durum bayrağı olarak MergeCells değerini bildirir, içeren bölgeyi MergeArea aracılığıyla döndürür och Unmerge ile kendini çözer. XLSX arayüzü aynı işlemleri farklı adlar altında sunar: Sheet.MergeCells(Row1, Col1, Row2, Col2) tamsayı sınırları alır, TXLSXRange.Merge eşdeğer Across varyantını kabul eder ve MergedCells koleksiyonu sonucu tutar

Verileriyle birlikte büyüyen bir şablon

Gerçek bir rapor şablonu sabit bir ızgara değildir. Başlık ve toplamlar sabittir ancak aralarındaki ayrıntı bölümü sorgunun döndürdüğü şeye göre genişler. Ayakta kalan kalıp, şablonda tam olarak biçimlendirilmiş bir ayrıntı satırı tutar, bunu kayıt başına bir kez kopyalar ve ardından toplamlar bloğunun önüne bir boşluk açar, böylece aşağıda sabitlenen her şey biçimlendirmesini kaybetmeden aşağı kayar

Sheet.Range['A1:F1'].Merge;
Sheet.Cells[1, 1].Value := 'INVOICE #2026-0611'; // değer çıpa olan A1'e gider
Sheet.RowHeight[1] := 28;
TitleFont := Book.Fonts.Add('Calibri', 16, True, False);
Sheet.Cells[1, 1].FontIndex := TitleFont + 1; // havuz dizini 0 tabanlı, hücre tarafı 1 tabanlı
// satır 5 biçimlendirilmiş ayrıntı şablon satırıdır
for I := 0 to ItemCount - 1 do
  Sheet.CopyRange(5, 1, 5, 6, 6 + I, 1); // stiller ve formüller onunla seyahat eder
// toplamlar bloğunun üstünde bir boşluk açar; altındaki içerik aşağı kayar
Sheet.InsertRows(6 + ItemCount, 1);
Sheet.Range['A1:F1'].SetBorders(xlsxEdgeOutline, xlsxBorderMedium);

İki satır ikinci bir bakışı hak ediyor. Yazı tipi ataması sessizce ısıran bir indeks kayması hatası taşır: Fonts.Add 0 tabanlı bir havuz konumu döndürürken, bir hücre 0'ın varsayılan yazı tipi anlamına geldiği 1 tabanlı bir yazı tipi referansı saklar, bu nedenle + 1'i düşürmek hiçbir şey fırlatmaz, sadece başlığınızı yanlış yazı tipiyle biçimlendirir. Diğer satır ise biçimlendirmeyi ve formülleri değerlerle birlikte hareket ettiren CopyRange'dir. Kodda görünümü yeniden oluşturmak yerine elle oluşturulmuş bir şablon satırını kopyalamanın tüm nedeni budur. Bir tasarımcı görünüme bir kez şablonda sahip olur; oluşturucu ise yalnızca verileri kopyalarına döker

Yeniden kullanılabilir düzen kendi çalışma kitabında yer aldığında, örneğin raporlar arasında paylaşılan bir üstbilgi ve altbilgi bandı sayfasında, bu ayrım daha da ölçeklenir. CopyRangeTo, hedef sayfa artı hedef koordinatları alarak çalışma sayfası sınırları boyunca aynı kopyalamayı gerçekleştirir, böylece bir oluşturucu el değmemiş bir şablon sayfasını saklayabilir ve bölgelerini bir işin ihtiyaç duyduğu kadar çok çıktı sayfasına basabilir. Alternatif olarak, şablonu yerinde değiştirmek ve sonrasında geri yüklemeye çalışmak, bir çalışmanın yarıda kesildiği güne kadar işe yarayan türden bir şeydir

InsertRows neleri taşır ve neleri taşımaz?

Şablonu büyütme kalıbı yalnızca XLSX InsertRows'un hücre karıştırmasından ziyade yapısal bir düzenleme olması nedeniyle çalışır. Bir boşluk açtığında, yalnızca hücre değerlerini değil, ekleme noktasının altında yer alan birleştirilmiş bölgeleri, satır yüksekliklerini, köprüler, yorumları, dondurulmuş bölmeleri, otomatik filtre aralıklarını, koşullu biçimlendirmeleri, veri doğrulamalarını, tabloları, tanımlanmış adları, resim çıpalarını ve grafik çıpalarını da yeniden konumlandırır. Toplamlar bloğunun, soyulmuş olarak gelmek yerine birleştirmeleri ve sayı biçimleri bozulmadan yeni satırına ulaşmasını sağlayan şey budur

Belgelenmiş iki sınırı, etrafında tasarım yapılması gereken sınırlardır. Formül ayarlaması düzenlenen sayfa ile sınırlıdır: o sayfa içindeki referanslar yeniden yazılır ve başka bir sayfadaki kaydırılan alana başvuran bir formül de yeniden yazılır, ancak ayarlama yalnızca düzenlenen sayfayı hedefleyen referansları takip eder, bu nedenle sayfalar arası herhangi bir referans şeması körülüğe güvenmek yerine kendi denetimini hak eder. İkinci sınır daha keskindir ve XLS tarafındadır. Pivot tablolar, HotXLS'in hareket ettirebileceği modellenmiş nesneler olarak değil, ham korunmuş kayıtlar olarak açma-kaydetme döngülerinden sağ çıkar, bu nedenle satır eklemek bir pivotun kapladığı alanı yeniden konumlandırmaz. .xls biçimi için oluşturduğunuz herhangi bir şablon, pivot bölgelerini büyüyen herhangi bir bandın uzağına park etmelidir

Düzen alanına veri yazmayı reddetme

Aslında üretime ulaşan birleştirilmiş hücre hatası kozmetik olan değildir. Yapısaldır: Ayrıntı satırı birleştirilmiş bir düzen bandına kayar, değerleri kapalı hücrelere düşer ve görünmez hale gelir ve sütun toplamları sessizce sayfayı okuyan herkesin görebileceği şeyle eşleşmeyi durdurur. FindAt herhangi bir koordinat için kapsama alanı sorusuna yanıt verdiğinden, oluşturucu sessizce eksik sayan bir rapor göndermek yerine bu yazmayı tam gerçekleşeceği anda reddedebilir:

// birleştirilmiş bir düzen bölgesine ayrıntı verisi yazmayı reddeder
if Sheet.MergedCells.FindAt(Row, 1) <> nil then
  raise Exception.CreateFmt('row %d overlaps a merged layout region', [Row]);
Sheet.Cells[Row, 1].Value := Detail.Description;

Aynı sınır kontrolü, bir kullanıcının daha sonra çıktıyı sıralayacağı veya filtreleyeceği her yerde geçerlidir. İçinde birleştirmeler bulunan bir aralık temiz bir şekilde sıralanamaz, çünkü sıralama satırları bağımsız olarak hareket ettirir ve satırları kapsayan bir birleştirmenin birlikte hareket edeceği tek bir satırı yoktur; Excel bir hata veya karmakarışık bir düzenle yanıt verir. Raporları doğru tutan disiplin coğrafidir: Birleştirmeleri başlık bantları, bölüm ayırıcıları ve imza bloklarıyla sınırlayın ve sayfanın tablolu ortasını düz tutun. Şablon rapor oluşturma makalesi bu düzen-veri ayrımını yer tutucu güdümlü tam bir iş akışına dönüştürür ve koşullu biçimlendirme ve zengin metin makalesi bu düz veri bandının biçimlendirilmesini kapsar

Birleştirmelerin dışa aktarım sırasında nasıl bozulduğu

Birleştirme bir çalışma kitabı kavramıdır ve metin odaklı her dışa aktarım biçimi buna farklı derecelerde uyar. Üç davranışı önceden bilmek bir QA döngüsünü kurtarır: HTML dışa aktarımı, tek bir tabloda colspan ve rowspan yayınlayarak birleştirmeleri aslına sadık kalarak yeniden üretir, böylece tarayıcıya yönelik bir rapor bantlı görünümünü korur. RTF dışa aktarımı sütunları hiç yaymaz: Çıpa metni kendi hücresine düşer ve birleştirmenin geri kalan genişliği boş hücreler olarak çıkar, bu altında geniş bir başlığı kelime işlemcide görsel olarak sola itilmiş olarak bırakır. CSV'nin birleştirme kavramı yoktur, bu nedenle çıpa değeri tek bir alanı kaplar ve kapsanan her hücre boş bir alan olarak yayınlanır. Sınırlı dışa aktarımları da besleyen bir çalışma kitabı için çıkarılacak ders, yük taşıyan her şeyi birleştirilmiş geometrinin dışında tutmaktır; CSV, TSV ve HTML dışa aktarma makalesi her biçimi ayrıntılı olarak inceler

Bunu dosya boyutuna göre tartan herkes için bir güvence: Birleştirmeler rapor ölçeğinde neredeyse hiçbir maliyet getirmez. Birleştirme tablosu hücre verilerinin yanında küçüktür ve kapsanan bir hücreyi okumak tarama yapmak yerine hala FindAt'ten geçer. Büyük çalışma kitaplarındaki performans baskısı başka yerlerden gelir; esas olarak stil havuzu büyümesi ve kaydetme yolunun tuttuğu bellekten gelir ki bu konu büyük çalışma kitabı performansı makalesinde doğrudan ele alınmıştır. Her iki birleştirme API'si, yapısal düzenleme işlemleri ve şablon demoları HotXLS Bileşeni ile birlikte gönderilmektedir