Odborný článok

Zápis súborov XLSX v režime ISO 29500 Strict z Delphi

HotXLS zapisuje z Delphi a C++Builder zošity Open XML v režime ISO/IEC 29500 Strict nastavením jedinej vlastnosti, StrictOOXML, pred uložením. Každá časť balíka, od xl/workbook.xml až po súbory vzťahov a typy obsahu, sa zapisuje pomocou prísnych slovníkov purl.oclc.org namiesto prechodných schemas.openxmlformats.org, a funkcie, ktoré Strict nepovoľuje, sa odmietnu explicitnou výnimkou namiesto toho, aby sa aj tak zapísali

Väčšina vývojárov sa s touto požiadavkou stretne cez obstarávací dokument. Verejné súťaže vo viacerých jurisdikciách požadujú normalizovanú formu Open XML podľa ISO, nie prechodnú formu, ktorú Office zapisuje predvolene, a archív, ktorý vyžaduje ISO 29500 Strict, odmietne bežné .xlsx, aj keď ho Excel bezchybne otvorí. Prechodné menné priestory existujú kvôli kompatibilite so starším binárnym správaním; prísne menné priestory sú samotný štandard

Čo sa v skutočnosti líši medzi Strict a Transitional?

Viditeľný rozdiel je v slovníku. Prísna časť zošita deklaruje http://purl.oclc.org/ooxml/spreadsheetml/main ako svoj koreňový menný priestor a http://purl.oclc.org/ooxml/officeDocument/relationships pre odkazy na vzťahy, a nikde v balíku nesmie prežiť žiadny prechodný menný priestor. S tým sa menia aj typy vzťahov, takže koreňová časť vzťahov pomenúva .../ooxml/officeDocument/relationships/officeDocument namiesto známeho ekvivalentu openxmlformats, a typ rozšírených vlastností je v tvare camelCase ako extendedProperties

Neviditeľný rozdiel je v rozsahu. Strict zámerne vynecháva časti prechodnej schémy, ktoré existovali iba na obojsmerné spracovanie starších binárnych súborov, spolu s rozšíreniami dodávateľa, ktoré Office pridal neskôr. Preto konverzia nie je vyhľadaj-a-nahraď nad reťazcami: niektoré funkcie jednoducho nemajú prísny zápis a nesmú sa zapísať vôbec

Zapnutie funkcie

Bežný kód na tvorbu obsahu sa nemení. Zostavte zošit tak, ako to robíte vždy, nastavte príznak a uložte:

var
  Wb: TXLSXWorkbook;
  Sh: TXLSXWorksheet;
begin
  Wb := TXLSXWorkbook.Create;
  try
    Sh := Wb.Sheets.Add('Data');
    Sh.Cells[1, 1].Value := 'Product';
    Sh.Cells[1, 2].Value := 'Amount';
    Sh.Cells[2, 1].Value := 'Widget';
    Sh.Cells[2, 2].Value := 17;
    Sh.Cells[3, 2].Formula := '=SUM(B2:B2)';

    Wb.StrictOOXML := True;          // výstup ISO/IEC 29500 Strict
    if Wb.SaveAs('archive-copy.xlsx') <> 1 then
      raise Exception.Create('strict save failed');
  finally
    Wb.Free;
  end;
end;

Príznak sa resetuje na začiatku každej operácie ukladania a znovu priradí z vlastnosti zošita, takže výnimka počas jedného ukladania nemôže preniesť prísny režim do ďalšieho. Tento detail je dôležitý v serverových procesoch, kde jeden objekt zošita obsluhuje viacero exportných požiadaviek

Prečo môže prísne ukladanie odmietnuť beh?

Štyri rodiny funkcií sú rozšírenia od Microsoftu bez ekvivalentu v ISO 29500 Strict, a HotXLS pri ukladaní vyvolá výnimku namiesto toho, aby vygeneroval balík, ktorý tvrdí, že je v súlade s prísnym režimom, hoci nie je:

// Prísny výstup nemôže vložiť projekt VBA
//   -> zošity s makrami ukladajte ako prechodné .xlsm
// Prísny výstup nemôže niesť ovládacie prvky formulára
//   -> tlačidlá, začiarkavacie polia, rozbaľovacie zoznamy a ich ctrlProps
// Prísny výstup nemôže niesť vláknové komentáre
//   -> moderný model persons/threads, nie klasické poznámky
// Prísny výstup nemôže niesť metadáta dynamických polí
//   -> rozliate rozsahy zaznamenané cez časť metadát

