HotXLS zapisuje sešity Open XML ve formátu ISO/IEC 29500 Strict z Delphi a C++Builder nastavením jediné vlastnosti, StrictOOXML, před uložením. Každá část balíčku, od xl/workbook.xml až po soubory vztahů a typy obsahu, se zapisuje se striktními slovníky purl.oclc.org namísto přechodných slovníků schemas.openxmlformats.org, a funkce, které Strict nepovoluje, jsou odmítnuty výslovnou výjimkou, místo aby se přesto zapsaly
Většina vývojářů se s tímto požadavkem setká přes zadávací dokumentaci. Veřejné zakázky v několika jurisdikcích požadují ISO standardizovanou formu Open XML, ne přechodnou formu, kterou Office ve výchozím stavu zapisuje, a archiv, který vyžaduje ISO 29500 Strict, odmítne běžný soubor .xlsx, i když jej Excel otevře bez problémů. Přechodné jmenné prostory existují kvůli zachování chování starších binárních formátů; striktní jsou samotný standard
Co se ve skutečnosti liší mezi Strict a Transitional?
Viditelný rozdíl je ve slovníku. Striktní část sešitu deklaruje http://purl.oclc.org/ooxml/spreadsheetml/main jako svůj kořenový jmenný prostor a http://purl.oclc.org/ooxml/officeDocument/relationships pro odkazy na vztahy, a nikde v balíčku nesmí přežít žádný přechodný jmenný prostor. S tím se mění i typy vztahů, takže kořenová část vztahů pojmenovává .../ooxml/officeDocument/relationships/officeDocument namísto známého ekvivalentu openxmlformats, a typ rozšířených vlastností je zapsán stylem camelCase jako extendedProperties
Neviditelný rozdíl je v rozsahu. Strict záměrně vynechává části přechodného schématu, které existovaly jen kvůli zpětné kompatibilitě se staršími binárními soubory, spolu s rozšířeními dodanými Office později. Proto převod není hledáním a nahrazováním v řetězcích: některé funkce prostě nemají striktní zápis a nesmí se vůbec zapisovat
Zapnutí funkce
Běžný kód pro tvorbu obsahu se nemění. Sestavte sešit obvyklým způsobem, nastavte pří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;
Příznak se resetuje na začátku každé operace uložení a znovu se přiřadí z vlastnosti sešitu, takže výjimka během jednoho uložení nemůže striktní režim prosáknout do dalšího. Tento detail má význam v serverových procesech, kde jeden objekt sešitu obsluhuje více exportních požadavků
Proč může striktní uložení odmítnout proběhnout?
Čtyři skupiny funkcí jsou rozšíření Microsoftu bez ekvivalentu v ISO 29500 Strict, a HotXLS při ukládání vyvolá výjimku, místo aby vydal balíček, který tvrdí, že je striktně konformní, a přitom není:
// Striktní výstup nemůže vložit projekt VBA
// -> sešity s makry uložte jako přechodné .xlsm
// Striktní výstup nemůže nést ovládací prvky formuláře
// -> tlačítka, zaškrtávací pole, rozevírací seznamy a jejich ctrlProps
// Striktní výstup nemůže nést vláknové komentáře
// -> moderní model persons/threads, ne klasické poznámky
// Striktní výstup nemůže nést metadata dynamických polí
// -> rozlévané oblasti zaznamenané v části metadat
Hlasité selhání je zde správný kompromis. Tiše zahozený projekt VBA promění funkční sešit v rozbitý, který se přesto otevře, a zpráva o selhání dorazí od uživatele o týdny později. Výjimka pojmenuje funkci i vlastnost, kterou je třeba změnit, zatímco volající kód ještě ví, co exportoval. Zachování maker a externích odkazů na přechodné cestě popisuje článek zachování projektů VBA a externích odkazů
Dvě skupiny rozšíření se řeší jinak, a stojí za to vědět proč. Datové pruhy, minigrafy a podobné funkce žijí ve slovnících x14 a xm, a varianty obrázků SVG žijí v c15. Jde o obsah rozšiřujícího seznamu, jehož jmenné prostory jsou samopopisné, obecné parsery tabulek je tolerují a neexistuje žádný ekvivalent ISO, do kterého by se daly převést. HotXLS je ponechává, místo aby zahodil uživatelský obsah. Pokud je validátor ve vaší pipeline striktní i ohledně rozšíření, ne jen jmenných prostorů, odstraňte tyto funkce ze zdrojového sešitu ještě před exportem
Převod musí zasáhnout části, které běžně nikdo nepřepisuje
Zajímavý inženýrský problém striktního výstupu není XML listu. Je to části, které by rychlý zapisovač raději zkopíroval doslovně. HotXLS zachovává motivy, připojení, externí odkazy, grafy a bloky kontingenčních tabulek tím, že kopíruje jejich původní komprimované bajty přímo skrz, což je přesně to správné pro věrnost a přesně to špatné pro striktní výstup, protože zkopírované bajty nesou přechodné jmenné prostory
Pod StrictOOXML těchto pět zachovávaných cest přepne na přestavbu nebo na překládané přehrání, čímž obejde rychlou cestu kopírování bajtů. Veškeré XML prochází jedinou překladovou rutinou, která se ukotvuje na hodnotách atributů v uvozovkách, takže řetězec vypadající jako URI uvnitř buňky nemůže být nikdy omylem přepsán. Text buňky obsahující stejné URI je v XML escapován jako entita, takže jej ukotvené nahrazení nevidí. Streamovací zapisovač nejprve přeloží svou kostru a poté se rozdělí u sheetData, protože bloky řádků neobsahují vůbec žádná URI slovníků. Související mechaniku pro cestu zachování popisuje článek bezztrátové obousměrné převody motivů, seznamů rozšíření a calcChain
Čtení souborů, které Excel uložil jako strict
Výstup je jen polovina příběhu. Excel nabízí jako možnost uložení "Strict Open XML Spreadsheet" a soubory takto vytvořené se musí otevřít správně. HotXLS normalizuje typy vztahů na každém místě, kde se v balíčku vztahy parsují, u kořene, externích odkazů, listů, kreseb a kontingenčních tabulek, takže striktní typ vztahu odpovídá stejné interní konstantě jako jeho přechodný protějšek
Protějšek na straně čtečky je normalizace prefixů jmenných prostorů, která umožňuje libovolné prefixy a oba slovníky rozřešit do jedné kanonické tabulky názvů. Tato práce prospívá běžným souborům stejně jako striktním, protože generátory třetích stran vážou prefixy volně, a jde o stejnou mechaniku popsanou v článku rozřešení vztahů OPC v balíčcích XLSX
Krátký kontrolní seznam před vydáním striktního výstupu
Ověřujte balíček, ne Excel. Excel ochotně otevře obě formy, takže úspěšné otevření o shodě nic nedokazuje. Rozbalte výsledek a potvrďte, že xl/workbook.xml deklaruje jmenný prostor purl, že žádná část neobsahuje schemas.openxmlformats.org/spreadsheetml a že typy vztahů v _rels/.rels a xl/_rels/workbook.xml.rels používají striktní formy
Poté soubor znovu otevřete přes HotXLS a porovnejte hodnoty, vzorce, formáty a hypertextové odkazy se zdrojem. Test zpětného čtení je jediný levný způsob, jak dokázat, že převod obsah nepoškodil, a zároveň prověřuje normalizaci na straně čtečky. Pokud vaše sešity obsahují grafy, zkontrolujte i ty, protože část grafu je jednou ze zachovávaných částí, která ve striktním režimu přepíná na přestavěnou cestu
Striktní výstup, tolerantní čtení a bezztrátové zachování jsou součástí stejného motoru OOXML pro Delphi a C++Builder; kompletní seznam funkcí je na stránce komponenty HotXLS pro tabulky v Delphi