Egy táblázat kétféle azonosságot hordoz. Ott van a cellák rácsa, és ott van a mellette utazó dokumentum-metaadat: cím, szerző, cég, kulcsszavak, időbélyegek. Az Excel ezt a második réteget soha nem mutatja meg a rácsban, mégis ez az a réteg, amelyet a Windows Search indexel, amelyből a SharePoint a dokumentum címét veszi, és amely szerint egy iratkezelő rendszer iktat. Amikor egy generált munkafüzet a Szerző és a Cím mezőt attól a sablontól örökli, amelyből készült, minden downstream rendszer a sablon tervezőjét jegyzi fel négyezer ügyfélkivonat szerzőjeként. A metaadat sehol nem helyes, és mindenütt megnézik
A HotXLS ezt a réteget mindkét motorjában közönséges munkafüzetszintű tulajdonságokként teszi elérhetővé: a BIFF-homlokzatban az .xls, az OOXML-homlokzatban az .xlsx fájlokhoz. Egy fájl megnyitása után kiolvassa a mezőt, mentés előtt pedig kiírja. Azt, hogy az érték melyik fizikai konténerbe kerül, a könyvtár dönti el. Amit érdemes megérteni, mielőtt generátort ír: melyik mezőt támogatja ténylegesen az egyes formátumok, hol élnek fizikailag ezek a mezők, és mi az az egyetlen kapuszabály, amely eldönti, hogy egy .xlsx egyáltalán rögzít-e metaadatot
Két formátum, két tárolási modell
Azért van szüksége egy táblázatkezelő könyvtárnak két metaadat-megvalósításra – és azért bélyegzik a félkész eszközök helyesen az egyik formátumot, miközben a másikról megfeledkeznek –, mert az .xls és az .xlsx egymással össze nem függő helyeken tartja a tulajdonságait. A BIFF-munkafüzet OLE összetett fájl streamjeibe írja őket, elsősorban abba a SummaryInformation tulajdonságkészletbe, amely magát az Excelt is megelőzi, továbbá a streamen belüli WRITEACCESS rekordba, amely megnevezi, ki mentette utoljára a fájlt. Az OOXML-munkafüzet XML-részekként tartja őket a zip csomagon belül, rendeltetés szerint szétosztva: a docProps/core.xml hordozza a Dublin Core mezőket (cím, létrehozó, tárgy, kulcsszavak, dátumok), a docProps/app.xml pedig az alkalmazásszintű mezőket, például a céget és az előállító alkalmazást, az ECMA-376 Part 1 szerint
A HotXLS mindkét tárolási modellt a munkafüzet-objektum közvetlen tulajdonságaivá lapítja. Soha nem nyit meg tulajdonságkészlet-streamet, és nem szerkeszt kézzel XML-részt. Sztringeket és dátumokat rendel a munkafüzethez, a megfelelő konténer pedig magától megjelenik ahhoz a formátumhoz, amelyben ment
Generált munkafüzetek bélyegzése az üzleti adatrekordból
Az XLSX oldalon a TXLSXWorkbook sztringként teszi elérhetővé a Title, Subject, Author, Keywords, Description, Category, LastModifiedBy, Company, Application és AppVersion mezőket, ezenfelül a Created és Modified mezőket TDateTime értékként, ahol a nulla a beállítatlan állapotot jelenti. Az a szabály, amely bezárja az öröklési rést, egyetlen mondat: minden futáskor rendeljen értéket minden mezőhöz, az értékeket az üzleti adatrekordból véve, ahelyett hogy megbízna abban, amit a sablon éppen hordozott
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open('statement-template.xlsx') <> 1 then
raise Exception.Create('Template not available');
// Írjon felül minden mezőt: amit érintetlenül hagy, azt
// a sablon tervezőjétől örökli a fájl.
Book.Title := 'Account Statement 2026-06 / ACME Corp';
Book.Subject := 'Monthly account statement';
Book.Author := 'Billing Service 4.2';
Book.LastModifiedBy := 'Billing Service 4.2';
Book.Company := 'Northwind Financial';
Book.Category := 'Customer Delivery';
Book.Keywords := 'statement;billing;2026-06;acct-10024';
Book.Description := 'Generated document - manual edits are not retained';
Book.Created := Now;
Book.Modified := Now;
Book.SaveAs('statement-10024.xlsx');
finally
Book.Free;
end;
end;
A Keywords mező több gondolkodást hoz vissza, mint amennyit általában kap. A keresési infrastruktúra szó szerint indexeli – a Windows Search, a SharePoint és a legtöbb DMS-termék egyaránt –, így egy pontosvesszővel tagolt konvenció, amely a számlaszámot és az időszakot hordozza, minden kiszállított munkafüzetet megtalálható irattá tesz, adatbázis-fordulós lekérdezés nélkül. Ugyanez a hatótáv a bökkenő is. A tulajdonságok a fájl minden példányával együtt utaznak, jóval az azokat kiíró rendszer hozzáférés-vezérlésén túl, ezért személyes adatnak nincs helye bennük
Az időbélyegpár olyan jelentést hordoz, amelyet érdemes szabályzatban rögzíteni, nem a megszokásra bízni. A Created mezőnek azt a pillanatot kell jelölnie, amikor a folyamat előállította a dokumentumot, és utána befagyva maradnia. A Modified az a mező, amelyet az Excel frissít, valahányszor egy címzett elmenti a fájlt, tehát a kettő közti eltérés a kiszállítás után pozitív bizonyíték arra, hogy valaki downstream szerkesztette a munkafüzetet – ami nem egy vitát dönt el arról, kinek a számait hordozza valójában egy továbbküldött táblázat. Egy csapda rejtőzik a beállítatlan állapotban: az szó szerint nulla érték, nem kivétel és nem null, tehát az auditkódnak kifejezetten a nullára kell vizsgálnia. Formázzon meg egy beállítatlan TDateTime értéket enélkül a védelem nélkül, és a naplói megtelnek magabiztosan hibás 1899. decemberi dátummal
DocPropsTouched: a munkafüzet, amely docProps nélkül kerül ki
Egy csak olvasható jelző, a DocPropsTouched, kapuzza az XLSX tulajdonságírót. Az a munkafüzet, amelyben soha egyetlen tulajdonsághoz sem rendeltek értéket, egyáltalán nem hoz létre docProps részeket; a HotXLS nem hajlandó üres metaadat-vázat kiírni. A viselkedés rendezett, és két olyan következménye van, amelyek köré érdemes tervezni
A fogadó oldal beolvasó kódja nem feltételezheti, hogy a core.xml minden csomagban létezik. Az az eszköz, amely keményen megköveteli, tökéletesen érvényes minimális fájlokat fog visszautasítani. Ha pedig a megfelelőségi elvárása az, hogy minden kimenő dokumentum hordozzon legalább egy generátorazonosságot, ez az elvárás kóddá válik, nem a formátum tulajdonságává: rendeljen értéket az Application és az Author mezőhöz feltétel nélkül a mentési útvonalon, mivel egy érintetlen munkafüzet a specifikáció szerint teljesen szabályos, miközben csendben megsérti az Ön szabályzatát
A régi XLS felület és a Comments csapdája
A BIFF-homlokzat a régebbi, kisebb mezőkészletet hordozza: Title, Subject, Author, Keywords, Comments, Company és Manager, ezenfelül a LastSavedBy, amely a UserName aliasa, és amely azt a WRITEACCESS rekordot írja, amelyet az Excel megjelenít, amikor egy másik felhasználó zárolta a fájlt
var
Legacy: IXLSWorkbook; // referenciaszámlált interfész: nincs kézi Free
begin
Legacy := TXLSWorkbook.Create;
if Legacy.Open('archive-1999.xls') <= 0 then
raise Exception.Create('Cannot open archive file');
Legacy.Title := 'FY1999 ledger (migrated copy)';
Legacy.Author := 'Archive Migration Batch';
Legacy.Company := 'Northwind Financial';
Legacy.Comments := 'Migrated 2026-06-11; source retained in cold storage';
Legacy.LastSavedBy := 'migration-svc'; // BIFF WRITEACCESS rekord
Legacy.SaveAs('archive-1999-stamped.xls');
end;
Egyetlen névütközés okoz visszatérő zavart. Az itteni dokumentumszintű Comments tulajdonság az a szabad szöveges megjegyzés, amely a fájl tulajdonságpárbeszédében látszik. Semmi köze a cellamegjegyzésekhez, amelyek rajzréteg-objektumok, és teljesen külön API-n keresztül kapcsolódnak tartományokhoz. Az a kódellenőrzés, amely a „már írunk Comments mezőt” állítást elfogadja anélkül, hogy megnézné, melyikről van szó, rossz funkcióról szóló állítást fogadott el, és ez gyakrabban fordul elő, mint amennyit a közös név sejtetne. A kettőben négy betű közös, egyetlen bájtnyi tárolás sem
Metaadat olvasása beérkezéskor, és a szondázási rés
Az olvasás szimmetrikus. Az Open után ugyanazok a tulajdonságok a fájlból feltöltve térnek vissza, ami a beérkező munkafüzetek metaadat-auditját rövid ciklussá alakítja
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open(FileName) = 1 then
begin
Writeln(Format('%s | title="%s" author="%s" created=%s',
[ExtractFileName(FileName), Book.Title, Book.Author,
FormatDateTime('yyyy-mm-dd', Book.Created)]));
if Book.Created = 0 then
Writeln(' no creation date recorded');
end;
finally
Book.Free;
end;
end;
Eközben egy korlát köré tervezzen. Nincs csak tulajdonságokat olvasó szonda. A GetSheetNames munkafüzet betöltése nélkül tudja listázni a munkalapokat, de a Title vagy az Author kiolvasása teljes Open hívást jelent, tehát egy nagy archívum metaadat-osztályozása minden fájlon megfizeti a teljes elemzés árát. A BIFF oldalán ezt a költséget csak olvasó auditoknál csökkentheti, ha megnyitás előtt igazra állítja a _DisableGraphics értéket, ami egyenesen kihagyja a rajzréteget. Ez illik egy olyan ciklushoz, amely csak tulajdonságokat és cellastatisztikát olvas, és pontosan rossz abban a pillanatban, amint ugyanaz a példány menteni is akar, mert a kihagyott rajztartalom elveszne. Amikor önmagában a munkalapszerkezet is előszűrheti a halmazt – az egylapos exportok a kézenfekvő átugorható eset –, a munkalapok listázásáról és a könnyűsúlyú vizsgálatról szóló cikkünkben leírt olcsó technikák csökkentik, hány fájl jut el a drága lépésig. Tömeges bélyegzési feladatoknál pedig, ahol több ezer kimenet íródik ki, nem pedig vizsgálat zajlik, a kötegfeladatokhoz való streamelt írásról szóló cikkünk írásoldali átbocsátóképességi mintái változtatás nélkül átvihetők, hiszen a tulajdonságok beállítása semmi mérhetőt nem ad a mentési időhöz
Formátumok közti átkelés és a szivárgás megfékezése
A tulajdonságok egyetlen homlokzaton belül tisztán megjárják az oda-vissza utat: nyisson meg egy .xlsx fájlt, szerkessze, mentse el, és a készlet sértetlenül tér vissza. A formátumok közti átkelésnél törik meg a paritás feltételezése, mert a BIFF és az OOXML mezőkészlete nem fedi egymást egy az egyben. A BIFF-ben van Manager, de nincsenek időbélyegek; az OOXML-ben van Category, Description, valamint a Created/Modified pár. Az a konverter, amely vakon másol, elveszíti mindazt, amit a célformátum nem tud tárolni, ezért képezze le a mezőket kifejezetten, és tegye a leképezést a konverziós ellenőrzőlistájára minden más mellé, ami nem éli túl az utat
Az a szivárgás, amelyet a sablonöröklés nyit, a másik irányba fut: olyan információ, amelyet soha nem akart kiküldeni. Szerzőnevek, kulcsszavakban felejtett belső projektcímkék, egy piszkozatcím, amelyet senki nem hagyott jóvá. A fenti generátor mindent felülíró fegyelme az egész védelem, és érdemes úgy ellenőrizni, ahogyan egy kívülálló tenné: megnyitva a Tulajdonságok párbeszédet, amelyhez bármelyik ügyfél hozzáfér, vagy kicsomagolva az .xlsx fájlt, és közvetlenül a csomagból olvasva a docProps/core.xml részt. Amit ott lát, pontosan az, amit minden downstream indexelő is lát
Ez a downstream láthatóság az oka annak is, hogy néhány mező több gondosságot érdemel a többinél. A Title, az Author, a Keywords (amely címkékként jelenik meg), valamint a Comments vagy a Description hordozza az indexelési súly nagy részét a SharePointban és a Windows Searchben. Egy dokumentumonként valóban egyedi Title, amely az időszakot és a számlát hordozza, többet tesz a megtalálhatóságért, mint bármilyen ráépített mappaelnevezési séma, és mentésenként egyetlen értékadásba kerül
A dokumentumtulajdonságok a legolcsóbb professzionális fényezés, amelyet egy generált munkafüzet hordozhat, és a leggyakrabban kiszállított hiba, ha senki nem gazdája nekik. Az itt leírt mindkét tulajdonságfelület a HotXLS Delphi Component része, amely natívan írja őket XLS és XLSX formátumhoz, Excel-automatizálás nélkül