Articol tehnic

Scrierea fișierelor XLSX ISO 29500 Strict din Delphi

HotXLS scrie registre de lucru Open XML ISO/IEC 29500 Strict din Delphi și C++Builder prin setarea unei singure proprietăți, StrictOOXML, înainte de salvare. Fiecare parte din pachet, de la xl/workbook.xml până la fișierele de relații și tipurile de conținut, este scrisă cu vocabularele stricte purl.oclc.org în loc de cele tranzitorii schemas.openxmlformats.org, iar funcțiile pe care Strict nu le permite sunt respinse printr-o excepție explicită, nu scrise oricum

Majoritatea dezvoltatorilor întâlnesc această cerință printr-un document de achiziție. Licitațiile din sectorul public din mai multe jurisdicții cer forma standardizată ISO a Open XML, nu forma tranzitorie pe care Office o scrie implicit, iar o arhivă care impune ISO 29500 Strict va respinge un .xlsx normal chiar dacă Excel îl deschide perfect. Spațiile de nume tranzitorii există pentru a accepta comportamentul binar vechi; cele stricte sunt standardul propriu-zis

Ce diferă efectiv între Strict și Transitional?

Diferența vizibilă este vocabularul. O parte de registru de lucru strict declară http://purl.oclc.org/ooxml/spreadsheetml/main ca spațiu de nume rădăcină și http://purl.oclc.org/ooxml/officeDocument/relationships pentru referințele de relații, iar niciun spațiu de nume tranzitoriu nu poate supraviețui nicăieri în pachet. Tipurile de relații se schimbă odată cu asta, așa că partea de relații rădăcină numește .../ooxml/officeDocument/relationships/officeDocument în loc de echivalentul familiar openxmlformats, iar tipul proprietăților extinse este scris cu literă mică la început, extendedProperties

Diferența invizibilă este scopul. Strict omite deliberat părți ale schemei tranzitorii care existau doar pentru a permite conversia dus-întors a fișierelor binare vechi, împreună cu extensiile de furnizor pe care Office le-a adăugat ulterior. De aceea conversia nu este o simplă căutare și înlocuire de șiruri: unele funcții pur și simplu nu au o formă strictă și nu trebuie scrise deloc

Activarea ei

Codul obișnuit de creare nu se schimbă. Construiește registrul de lucru așa cum o faci mereu, setează indicatorul și salvează:

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

Indicatorul este resetat la începutul fiecărei operații de salvare și reatribuit din proprietatea registrului de lucru, așa că o excepție în timpul unei salvări nu poate lăsa modul strict să se scurgă în următoarea. Acest detaliu contează în procesele server unde un singur obiect registru de lucru deservește mai multe cereri de export

De ce poate refuza să ruleze o salvare strictă?

Patru familii de funcții sunt extensii Microsoft fără echivalent ISO 29500 Strict, iar HotXLS ridică o excepție la momentul salvării, în loc să emită un pachet care pretinde conformitate strictă și nu o are:

// Rezultatul strict nu poate încorpora un proiect VBA
//   -> salvează registrele de lucru cu macrocomenzi ca .xlsm tranzitoriu
// Rezultatul strict nu poate purta controale de formular
//   -> butoane, casete de bifat, casete combo și ctrlProps-urile lor
// Rezultatul strict nu poate purta comentarii cu fir de discuție
//   -> modelul modern persons/threads, nu notele clasice
// Rezultatul strict nu poate purta metadate de array dinamic
//   -> intervale de propagare (spill) înregistrate prin partea de metadate

Eșecul zgomotos este alegerea corectă aici. Un proiect VBA eliminat în tăcere transformă un registru de lucru funcțional într-unul stricat care încă se deschide, iar raportul despre eșec ajunge de la un utilizator după săptămâni. O excepție numește funcția și proprietatea de schimbat cât timp codul apelant încă știe ce exporta. Păstrarea macrocomenzilor și a legăturilor externe pe calea tranzitorie este acoperită în păstrarea proiectelor VBA și a legăturilor externe

