Se for deg en nattlig jobb som bygger en fakturaarbeidsbok i kode og skriver den ut som CSV for at et nedstrøms system skal importere den. Tallene ser riktige ut i Excel. CSV-en åpner rent i en teksteditor. Deretter kveles importøren på totalkolonnen, fordi beløpsfeltet for rad 42 leser =SUM(D2:D41), formelen som bokstavelig tekst, ikke tallet den skulle beregne seg til. Ingenting er ødelagt. Dette er dokumentert oppførsel, og det er det første å forstå om eksport fra HotXLS: skriveren serialiserer cellemodellen nøyaktig slik den står, og en formelcelle hvis verdi aldri ble beregnet, har bare formelteksten sin å levere fra seg
Hvorfor CSV-en din inneholder formler i stedet for tall
HotXLS lagrer formeltekst og beregnet verdi som to atskilte ting. SaveAsCSV kjører ikke beregningsmotoren på vei ut, med hensikt: en eksport skal ikke mutere arbeidsboken, og den skal ikke risikere å henge seg opp i en patologisk formelkjede. Filer som Excel selv lagret, bærer bufrede resultater ved siden av formlene, så gjeneksport av dem oppfører seg slik du forventer. Fellen er spesifikk for arbeidsbøker koden din selv genererte, der formler ble skrevet, men aldri evaluert. Løsningen er å få verdiene til å eksistere før du eksporterer, ved å bruke den samme Calculate-motoren som løser arkkryssende referanser og egendefinerte funksjoner:
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
R: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('invoice-run.xlsx');
Sheet := Book.Sheets[0];
// Materialiser formelresultater slik at CSV-en bærer tall, ikke '=...'-tekst
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, ','); // ark 0, komma
Book.SaveAsCSV('feed.tsv', 0, #9); // samme ark som TSV
finally
Book.Free;
end;
end;
Legg merke til hva løkken faktisk gjør: den overskriver formelcellene med sine beregnede verdier. Det er akkurat riktig for en engangs eksportrunde og feil hvis du har tenkt å lagre arbeidsboken igjen som .xlsx etterpå, fordi du nettopp har erstattet levende formler med fastfrosne tall. Eksporter fra en kopi, eller avgrens tilbakeskrivingen slik at den bare berører eksportkjøringen. Motoren bak Calculate går lenger enn dette, blant annet ved å registrere dine egne funksjoner, som er temaet for HotXLS-formelmotoren og egendefinerte funksjoner
Hva den avgrensede skriveren garanterer
CSV-stien produserer UTF-8 med en byte order mark, CRLF-linjeskift og RFC 4180-sitering. Ethvert felt som inneholder skilletegnet, et anførselstegn eller et linjeskift, blir pakket inn, og innebygde anførselstegn dobles. Datoer gjengis som yyyy-mm-dd hh:nn:ss uansett cellens visningsformat. Det er det riktige valget for en maskinkonsument, selv om det overrasker alle som forventet at skjermformateringen skulle bli med. Rich text-celler flates ut ved å slå sammen strekkene deres
Disse standardvalgene avgjør de fleste stridighetene med en importør før de starter, men to av dem hører uansett hjemme i grensesnittkontrakten din. Den første er BOM-en. Det er den som lar Excel åpne filen med aksenttegn intakte, likevel behandler en håndfull strenge parsere de tre bytene som data; hvis din er en av dem, fjern dem i overleveringen. Den andre er TSV. Det er ikke en egen funksjon i det hele tatt, bare den samme skriveren kalt med #9 som skilletegn, så alt ovenfor gjelder uendret for den. Arket som eksporteres, velges med en 0-basert indeks i overbelastningen med flere argumenter, mens snarveien med ett argument, SaveAsCSV(FileName), tar det aktive arket
HTML-eksport er et øyeblikksbilde, ikke et utvekslingsformat
Der CSV kaster bort alt utenom verdier, prøver SaveAsHTML å beholde utseendet: én <table> per ark, sammenslåtte områder uttrykt som colspan og rowspan, grunnleggende cellestiling satt inline som CSS. Temarelative farger hoppes over i stedet for å løses, så en mal som lener seg på temaplasser, kommer ut mer nøkternt enn den ser ut i Excel. Sett eksplisitte RGB-farger på alt som må overleve turen. Options-objektet styrer konvolutten:
var
Opts: TXLSXHtmlExportOptions;
begin
Opts := TXLSXHtmlExportOptions.Create;
try
Opts.Title := 'Weekly settlement';
Opts.TableClass := 'report-grid'; // krok for vertssidens stilark
Opts.WriteDocument := True; // hel side, ikke et fragment
if Book.SaveAsHTML('settlement.html', 0, Opts) <> 0 then
raise Exception.Create('Sheet index out of range');
finally
Opts.Free;
end;
end;
To detaljer i det utdraget er verdt oppmerksomhet. Sett WriteDocument til False, og utdataene blir et bart tabellfragment i stedet for en hel side, som er det du vil ha når du injiserer en forhåndsvisning inn i et eksisterende oppsett: sett TableClass og la vertsstilarket gjøre temaarbeidet. Returkonvensjonen er også omvendt av de fleste HotXLS-kall. SaveAsHTML returnerer 0 ved suksess og -1 for en ugyldig arkindeks, så en vanebasert sjekk for = 1 vil rapportere hver vellykket eksport som en feil. Når du trenger et område i stedet for et helt ark, kanskje for å sende på e-post eller bygge inn en enkelt blokk, eksporterer TXLSXRange.SaveAsHTML et hvilket som helst rektangulært område under de samme rendringsreglene
RTF-utdata og hvor det fortsatt fortjener sin plass
Det fjerde målet skriver RTF 1.6-tabeller, ett ark per kall gjennom SaveAsRTF. Kolonnebredder tilnærmes til omtrent 96 twips per tegn kolonnebredde. Den strukturelle begrensningen å kjenne til, er at sammenslåtte celler ikke spenner over i utdataene: bare ankercellen bærer innholdet sitt, og de dekkede cellene sendes ut som tomme. Det utelukker RTF for oppsettstunge maler. Det fortjener likevel sin plass som veien med minst motstand for å slippe tabelldata inn i en tekstbehandler eller inn i et eldre dokumenthåndteringssystem som kom før HTML-inntak
Tur-retur: import av CSV er destruktiv med hensikt
Å lese CSV tilbake inn har sin egen kontrakt. OpenCSV tømmer hele arbeidsboken og bygger den opp igjen som ett enkelt ark ved navn Sheet1. Den er en konstruktør i ånden, ikke en sammenslåing, så kall den aldri på en arbeidsbok som fortsatt bærer ulagret innhold. Å sende #0 som skilletegn utløser automatisk gjenkjenning av skilletegn. ADetectTypes-flagget styrer typeopprykk: med det på blir numeriske strenger til tall, ISO-8601-strenger til datoer, og true/false til boolske verdier. Slå det av når kildedataene bærer identifikatorer med innledende nuller, postnumre eller produktkoder, som alle blir stille ødelagt til tall av opprykket (en innledende null er rett og slett borte i det øyeblikket 00123 blir 123). Begge fasadene eksponerer samme import. Kombiner den med eksportkallene ovenfor, og du har en formatbro som ikke trenger Excel installert noe sted i pipelinen, scenarioet dekket i databasetil-Excel-rapportgenerering med HotXLS
Eksport rett inn i en strøm
Hver skriver her har en strømoverbelastning ved siden av filnavn-versjonen: CSV, HTML, RTF og selve arbeidsbokformatene. I serverkode er det de overbelastningene du skal gripe til. Et web-endepunkt som serverer en CSV-nedlasting, kan skrive inn i en TMemoryStream og gi den rett videre til responsobjektet, uten noen midlertidig fil, ingen opprydningsjobb, og ingen kollisjon mellom to forespørsler som tilfeldigvis valgte samme genererte navn. Det samme gjelder for å skyve eksporter inn i blob-lagring eller feste dem til utgående e-post. Filsystemet faller helt ut av bildet
Det mønsteret forsterkes av hvordan biblioteket driftsettes. Begge fasadene er native Object Pascal-lesere og -skrivere, så det er ingen Excel-installasjon, ingen COM-automatisering, og ingen per-prosess-flaskehals som serialiserer forespørsler på serveren. Hver forespørsel kan eie sitt eget arbeidsbokobjekt, kjøre beregnings-tilbakeskrivingen fra den første seksjonen, og strømme eksporten sin parallelt med naboene sine. Minne er den ene ressursen å holde øye med. Arbeidsbokmodellen lever i RAM for varigheten av eksporten, så en tjeneste som åpner svært store filer bare for å sende dem ut igjen som CSV, bør sette et tak på samtidige jobber, eller sette de for store i kø, i stedet for å la en trafikktopp bestemme arbeidssettet
Én mindre bryter: sett IncludeBOM på HTML-alternativene når fragmentet skal lagres som en frittstående fil som et verktøy nedstrøms snuser på for koding. Når du serverer HTML direkte over HTTP, la heller charset-deklarasjonen ligge til responshodene
Når bytene fortsatt kommer ut feil
Det vanligste supportspørsmålet om CSV-eksport er åpningsproblemet i en annen drakt: Excel viser tegnsøppel i stedet for aksenttegn. Instinktet er å skylde på skriveren, men den sender ut en UTF-8-BOM nettopp av denne grunnen, og filen er nesten alltid korrekt når den forlater koden din. Noe mellom der og Excel har spist BOM-en. En FTP-overføring i tekstmodus, en strømkopi som hopper over de tre første bytene, en proxy som koder om underveis: hvilken som helst av disse vil fjerne markøren og la Excel gjette på kodingen, noe den gjør dårlig. Diagnostiser dette ved grensesnittet, ikke i eksportkallet. Åpne den leverte filen i en hex-viewer og bekreft at EF BB BF fortsatt er det første i den
Det er den røde tråden gjennom alle fire formatene. Eksportkallet er den enkle delen, og HotXLS tar et forsvarlig valg ved hver beslutning skriveren står overfor. Feilene bor i skjøtene, der formeltekst møter en parser som ønsket seg et tall, der en BOM møter en transport som ikke bevarer den, der en sammenslått celle møter RTF-ens flate tabellmodell. Hver av dem er et faktum å skrive inn i kontrakten mellom eksportøren din og det som konsumerer den, fordi konsumenten ikke kan lese intensjonene dine ut av bytene. For den fullstendige metodelisten på tvers av begge arbeidsbokfasadene, bærer produktsiden for HotXLS Delphi Component hele referansen