Teknisk artikel

Skrivning af ISO 29500 Strict XLSX-filer fra Delphi

HotXLS skriver ISO/IEC 29500 Strict Open XML-arbejdsbøger fra Delphi og C++Builder ved at sætte én enkelt egenskab, StrictOOXML, før gemning. Hver del i pakken, fra xl/workbook.xml ned til relationsfilerne og indholdstyperne, skrives med de strenge purl.oclc.org-vokabularer i stedet for de transitionelle schemas.openxmlformats.org-vokabularer, og funktioner, som Strict ikke tillader, afvises med en eksplicit undtagelse frem for at blive skrevet ud alligevel

De fleste udviklere møder dette krav via et udbudsdokument. Offentlige udbud i flere retskredse beder om den ISO-standardiserede form af Open XML, ikke den transitionelle form, som Office skriver som standard, og et arkiv, der kræver ISO 29500 Strict, vil afvise en normal .xlsx, selvom Excel åbner den fint. De transitionelle navnerum findes for at imødekomme legacy-binær adfærd; de strenge er selve standarden

Hvad adskiller faktisk Strict fra Transitional?

Den synlige forskel er vokabular. En streng arbejdsbogsdel deklarerer http://purl.oclc.org/ooxml/spreadsheetml/main som sit rodnavnerum og http://purl.oclc.org/ooxml/officeDocument/relationships til relationsreferencer, og intet transitionelt navnerum må overleve nogen steder i pakken. Relationstyper ændrer sig med det, så rodrelationsdelen navngiver .../ooxml/officeDocument/relationships/officeDocument frem for den velkendte openxmlformats-ækvivalent, og den udvidede egenskabstype er camelCased som extendedProperties

Den usynlige forskel er omfang. Strict udelader bevidst dele af det transitionelle skema, som kun eksisterede for at rundture legacy-binærfiler, sammen med de leverandørudvidelser, Office tilføjede efterfølgende. Det er derfor, konverteringen ikke er en søg-og-erstat over strenge: nogle funktioner har simpelthen ingen streng stavemåde og må slet ikke skrives

At slå det til

Almindelig forfatterkode ændrer sig ikke. Byg arbejdsbogen, som du altid gør, sæt flaget, og gem:

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;          // ISO/IEC 29500 Strict-output
    if Wb.SaveAs('archive-copy.xlsx') <> 1 then
      raise Exception.Create('strict save failed');
  finally
    Wb.Free;
  end;
end;

Flaget nulstilles ved starten af hver gemmehandling og gentildeles fra arbejdsbogsegenskaben, så en undtagelse under én gemning ikke kan lække strict-tilstand ind i den næste. Den detalje har betydning i serverprocesser, hvor ét enkelt arbejdsbogsobjekt betjener flere eksportanmodninger

Hvorfor kan en strict-gemning nægte at køre?

Fire funktionsfamilier er Microsoft-udvidelser uden ISO 29500 Strict-ækvivalent, og HotXLS udløser en undtagelse ved gemning frem for at udsende en pakke, der hævder streng konformitet og ikke er det:

// Strict-output kan ikke indlejre et VBA-projekt
//   -> gem makroaktiverede arbejdsbøger som transitionel .xlsm
// Strict-output kan ikke bære formularkontroller
//   -> knapper, afkrydsningsfelter, kombinationsbokse og deres ctrlProps
// Strict-output kan ikke bære trådede kommentarer
//   -> den moderne persons/threads-model, ikke klassiske noter
// Strict-output kan ikke bære dynamisk array-metadata
//   -> spill-områder registreret via metadata-delen

At fejle højlydt er den rigtige afvejning her. Et stiltiende droppet VBA-projekt gør en fungerende arbejdsbog til en ødelagt en, der stadig åbner, og rapporten om fejlen ankommer fra en bruger uger senere. En undtagelse navngiver funktionen og den egenskab, der skal ændres, mens den kaldende kode stadig ved, hvad den eksporterede. Bevaring af makroer og eksterne links på den transitionelle sti er beskrevet i bevaring af VBA-projekter og eksterne links

