Delphi pozadinski sistem (backend) za izveštaje koji godinama emituje .xlsx dobija nov zahtev: pravila javnih nabavki kupca iz javnog sektora nalažu OpenDocument Spreadsheet izlaz, a analitičari sa tog naloga šalju svoje izmene nazad kao .ods datoteke sačuvane u LibreOffice-u. Tako da sada isti kod mora da upisuje i čita ODS. HotXLS, losLab-ova izvorna (native) Object Pascal biblioteka za radne tabele namenjena Delphi-ju i C++Builder-u, rukuje sa oba smera bez potrebe za instaliranim Excel-om ili LibreOffice-om. Ono što ne radi jeste da ta dva smera učini simetričnim. Izvoz prenosi daleko više nego što uvoz uspeva da povrati, i tim koji pretpostavi drugačije gledaće kako formule i formatiranje isparavaju negde između klijentove revizije i sledećeg izveštaja, bez ikakve greške na koju bi mogli ukazati.
Podrška za ODS živi na XLSX fasadi, a ne na XLS fasadi
HotXLS isporučuje dve nezavisne hijerarhije klasa u jednom paketu: TXLSWorkbook u unit-u lxHandle za binarne BIFF8 .xls datoteke, i TXLSXWorkbook u unit-u lxHandleX za OOXML .xlsx pakete. Svaka ulazna tačka za OpenDocument – OpenODS, SaveAsODS, GetODSSheetNames – vezana je za TXLSXWorkbook. Ovaj raspored nije proizvoljan. ODS paket, kako je specifikovano u standardu OASIS ODF 1.3, jeste zip arhiva koja sadrži mimetype član, manifest i telo content.xml, što ga čini strukturnim rođakom OOXML zip-a; BIFF8 je binarni tok zapisa iz 1990-ih koji nema ništa zajedničko sa tim.
Taj raspored ima praktičnu posledicu: stara .xls radna sveska ne može postati .ods u jednom pozivu. Prvo morate premostiti BIFF sadržaj u XLSX model pomoću funkcije SaveXLSWorkbookAsXLSX iz unit-a lxXlsxExport, ponovo otvoriti rezultat preko TXLSXWorkbook, a zatim izvesti odatle. Taj most nije bez gubitaka, i vredi znati gde su praznine pre nego što počnete da gradite na njemu. On kopira vrednosti, formule, formate brojeva, fontove, ispune (fills) i širine kolona. Ispušta ivice, spojene opsege, komentare, grafikone i uslovno formatiranje. Izvorna .xls datoteka sa gustim formatiranjem stići će u ODS sa znatno jednostavnijim izgledom, a to je svojstvo tog mosta, a ne ODS pisca.
Detekcija na strani uvoza je automatska. Obična metoda Open prepoznaje ODS paket po njegovom mimetype članu, vraćajući se na proveru datoteke content.xml na najvišem nivou kada taj član nedostaje, tako da generička putanja koda "otvori šta god da je korisnik otpremio" ne zahteva sopstveno ispitivanje ekstenzija. Nakon otvaranja, svojstvo SourceFormat prijavljuje koja je grana aktivirana.
Izvoz u ODS pomoću TODSExportOptions
Sam poziv za izvoz je u jednoj liniji; objekat opcija oko njega nosi odluke o kojima će vas recenzent kasnije pitati:
var
Book: TXLSXWorkbook;
Opts: TODSExportOptions;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('quarterly-report.xlsx');
Opts := TODSExportOptions.Create; // caller owns and frees this
try
Opts.Generator := 'ReportService 4.2'; // meta:generator override
Opts.IncludeCharts := True;
Opts.IncludeImages := True;
Book.SaveAsODS('quarterly-report.ods', Opts);
finally
Opts.Free;
end;
finally
Book.Free;
end;
end;
Objekat opcija je u vlasništvu pozivaoca. HotXLS ga neće osloboditi, što je razlog zašto je unutrašnji blok try..finally tu i nije opcionalan. Dva svojstva koja menjaju izlaz, a ne samo da ga označavaju, zaslužuju detaljniji osvrt. Postavljanje IncludeCharts := False radi više od samog skrivanja grafikona: uklanja poddokumente grafikona i njihove unose u manifestu iz paketa, što je upravo ono što želite kada je potrošač proces obrade podataka koji bi se inače spotakao o njih. Generator prepisuje ODF meta:generator string, koji inače glasi HotXLS/<version>; prepišite ga kada nizvodni alati identifikuju proizvođače datoteka radi usmeravanja podrške. Ako se ništa od toga ne primenjuje, u potpunosti preskočite objekat opcija. Pozivanje SaveAs(FileName, xlsxOpenDocumentSpreadsheet) je isto što i SaveAsODS sa podrazumevanim vrednostima, a preopterećenja toka na oba omogućavaju vam da upišete paket direktno u HTTP odgovor bez privremene datoteke.
Ša putanja uvoza čita – a šta namerno preskače
Pažljivo pročitajte ovaj deo pre nego što bilo kome obećate potpunu vernost kružnog putovanja (round-trip). Uvoz ODS-a u HotXLS-u je namerno napravljen kao lagana putanja. On čuva skalarne vrednosti ćelija i keširani rezultat koji je svaka formula nosila u trenutku čuvanja, i proširuje ponovljene redove i kolone u mrežu. Ne prenosi stilove, izraze ODS formula ili crteže.
Odluka vezana za formule je ona koja će najverovatnije stvoriti probleme, i doneta je namerno. ODF ćelija čuva dve stvari jednu pored druge: izraz formule, napisan u OpenFormula dijalektu definisanom u ODF 1.3 Part 4, i poslednju vrednost koju je aplikacija izračunala za nju. Prevođenje OpenFormula u sintaksu Excel formula je sopstveni problem konverzije dijalekata, sa realnim graničnim slučajevima oko vokabulara funkcija, sintakse referenci i modela grešaka. Čitanje keširane vrednosti umesto toga zaobilazi celu tu klasu tihih pogrešnih prevoda, tako da su brojevi koje uvozite tačno oni brojevi koje je pošiljalac poslednji put video. Cena toga je što oni stižu kao brojevi, a ne kao žive formule koje su ih proizvele.
Način neuspeha oko kog treba dizajnirati rešenje sledi direktno: tabela čiji su ukupni zbirovi bili tačni kada ju je LibreOffice poslednji put sačuvao uvozi se sa tačnim brojevima, ali ti brojevi su sada konstante. Izmenite ulaznu ćeliju, pokrenite preračunavanje i ništa se ne menja – formula je nestala, ostaje samo njen konačni rezultat. Ako tok rada zahteva žive formule nakon uvoza, ponovo ih uspostavite programski iz sopstvenih poslovnih pravila preko Cell.Formula, koja na XLSX fasadi prihvata izraz bez vodećeg znaka jednakosti.
Dizajniranje oko asimetričnog kružnog putovanja
Izvoz se renderuje iz kompletnog modela radne sveske u memoriji: vrednosti, stilovi i, ako ih zatražite, grafikoni i slike. Uvoz vraća samo vrednosti. Dakle, korak od .xlsx do .ods je visoke vernosti, dok korak od .ods do .xlsx vraća vrednosti i keširane rezultate, ali ne i stilove i žive formule. Lančano povežite ova dva smera i asimetrija se usložnjava. Pun ciklus od .xlsx do .ods pa do .xlsx upisuje sve verno na izlazu, a gubi stilove i formule na ulazu nazad, iako ništa nije pošlo naopako ni u jednom koraku.
Book := TXLSXWorkbook.Create;
try
Book.Open('vendor-revision.ods'); // format auto-detected
if Book.SourceFormat = xlsxOpenDocumentSpreadsheet then
begin
// Values and cached formula results are present after an ODS
// import; styles and live formulas are not. Rebuild whatever
// the downstream pipeline depends on before saving.
Book.Sheets[0].Cells[2, 5].Formula := 'SUM(B2:D2)';
Book.SaveAs('vendor-revision.xlsx');
end;
finally
Book.Free;
end;
Arhitektonski šablon koji proizilazi iz ovoga: tretirajte dolazne .ods datoteke kao izvore podataka, a ne kao dokumente koje menjate na licu mesta. Držite kanonsku radnu svesku u .xlsx formatu, čitajte vrednosti iz klijentskih revizija i emitujte sveže ODS datoteke na zahtev iz kanonske kopije. Verifikacija pripada obema stranama – otvorite izvezene datoteke u LibreOffice Calc-u, referentnom potrošaču ODF-a, i u Excel-u, koji godinama čita ODS ali se ne slaže sa LibreOffice-om na granicama podrške za grafikone i stilove. Broj listova, nekoliko ključnih ćelija i prisustvo grafikona čine dovoljnu brzu proveru po izvoznom profilu.
Trijaža ODS datoteke pre započinjanja uvoza
Kada krajnja tačka prihvata otpremanja, izlistavanje naziva listova je daleko jeftinije od kompletnog parsiranja i rano otkriva strukturna iznenađenja:
Names := TStringList.Create;
Book := TXLSXWorkbook.Create;
try
if Book.GetODSSheetNames('incoming.ods', Names) <= 0 then
raise Exception.Create('not a readable ODS package');
if Names.IndexOf('Data') < 0 then
raise Exception.Create('revision is missing the Data sheet');
finally
Book.Free;
Names.Free;
end;
Konvencija vraćanja vrednosti često zbunjuje ljude: HotXLS pozivi uglavnom vraćaju pozitivan broj ili 1 u slučaju uspeha i -1 u slučaju neuspeha, prazneći listu kada ne uspeju, tako da testirate <= 0 umesto poređenja sa jednom specifičnom pozitivnom vrednošću. Metoda GetODSSheetNames niti resetuje niti popunjava instancu radne sveske, tako da jedan objekat sonde može pregledati čitav direktorijum dolaznih datoteka. Strukturne provere poput ove hvataju najčešći neuspeh u stvarnom svetu – kada analitičar preimenuje ili obriše list pre nego što pošalje reviziju nazad – odmah na ulazu, gde poruka o grešci i dalje može imenovati datoteku i list koji nedostaje, umesto da se pojavi kao nil referenca tri nivoa dublje.
Ako gradite širi proces konverzije oko ovoga, šablon za reviziju radne sveske i radni sto za konverziju pokazuje kako da popišete karakteristike datoteke pre nego što izaberete ciljni format, a vodič za performanse velikih radnih svezaka drži grupne izvoze u razumnim granicama memorije.
HotXLS je izvorna Delphi i C++Builder biblioteka za radne tabele sa kompletnim izvornim kodom; kompletna lista funkcija i detalji o licenciranju nalaze se na stranici proizvoda HotXLS komponente.