Două familii de extensii sunt tratate diferit, și merită să știi de ce. Barele de date, sparkline-urile și funcții similare trăiesc în vocabularele x14 și xm, iar variantele SVG ale imaginilor trăiesc în c15. Acestea sunt conținut de listă de extensie ale cărui spații de nume sunt autodescriptive, parserele generale de foi de calcul le tolerează, și nu există niciun echivalent ISO pentru a le traduce. HotXLS le păstrează, în loc să arunce conținutul utilizatorului. Dacă un validator din pipeline-ul tău este strict și cu privire la extensii, nu doar la spații de nume, elimină acele funcții din registrul de lucru sursă înainte de export

Traducerea trebuie să ajungă la părți pe care nimeni nu le rescrie de obicei

Problema de inginerie interesantă în rezultatul strict nu este XML-ul foii de calcul. Sunt părțile pe care un scriitor rapid le-ar copia mai degrabă exact. HotXLS păstrează temele, conexiunile, legăturile externe, graficele și blob-urile pivot copiindu-le octeții comprimați originali direct, ceea ce e exact lucrul corect pentru fidelitate și exact lucrul greșit pentru rezultatul strict, deoarece octeții copiați poartă spații de nume tranzitorii

Sub StrictOOXML, acele cinci căi păstrate trec la reconstrucție sau la o redare traducătoare, ocolind calea rapidă de copiere a octeților. Tot XML-ul trece printr-o singură rutină de traducere, care se ancorează pe valorile de atribut cu ghilimele duble, astfel încât un șir care arată ca un URI dintr-o celulă nu poate fi rescris din greșeală. Textul de celulă care conține același URI este scăpat ca entitate în XML, astfel încât înlocuirea ancorată nu-l poate vedea. Scriitorul în flux își traduce mai întâi scheletul, apoi îl împarte la sheetData, deoarece blocurile de rânduri nu conțin niciun URI de vocabular. Mecanica aferentă căii de păstrare este acoperită în conversii dus-întors fără pierderi ale temelor, listelor de extensie și calcChain

Citirea fișierelor pe care Excel le-a salvat ca strict

Rezultatul este doar jumătate din poveste. Excel oferă "Strict Open XML Spreadsheet" ca opțiune de salvare, iar fișierele produse astfel trebuie să se deschidă corect. HotXLS normalizează tipurile de relații la fiecare punct de analiză a relațiilor din pachet, rădăcina, legăturile externe, foile de lucru, desenele și tabelele pivot, astfel încât un tip de relație strict se potrivește cu aceeași constantă internă ca și echivalentul său tranzitoriu

Contrapartea de pe partea de citire este normalizarea prefixului de spațiu de nume, care permite prefixe arbitrare și ambele vocabulare să se rezolve într-un singur tabel de nume canonic. Acest lucru avantajează atât fișierele obișnuite, cât și pe cele stricte, deoarece generatoarele terțe leagă prefixe liber, și este exact mecanismul descris în rezolvarea relațiilor OPC în pachetele XLSX

O listă scurtă de verificare înainte de a livra rezultatul strict

Verifică cu pachetul, nu cu Excel. Excel deschide ambele forme fără probleme, așa că o deschidere reușită nu dovedește nimic despre conformitate. Dezarhivează rezultatul și confirmă că xl/workbook.xml declară spațiul de nume purl, că nicio parte nu conține schemas.openxmlformats.org/spreadsheetml, și că tipurile de relații din _rels/.rels și xl/_rels/workbook.xml.rels folosesc formele stricte

Apoi redeschide fișierul prin HotXLS și compară valorile, formulele, formatele și hyperlink-urile cu sursa. Un test de recitire este singura metodă ieftină de a dovedi că traducerea nu a deteriorat conținutul, și exercită în același timp normalizarea de pe partea de citire. Dacă registrele tale de lucru poartă grafice, verifică și acelea, deoarece partea de grafic este una dintre părțile păstrate care trece la o cale reconstruită în modul strict

Rezultatul strict, citirea tolerantă și păstrarea fără pierderi fac toate parte din același motor OOXML pentru Delphi și C++Builder; lista completă de funcții este pe pagina componentei de foi de calcul HotXLS pentru Delphi