To udvidelsesfamilier håndteres anderledes, og det er værd at vide hvorfor. Databjælker, sparklines og lignende funktioner findes i x14- og xm-vokabularerne, og SVG-varianterne af billeder findes i c15. Dette er extension list-indhold, hvis navnerum er selvbeskrivende, generelle regnearksparsere tolererer dem, og der findes ingen ISO-ækvivalent at oversætte dem til. HotXLS beholder dem frem for at smide brugerindhold på gulvet. Hvis en validator i din pipeline er streng omkring udvidelser lige såvel som navnerum, skal du fjerne disse funktioner fra kildearbejdsbogen før eksport

Oversættelsen skal nå dele, som normalt ikke omskrives af nogen

Det interessante tekniske problem i strict-output er ikke regnearks-XML'en. Det er de dele, en hurtig skriver hellere ville kopiere ordret. HotXLS bevarer temaer, forbindelser, eksterne links, diagrammer og pivot-blobs ved at kopiere deres oprindelige komprimerede bytes direkte igennem, hvilket er præcis det rigtige at gøre for troskab og præcis det forkerte for strict-output, fordi kopierede bytes bærer transitionelle navnerum

Under StrictOOXML skifter disse fem bevarede stier til genopbygning eller til en oversættende replay, som forbigår byte-kopi-hurtigstien. Al XML går gennem én oversættelsesrutine, som forankrer på dobbelt-anførselstegn-attributværdier, så en URI-lignende streng inde i en celle aldrig kan blive omskrevet ved et uheld. Celletekst, der indeholder samme URI, er escaped som en entitet i XML'en, så den forankrede erstatning ikke kan se den. Den streamende skriver oversætter sit skelet først og splitter derefter ved sheetData, da rækkeblokkene slet ingen vokabular-URI'er indeholder. Relateret mekanik for bevaringsstien er beskrevet i tabsfrie rundture af temaer, extension lists og calcChain

Læsning af filer, Excel gemte som strict

Output er kun halvdelen af historien. Excel tilbyder "Strict Open XML Spreadsheet" som en gemmemulighed, og filer produceret på den måde skal åbne korrekt. HotXLS normaliserer relationstyper ved hvert relationsparsingssted i pakken, roden, eksterne links, regneark, tegninger og pivottabeller, så en streng relationstype matcher den samme interne konstant som sin transitionelle modpart

Modstykket på læsersiden er normalisering af navnerumspræfikser, som lader vilkårlige præfikser og begge vokabularer opløses til én kanonisk navnetabel. Dette arbejde gavner almindelige filer lige såvel som strenge, da tredjepartsgeneratorer binder præfikser frit, og det er den samme mekanik, der er beskrevet i OPC-relationsopløsning i XLSX-pakker

En kort tjekliste, før du sender strict-output i produktion

Verificér med pakken, ikke med Excel. Excel åbner begge former uden problemer, så en vellykket åbning beviser intet om konformitet. Udpak resultatet, og bekræft, at xl/workbook.xml deklarerer purl-navnerummet, at ingen del indeholder schemas.openxmlformats.org/spreadsheetml, og at relationstyper i _rels/.rels og xl/_rels/workbook.xml.rels bruger de strenge former

Genåbn derefter filen via HotXLS, og sammenlign værdier, formler, formater og hyperlinks mod kilden. En genindlæsningstest er den eneste billige måde at bevise, at oversættelsen ikke skadede indholdet, og den motionerer samtidig normaliseringen på læsersiden. Hvis dine arbejdsbøger bærer diagrammer, så tjek også dem, da diagramdelen er en af de bevarede dele, der skifter til en genopbygget sti under strict-tilstand

Strict-output, tolerant læsning og tabsfri bevaring er alle en del af den samme OOXML-motor til Delphi og C++Builder; den komplette funktionsliste findes på HotXLS Delphi regnearkskomponentsiden