Odborný článok

Nastavenie vlastností dokumentu Excel a metadát zošita v Delphi pomocou HotXLS

Prečo metadáta zošita patria do generátora

Zošit Excelu nenesie iba bunky. Vedľa mriežky sa prenáša druhá identita dokumentu: názov, autor, firma, kľúčové slová, dátumy a poznámky. Tieto údaje nevidno v hárku, ale indexujú ich Windows Search, SharePoint aj systémy správy dokumentov. Ak generovaný súbor zdedí autora a názov zo šablóny, celé archívne pracovisko začne evidovať nesprávny pôvod dokumentu

HotXLS sprístupňuje túto vrstvu priamo na úrovni workbook objektu. Hodnoty nastavíte ako vlastnosti pred uložením a knižnica ich zapíše do správneho fyzického kontajnera podľa toho, či výsledkom je XLS alebo XLSX. Tým odpadá ručné otváranie OLE property setov alebo úprava XML častí v ZIP balíku

Rozdiel medzi XLS a XLSX

Starší BIFF formát ukladá dokumentové vlastnosti do OLE compound-file streamov, najmä SummaryInformation, a používa aj záznam WRITEACCESS pre meno posledného zapisujúceho používateľa. OOXML naopak ukladá jadrové vlastnosti do docProps/core.xml a aplikačné vlastnosti do docProps/app.xml. Pole, ktoré má v jednom formáte prirodzené miesto, nemusí mať presný ekvivalent v druhom

Preto by konverzný nástroj nemal kopírovať metadáta naslepo. Vopred určte mapovanie polí, napríklad Title, Subject, Author, Keywords, Company, Created a Modified, a zapíšte ho do kontrolného zoznamu rovnako ako mapovanie formátovania alebo vzorcov

Zapisovanie vlastností pri generovaní

Najbezpečnejšie pravidlo je prepísať všetky dôležité polia pri každom uložení. Hodnoty majú pochádzať z obchodného záznamu, nie zo šablóny. Title môže niesť obdobie a číslo účtu, Author a LastModifiedBy identitu služby, Keywords stabilné vyhľadávacie značky a Description poznámku, že ide o automaticky vygenerovaný výstup

Created a Modified si zaslúžia samostatnú politiku. Created by mal označovať okamih vytvorenia dokumentu a zostať stabilný. Modified môže pomôcť odhaliť neskoršiu úpravu prijímateľom. Ak je hodnota TDateTime nulová, treba ju zachytiť explicitne, inak sa v logoch objavia zavádzajúce dátumy z konca roku 1899

DocPropsTouched a prázdne balíky

Pri XLSX existuje dôležitý detail: ak sa nikdy nenastaví žiadna vlastnosť, HotXLS nemusí vytvoriť docProps časti vôbec. To je korektné pre minimálny súbor, ale nemusí to vyhovovať firemnej politike. Ak každý odchádzajúci dokument musí niesť aspoň identitu generátora, nastavte Application a Author bezpodmienečne v ceste uloženia

Čítanie a audit vstupných súborov

Čítanie je symetrické. Po Open sú rovnaké vlastnosti dostupné na workbook objekte a audit archívu môže vypísať titul, autora, firmu a dátum vytvorenia. Neexistuje však lacná properties-only sonda, takže čítanie Title alebo Author znamená plné otvorenie súboru. Pri veľkých dávkach sa oplatí najprv filtrovať lacnými kontrolami, napríklad zoznamom hárkov

Na strane BIFF môže _DisableGraphics pomôcť pri čisto read-only audite, pretože preskočí kresliacu vrstvu. Nesmie sa však použiť na inštanciu, ktorá bude ukladať, inak by sa vynechaný obsah stratil. Tento rozdiel medzi auditom a editáciou treba zapísať do kódu aj do testov

Kontrola úniku informácií

Metadáta cestujú s každou kópiou súboru. Interný názov projektu, meno autora šablóny alebo osobný údaj v Keywords sa dostane mimo databázových oprávnení systému, ktorý dokument vytvoril. Preto je disciplína prepísať každé pole nielen otázkou vyhľadávania, ale aj ochranou pred neúmyselným zverejnením interných údajov

Ďalšie príklady kódu

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    if Book.Open('statement-template.xlsx') <> 1 then
      raise Exception.Create('Template not available');

    // Overwrite every field: anything left untouched is
    // inherited from whoever designed the template.
    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;
var
  Legacy: IXLSWorkbook;     // reference-counted interface: no manual 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 record

  Legacy.SaveAs('archive-1999-stamped.xls');
end;
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;