Járja be egy frissen megnyitott jelentéssablon celláit, és egy egyesített cím úgy viselkedik, mint egy szivárgás. Kiolvassa az A1 cellát, és megkapja a „Quarterly Statement” szöveget; kiolvassa a B1 és F1 közötti cellákat, amelyek láthatóan ugyanazon szalagcím alatt ülnek, és semmit nem kap. Írjon értéket a C1 cellába a fejléc javításához, és soha nem jelenik meg a képernyőn. A rács nem veszítette el az adatait. Pontosan azt teszi, amit az egyesítés jelent: XLS-ben és XLSX-ben egyaránt az egyesített téglalap egyetlen cella, a bal felső horgony tartalmát jeleníti meg, a többit pedig lefedett területként kezeli, amely értékeket tart, de sosem mutat. Az Excel felhasználói ezt próbálgatással szívják magukba. Egy jelentésgenerátornak szabályként kell kódolnia, mert előállított kódban a tünet üres terület, amelyhez semmilyen kivétel nem vezet vissza. A HotXLS, az a natív Object Pascal könyvtár, amely mindkét Excel formátumot olvassa és írja Delphiből és C++Builderből, elég kifejezetten teszi láthatóvá az egyesítési táblát ahhoz, hogy a szabály ellen programozhasson ahelyett, hogy egy támogatási jegyben fedezné fel újra
Egy érték, egy horgony
Az egyesítés megjelenítési utasítás egy olyan rács fölött, amely nem változtat alakot. Minden lefedett cella továbbra is saját rekeszként létezik a fájlban; az egyesítési rekord csak annyit mond a fogyasztónak, hogy a horgony tartalmát fesse végig a téglalapon. Ez a különbség három olyan viselkedést hajt, amelyet érdemes elraktározni, mielőtt bármilyen elrendezéskódot ír. Egy lefedett cella olvasása a saját tárolt értékét adja vissza, ami egy Ön által épített szalagcímnél rendszerint üres, ezért minden olyan kódnak, amely egyesített címet vizsgál, fel kell oldania és a horgonyt kell olvasnia. A lefedett cellába írás fájlszinten sikerül, és sehol nem jelenik meg, ez a nyitóbekezdés láthatatlan fejléces csapdája. Az egyesítés feloldása pedig kitakarja mindazt, ami végig alatta ült, így egy lefedett területre írt elkóborolt érték látható hibává válik azon a napon, amikor valaki felbontja az egyesítést
Az XLSX oldalon ez a tábla elsőrendű objektum. A Sheet.MergedCells hordozza az Add('A1:C1'), FindAt(Row, Col), DeleteAt és Items tagokat, és az a hívás, amelyhez a leggyakrabban nyúl, a FindAt: adjon át neki bármely koordinátát, és visszaadja az adott cellát lefedő egyesített területet, vagy nil értéket, ha a cella egyedül áll. Ez az egyetlen keresés a helyes egyesítéskezelés mindkét felének alapja, a biztonságos olvasásé és az írásőré, és mindkettő felbukkan később
Két homlokzat, két egyesítési szokás
A HotXLS külön objektummodellként tartja a klasszikus BIFF8 .xls motort és az OOXML .xlsx motort, és az egyesítést eltérően írják le, mert más egyezményekből származnak. Az XLS homlokzat az Excel COM szokását követi: kivesz egy tartományt egy kétargumentumos indexelt tulajdonságból, és meghívja rajta a Merge metódust egy OleVariant értékkel, amelynek értéke dönti el, milyen geometriát kap
var
Book: IXLSWorkbook; // felületszámlált: nincs kézi Free
Sh: IXLSWorksheet;
begin
Book := TXLSWorkbook.Create;
Sh := Book.Sheets[1]; // az XLS lapgyűjtemény 1-alapú
Sh.Range['A1', 'F1'].Merge(False); // False = egyetlen egyesített blokk
Sh.Cells.Item[1, 1].Value := 'Quarterly Statement';
Sh.Range['A3', 'F4'].Merge(True); // True = egyesítés vízszintesen: soronként egy
Book.SaveAs('layout.xls');
end;
A Merge argumentuma az, amit az emberek elrontanak. Kétsoros tartományon a Merge(True) két független, egysoros egyesítést állít elő, ez az Excel „Cellák egyesítése vízszintesen” parancsa, és pontosan ez kell egy olyan halmozott fejlécsávhoz, amelynek sorai szétválaszthatók maradnak. A Merge(False) az egész téglalapot egyetlen blokká olvasztja. A tartomány állapotjelzőként közli a MergeCells értékét is, a MergeArea tagon át adja vissza az őt tartalmazó területet, és az Unmerge hívással bontja fel magát. Az XLSX homlokzat ugyanezeket a műveleteket más néven teszi elérhetővé: a Sheet.MergeCells(Row1, Col1, Row2, Col2) egész számú határokat vár, a TXLSXRange.Merge elfogadja az ezzel egyenértékű Across változatot, az eredményt pedig a MergedCells gyűjtemény tartja
Sablon, amely az adataival együtt nő
Egy valódi jelentéssablon nem rögzített rács. A fejléc és az összegek rögzítettek, a köztük lévő részletező szakasz viszont addig nyúlik, ameddig a lekérdezés eredménye ér. Az a minta, amely megállja a helyét, egyetlen teljesen stílusozott részletsort tart a sablonban, rekordonként egyszer klónozza, majd rést nyit az összegblokk előtt, hogy minden alatta horgonyzott elem lecsússzon a formázása elvesztése nélkül
Sheet.Range['A1:F1'].Merge;
Sheet.Cells[1, 1].Value := 'INVOICE #2026-0611'; // az érték a horgonyba, az A1 cellába megy
Sheet.RowHeight[1] := 28;
TitleFont := Book.Fonts.Add('Calibri', 16, True, False);
Sheet.Cells[1, 1].FontIndex := TitleFont + 1; // a készletindex 0-alapú, a cellaoldal 1-alapú
// az 5. sor a stílusozott részletsablon sora
for I := 0 to ItemCount - 1 do
Sheet.CopyRange(5, 1, 5, 6, 6 + I, 1); // a stílusok és képletek vele utaznak
// rés nyitása az összegblokk fölött; az alatta lévő tartalom lecsúszik
Sheet.InsertRows(6 + ItemCount, 1);
Sheet.Range['A1:F1'].SetBorders(xlsxEdgeOutline, xlsxBorderMedium);
Két sor megéri a második pillantást. A betűtípus-hozzárendelés olyan eggyel elcsúszást hordoz, amely némán harap: a Fonts.Add 0-alapú készletpozíciót ad vissza, míg a cella 1-alapú betűtípus-hivatkozást tárol, ahol a 0 az alapértelmezett betűtípust jelenti, így a + 1 elhagyása semmit nem vált ki, csak rossz betűtípussal formázza a címét. A másik sor a CopyRange, amely az értékek mellett a formázást és a képleteket is viszi. Ez az egész oka annak, hogy egy kézzel épített sablonsort klónozzon ahelyett, hogy kódból építené újra a kinézetét. A megjelenést egyszer, a sablonban birtokolja egy tervező; a generátor csak adatot tölt annak másolataiba
Ez a szétválasztás tovább skálázódik, amikor az újrahasznosítható elrendezés a saját munkafüzetében él, mondjuk egy jelentések között megosztott fejléc- és láblécsávokat tartalmazó lapon. A CopyRangeTo ugyanezt a klónozást végzi munkalapok határain át, célként lapot és rendeltetési koordinátákat véve, így a generátor egyetlen érintetlen sablonlapot tarthat, és annak területeit annyi kimeneti lapra bélyegezheti, amennyire a feladatnak szüksége van. Az alternatíva, vagyis a sablon helyben módosítása és utólagos visszaállítási kísérlete, az a fajta megoldás, amely addig működik, amíg egy futás félúton meg nem szakad
Mit mozgat az InsertRows, és mit nem
A sablonnövesztő minta csak azért működik, mert az XLSX InsertRows szerkezeti szerkesztés, nem cellakeverés. Amikor rést nyit, a beszúrási pont alatt ülő egyesített területeket, sormagasságokat, hiperhivatkozásokat, megjegyzéseket, rögzített ablaktáblákat, autoszűrő-tartományokat, feltételes formátumokat, adatérvényesítéseket, táblázatokat, definiált neveket, képhorgonyokat és diagramhorgonyokat is áthelyezi, nem csak a cellaértékeket. Ez az, ami miatt az összegblokk ép egyesítésekkel és számformátumokkal érkezik meg az új sorába, nem pedig lecsupaszítva
A két dokumentált korlátja az, amely köré tervezni kell. A képletigazítás a szerkesztett lapra szűkül: az azon a lapon belüli hivatkozások átíródnak, és egy másik lapon lévő, az eltolt területre mutató képlet is átíródik, de az igazítás csak azokat a hivatkozásokat követi, amelyek a szerkesztett lapra irányulnak, ezért minden munkafüzeteken átnyúló hivatkozási séma vak bizalom helyett saját ellenőrzést érdemel. A második korlát élesebb, és az XLS oldalon van. A kimutatások megnyitás-mentés ciklusokat nyers, megőrzött rekordokként élnek túl, nem olyan modellezett objektumokként, amelyeket a HotXLS mozgatni tud, ezért a sorbeszúrás nem helyezi át a kimutatás területét. Minden .xls formátumra épített sablon jó messze parkolja a kimutatási területeit bármely növekvő sávtól
Az adatok elrendezési területre írásának megtagadása
Az az egyesített cellás hiba, amely valóban eléri az éles üzemet, nem a kozmetikai. Szerkezeti: egy részletsor egyesített elrendezési sávba sodródik, az értékei lefedett cellákba érkeznek és láthatatlanná válnak, az oszlopösszegek pedig csendben megszűnnek egyezni azzal, amit a lapot olvasó bárki lát. Mivel a FindAt bármely koordinátára megválaszolja a lefedő terület kérdését, a generátor abban a pillanatban megtagadhatja az írást, amikor az megtörténne, ahelyett hogy csendben alulszámoló jelentést szállítana
// a részletadatok egyesített elrendezési területre írásának megtagadása
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;
Ugyanez a határellenőrzés mindenhová való, ahol a felhasználó később rendezni vagy szűrni fogja a kimenetet. Az a tartomány, amelyben egyesítések vannak, nem rendezhető tisztán, mert a rendezés egymástól függetlenül mozgatja a sorokat, egy sorokon átnyúló egyesítésnek pedig nincs egyetlen sora, amellyel utazhatna; az Excel hibával vagy összekuszált elrendezéssel válaszol. Az a fegyelem, amely helyesen tartja a jelentéseket, földrajzi. Az egyesítéseket szorítsa címsávokba, szakaszelválasztókba és aláírásblokkokba, a lap táblázatos közepét pedig tartsa laposan. A sablonalapú jelentéskészítésről szóló cikk ezt az elrendezés kontra adat szétválasztást teljes, helyőrzővezérelt munkafolyamattá fejleszti, a feltételes formázásról és a rich textről szóló cikk pedig ennek a lapos adatsávnak a stílusozását tárgyalja
Hogyan romlanak le az egyesítések kifelé menet
Az egyesítés munkafüzet-fogalom, és minden szövegorientált exportformátum más mértékben tiszteli. A három viselkedés előzetes ismerete megspórol egy tesztelési kört. A HTML export hűen adja vissza az egyesítéseket, colspan és rowspan attribútumokat bocsát ki egyetlen táblázaton, így a böngészőnek szánt jelentés megtartja sávos kinézetét. Az RTF export egyáltalán nem nyújt át oszlopokat: a horgony szövege a saját cellájába kerül, az egyesítés maradék szélessége pedig üres cellákként jön ki, amitől egy széles cím szövegszerkesztőben vizuálisan balra tolódik. A CSV nem ismeri az egyesítés fogalmát, ezért a horgony értéke egy mezőt foglal el, minden lefedett cella pedig üres mezőként kerül ki. A tanulság egy olyan munkafüzethez, amely tagolt exportokat is táplál, az, hogy tartson mindent, ami teherhordó, az egyesített geometrián kívül; a CSV, TSV és HTML exportról szóló cikk részletesen végigveszi az egyes formátumokat
Egy megnyugtató megjegyzés annak, aki ezt a fájlmérettel veti össze: az egyesítések jelentésmérteken szinte semmibe nem kerülnek. Az egyesítési tábla parányi a cellaadatok mellett, egy lefedett cella olvasása pedig továbbra is a FindAt hívásán át megy, nem végigpásztázással. A nagy munkafüzetekre nehezedő teljesítménynyomás máshonnan jön, főként a stíluskészlet növekedéséből és abból a memóriából, amelyet a mentési útvonal tart, ezt pedig a nagy munkafüzetek teljesítményéről szóló cikk veszi elő közvetlenül. Mindkét egyesítési API, a szerkezeti szerkesztési műveletek és a sablonbemutatók a HotXLS Delphi Component csomaggal érkeznek