Hlasné zlyhanie je tu správnym kompromisom. Ticho zahodený projekt VBA premení funkčný zošit na poškodený, ktorý sa aj tak otvorí, a hlásenie o zlyhaní príde od používateľa až o niekoľko týždňov. Výnimka pomenuje funkciu aj vlastnosť, ktorú treba zmeniť, kým volajúci kód ešte vie, čo exportoval. Zachovanie makier a externých odkazov na prechodnej ceste opisuje časť zachovanie projektov VBA a externých odkazov

Dve rodiny rozšírení sa spracúvajú inak a oplatí sa vedieť prečo. Dátové pruhy, minigrafy a podobné funkcie žijú v slovníkoch x14 a xm, a varianty obrázkov SVG žijú v c15. Ide o obsah zoznamu rozšírení, ktorého menné priestory sú samopopisné, bežné parsery tabuliek ich tolerujú a neexistuje ISO ekvivalent, do ktorého by sa dali preložiť. HotXLS ich ponecháva namiesto toho, aby zahodil používateľský obsah. Ak je validátor vo vašej pipeline prísny aj voči rozšíreniam, nielen voči menným priestorom, tieto funkcie pred exportom odstráňte zo zdrojového zošita

Preklad musí zasiahnuť aj časti, ktoré bežne nikto neprepisuje

Zaujímavý inžiniersky problém prísneho výstupu nie je XML hárka. Sú to časti, ktoré by rýchly zapisovač radšej skopíroval doslovne. HotXLS zachováva témy, pripojenia, externé odkazy, grafy a kontingenčné bloby tak, že ich pôvodné komprimované bajty skopíruje priamo, čo je presne správny postup pre vernosť a presne nesprávny postup pre prísny výstup, pretože skopírované bajty nesú prechodné menné priestory

Pod StrictOOXML týchto päť zachovávaných ciest prepne na prestavbu alebo na prekladajúce prehratie, čím obíde rýchlu cestu kopírovania bajtov. Celé XML prechádza jedinou prekladovou rutinou, ktorá sa ukotvuje na hodnotách atribútov v úvodzovkách, aby sa reťazec vyzerajúci ako URI vo vnútri bunky nikdy nemohol prepísať omylom. Text bunky obsahujúci rovnaké URI je v XML uniknutý ako entita, takže ukotvené nahradenie ho nevidí. Streamovací zapisovač najprv preloží svoju kostru a potom sa rozdelí pri sheetData, pretože bloky riadkov neobsahujú vôbec žiadne URI slovníkov. Súvisiacu mechaniku pre cestu zachovania opisuje časť bezstratové obojsmerné spracovanie tém, zoznamov rozšírení a calcChain

Čítanie súborov, ktoré Excel uložil v prísnom režime

Výstup je len polovica príbehu. Excel ponúka „Prísna tabuľka Open XML" ako možnosť uloženia a súbory takto vytvorené sa musia dať správne otvoriť. HotXLS normalizuje typy vzťahov na každom mieste balíka, kde sa vzťahy parsujú — v koreni, v externých odkazoch, hárkoch, kresbách aj kontingenčných tabuľkách —, takže prísny typ vzťahu zodpovedá tej istej internej konštante ako jeho prechodný náprotivok

Náprotivkom na strane čítania je normalizácia prefixov menných priestorov, ktorá umožňuje ľubovoľné prefixy a oba slovníky preloží do jednej kanonickej tabuľky názvov. Táto práca je prínosom rovnako pre bežné súbory ako pre prísne, keďže generátory tretích strán viažu prefixy voľne, a ide o rovnaký mechanizmus, aký opisuje časť riešenie vzťahov OPC v balíkoch XLSX

Krátky zoznam kontrol pred nasadením prísneho výstupu

Overujte pomocou balíka, nie pomocou Excelu. Excel bez problémov otvorí obe formy, takže úspešné otvorenie nedokazuje nič o zhode. Rozbaľte výsledok a overte, že xl/workbook.xml deklaruje menný priestor purl, že žiadna časť neobsahuje schemas.openxmlformats.org/spreadsheetml, a že typy vzťahov v _rels/.rels a xl/_rels/workbook.xml.rels používajú prísne formy

Potom súbor znovu otvorte cez HotXLS a porovnajte hodnoty, vzorce, formáty a hypertextové odkazy so zdrojom. Spätný test čítania je jediný lacný spôsob, ako dokázať, že preklad nepoškodil obsah, a súčasne preveruje aj normalizáciu na strane čítania. Ak vaše zošity obsahujú grafy, skontrolujte aj tie, pretože časť grafu je jednou zo zachovávaných častí, ktorá v prísnom režime prepína na prestavanú cestu

Prísny výstup, tolerantné čítanie a bezstratové zachovanie sú súčasťou toho istého jadra OOXML pre Delphi a C++Builder; kompletný zoznam funkcií nájdete na stránke HotXLS Delphi spreadsheet component