Predstavljajte si nočno opravilo, ki v kodi zgradi delovni zvezek za račune in ga izvozi kot datoteko CSV za uvoz v drug sistem. V Excelu so številke videti pravilne. Datoteka CSV se čisto odpre v urejevalniku besedila. Nadzorni uvoznik pa se nato ustavi pri stolpcu s skupnimi zneski, saj polje za znesek v vrstici 42 vsebuje zapis =SUM(D2:D41), torej formulo kot besedilo in ne končne številke, ki bi jo morala izračunati. Nič ni pokvarjeno. Gre za dokumentirano vedenje in to je prva stvar, ki jo je treba razumeti pri izvozu iz HotXLS: pisalnik serializira model celic natanko takšen, kot je, celica s formulo, katere vrednost ni bila nikoli izračunana, pa ima za oddajo na voljo le besedilo svoje formule.
Zakaj vaša datoteka CSV vsebuje formule namesto številk
HotXLS hrani besedilo formule in izračunano vrednost kom dve ločeni stvari. Funkcija SaveAsCSV med izvozom načrtno ne zažene računskega pogona: izvoz ne bi smel spreminjati delovnega zvezka, prav tako pa ne bi smel tvegati zaustavitve zaradi zapletenih verig formul. Datoteke, ki jih je shranil sam Excel, nosijo predpomnjene rezultate poleg formul, zato ponovni izvoz teh deluje po pričakovanjih. Past je značilna za delovne zvezke, ki jih je ustvarila vaša koda, kjer so bile formule zapisane, a nikoli ovrednotene. Rešitev je v tem, da vrednosti pred izvozom materializirate z istim pogonom Calculate, ki razrešuje sklice med listi in funkcije po meri:
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
R: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('invoice-run.xlsx');
Sheet := Book.Sheets[0];
// Materialize formula results so the CSV carries numbers, not '=...' text
for R := 2 to 41 do
if Sheet.Cells[R, 4].Formula <> '' then
Sheet.Cells[R, 4].Value := Book.Calculate(Sheet.Cells[R, 4].Formula);
Book.SaveAsCSV('feed.csv', 0, ','); // sheet 0, comma
Book.SaveAsCSV('feed.tsv', 0, #9); // same sheet as TSV
finally
Book.Free;
end;
end;
Poglejte, kaj zanka dejansko počne: celice s formulami prepiše z njihovimi izračunanimi vrednostmi. To je povsem pravilno za hiter izvozni prehod in napačno, če želite delovni zvezek pozneje znova shraniti kot .xlsx, saj ste pravkar zamenjali aktivne formule z zamrznjenimi številkami. Izvozite iz kopije ali pa omejite pisanje nazaj le na izvozno opravilo. Pogon, ki stoji za metodo Calculate, ponuja še več, vključno z registracijo lastnih funkcij, kar je tema članka računski pogon HotXLS in funkcije po meri.
Kaj zagotavlja pisalnik z razmejenimi vrednostmi
Izvoz CSV ustvari datoteko v kodiranju UTF-8 z oznako BOM (Byte Order Mark), prelomi vrstic CRLF in navednicami po standardu RFC 4180. Vsako polje, ki vsebuje ločilo, narekovaj ali prelom vrstice, je ovito v narekovaje, vgrajeni narekovaji pa so podvojeni. Datumi se izrišejo v obliki yyyy-mm-dd hh:nn:ss ne glede na obliko prikaza celice. To je pravilna odločitev za strojne porabnike, čeprav lahko preseneti tiste, ki so pričakovali prenos zaslonskega oblikovanja. Celice z obogatenim besedilom se sploščijo z združevanjem njihovih delov.
Te privzete nastavitve rešijo večino težav z uvozniki še pred začetkom, vendar dve izmed njih vseeno sodita v pogodbo o vmesniku. Prva je oznaka BOM. Ta omogoča Excelu, da odpre datoteko s pravilno prikazanimi šumniki in drugimi posebnimi znaki, vendar jo nekateri strogi razčlenjevalniki obravnavajo kot podatke; če je vaš med njimi, te tri bajte ob predaji odstranite. Druga je TSV. To sploh ni ločena funkcija, temveč le isti pisalnik, poklican z ločilom #9, zato vse zgoraj navedeno velja tudi zanjo. List za izvoz izberete z indeksom, osnovanim na 0, v preobremenitvi z več parametri, medtem ko skrajšana oblika z enim parametrom SaveAsCSV(FileName) prevzame aktivni list.
Izvoz HTML je posnetek stanja in ne format za izmenjavo
Medtem ko CSV zavrže vse razen vrednosti, poskuša SaveAsHTML to keep the appearance: ena tabela <table> na list, združena območja, izražena kot colspan in rowspan, ter osnovno oblikovanje celic, vgrajeno kot CSS. Barve, odvisne od teme, se raje preskočijo kot razrešijo, zato je predloga, ki se zanaša na teme, videti preprostejša kot v Excelu. Nastavite eksplicitne barve RGB na vsem, kar mora preživeti pretvorbo. Objekt možnosti nadzoruje ovojnico:
var
Opts: TXLSXHtmlExportOptions;
begin
Opts := TXLSXHtmlExportOptions.Create;
try
Opts.Title := 'Weekly settlement';
Opts.TableClass := 'report-grid'; // hook for the host page stylesheet
Opts.WriteDocument := True; // full page, not a fragment
if Book.SaveAsHTML('settlement.html', 0, Opts) <> 0 then
raise Exception.Create('Sheet index out of range');
finally
Opts.Free;
end;
end;
V tem izseku sta dve podrobnosti, ki si zaslužita pozornost. Nastavite WriteDocument na False in izpis postane le fragment tabele namesto celotne strani, kar je uporabno pri vstavljanju predogleda v obstoječo postavitev: nastavite TableClass in prepustite oblikovanje slogovni predlogi gostitelja. Konvencija o povratni vrednosti je prav tako nasprotna večini klicem v HotXLS. Funkcija SaveAsHTML vrne 0 ob uspehu in -1 ob napačnem indeksu lista, zato bo preverjanje z = 1 vsak uspešen izvoz označilo kot napako. Osnovno pravilo velja tudi za določena območja: ko potrebujete le določeno območje namesto celotnega lista (npr. za pošiljanje po e-pošti ali vdelavo enega bloka), TXLSXRange.SaveAsHTML izvozi poljuben pravokoten obseg pod enakimi pravili izrisa.
Izpis RTF in kje še vedno najde svoje mesto
Četrti cilj zapisuje tabele RTF 1.6, in sicer en list na klic prek SaveAsRTF. Širine stolpcev so približno določene na 96 twipov na znak širine stolpca. Strukturna omejitev, ki jo morate poznati, je, da se združene celice v izpisu ne raztezajo: le sidrna celica vsebuje vsebino, prekrite celice pa so prazne. To izključuje RTF za zapletene predloge s postavitvijo. Vseeno pa najde svoje mesto kot najpreprostejša pot za vstavljanje tabelaričnih rezultatov v urejevalnik besedil ali v starejše sisteme za upravljanje dokumentov, ki ne podpirajo uvoza HTML.
Krožno potovanje: uvoz CSV je destruktiven s ciljem
Ponovno branje datotek CSV ima lastna pravila. Metoda OpenCSV počisti celoten delovni zvezek in ga znova zgradi kot en sam list z imenom Sheet1. Po naravi gre za konstruktor in ne za združevanje, zato je nikoli ne kličite na delovnem zvezku, ki še vsebuje neshranjeno vsebino. Če kot ločilo posredujete #0, se sproži samodejno zaznavanje ločila. Zastavica ADetectTypes nadzoruje pretvorbo tipov: ko je vklopljena, se številčni nizi pretvorijo v številke, nizi ISO-8601 v datume, vrednosti true/false pa v logične vrednosti. Izklopite jo, kadar podatki vsebujejo identifikatorje z vodilnimi ničlami, poštnimi številkami ali kodami izdelkov, saj jih ta pretvorba tiho spremeni v številke (vodilna ničla izgine v trenutku, ko se 00123 spremeni v 123). Oba vmesnika ponujata enak uvoz. Povežite ga z zgornjimi klici za izvoz in dobili boste formatni most, ki ne potrebuje nameščenega Excela v cevovodu, kar je scenarij, opisan v članku generiranje poročil iz podatkovne baze v Excel s HotXLS.
Izvoz neposredno v tok (stream)
Vsak pisalnik tukaj ponuja tudi preobremenitev za tok poleg različice z imenom datoteke: to velja za CSV, HTML, RTF in same formate delovnih zvezkov. V strežniški kodi so te preobremenitve najboljša izbira. Spletna točka, ki ponuja prenos CSV, lahko piše neposredno v TMemoryStream in to preda objektu odziva – brez začasne datoteke, brez čiščenja in brez trkov med dvema zahtevama, ki bi izbrali enako ime datoteke. Enake ugodnosti ponuja tudi pošiljanje izvozov v shrambo blob ali pripenjanje k odhodni e-pošti. Datotečni sistem v celoti izgine iz slike.
Ta vzorec se dopolnjuje s tem, kako se knjižnica uvaja. Oba vmesnika sta izvorna bralnika in pisalnika za Object Pascal, zato ni potrebe po namestitvi Excela, avtomatizaciji COM ali ozkem grlu pri serializaciji zahtev na strežniku. Vsaka zahteva ima lahko lasten objekt delovnega zvezka, zažene izračun iz prvega razdelka in pretoči izvoz vzporedno z ostalimi. Pomnilnik je edini vir, na katerega morate biti pozorni. Model delovnega zvezka med izvozom živi v pomnilniku RAM, zato bi morala storitev, ki odpira zelo velike datoteke le za ponovni izvoz v CSV, omejiti število vzporednih opravil ali pa prevelika opravila postaviti v vrsto, namesto da bi prometna konica določala porabo pomnilnika.
Majhna nastavitev: nastavite IncludeBOM v možnostih HTML, ko bo fragment shranjen kot samostojna datoteka, ki jo drugo orodje pregleduje glede kodiranja. Ko HTML ponujate neposredno prek HTTP, raje prepustite deklaracijo nabora znakov glavam odziva.
Ko so bajti še vedno napačni
Najpogostejše vprašanje za podporo glede izvoza CSV is the opening problem in a different costume: Excel prikaže nečitljive znake (mojibake) namesto šumnikov. Prvi vzgib je kriviti pisalnik, vendar ta prav zato izpiše oznako UTF-8 BOM, datoteka pa je skoraj vedno pravilna, ko zapusti vašo kodo. Nekaj vmes je moralo odstraniti oznako BOM. Prenos FTP v tekstovnem načinu, kopiranje toka, ki preskoči prve tri bajte, ali posredniški strežnik (proxy), ki spremeni kodiranje: karkoli od tega odstrani oznako in pusti Excelu, da ugiba kodiranje, kar pa počne slabo. Težavo diagnosticirajte na meji in ne v samem izvoznem klicu. Odprite prejeto datoteko v heksadecimalnem pregledovalniku in se prepričajte, da je EF BB BF še vedno na samem začetku.
To je skupna rdeča nit za vse štiri formate. Izvozni klic je enostaven del, HotXLS pa sprejme premišljene odločitve pri vsakem koraku pisalnika. Težave se pojavijo na stikih: koder se besedilo formule sreča z razčlenjevalnikom, ki želi številko, koder se oznaka BOM sreča s prenosom, ki je ne ohrani, ali koder se združena celica sreča z RTF-modelom ravne tabele. Vsako od teh dejstev morate zapisati v pogodbo med vašim izvoznikom in porabnikom podatkov, saj porabnik ne lahko prebere vaših namenov iz samih bajtov. Za celoten seznam metod na obeh vmesnikih delovnih zvezkov obiščite stran izdelka HotXLS Component, ki vsebuje celotno referenco.