Teknisk artikel

Eksporter Excel-regneark til PDF i Delphi uden Office

For at eksportere et Excel-regneark til PDF fra Delphi eller C++Builder uden Office installeret kaldes SaveAsPDF på et HotXLS-regneark eller en projektmappe (workbook). HotXLS is en indfødt VCL Excel-komponent, og dens regneark-til-PDF-eksport gengiver regnearkets anvendte område til en selvstændig PDF 1.4-fil, som kortlægger Excel-kolonnebredder og cellevist tekst på A4-sider med automatisk sideinddeling over flere sider. Hverken en kopi af Excel, en printerdriver eller en ekstern DLL deltager i gengivelsen

HotXLS behandler PDF som et datapræsentationsformat, en søskende til dens CSV-, TSV- og HTML-eksportveje, snarere end en pixel-nøjagtig gengivelsesmotor. Eksporten gengiver tabelindhold og layout: de værdier, du ser i gitteret, kolonneforholdene og gitterlinjerne omkring cellerne. Den ramme har betydning, fordi den sætter en ærlig forventning på påhånd, og resten af denne artikel handler om præcis, hvor grænsen går

Hvordan konverterer du Excel til PDF i Delphi uden Office?

Den korteste vej er et enkelt kald. TXLSWorksheet eksponerer SaveAsPDF(FileName) og SaveAsPDF(Stream), og TXLSWorkbook eksponerer de samme to overbelastninger (overloads), der videresender til det aktive ark. Hver af dem returnerer en Integer, 1 ved succes og -1 ved fejl, så du kan forgrene koden baseret på resultatet uden at pakke kaldet ind i din egen undtagelseshåndtering

uses
  lxHandle;

var
  Book: TXLSWorkbook;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('sales-june.xlsx');
    // Render the active sheet's used range straight to report.pdf.
    if Book.SaveAsPDF('report.pdf') = 1 then
      Writeln('PDF written');
  finally
    Book.Free;
  end;
end;

Når du kalder SaveAsPDF på et regneark, eksporterer HotXLS det arks UsedRange, som er afgrænsningsboksen (bounding box) for hver udfyldt celle. Overbelastningen på projektmappen er en bekvemmelighed, der delegerer til det aktive ark, så en rapport med flere ark enten skal køre i en løkke over de ark, den har brug for, eller vælge det aktive ark før kaldet. Der er ingen tilstand for hele projektmappen (alt-i-én-gennemgang), der sammenkæder hver fane: hvert kald gengiver ét ark eller ét område

Hvordan gør HotXLS et anvendt område til PDF-sider?

HotXLS gennemgår det anvendte område celle for celle og layouter det som et sideinddelt gitter. Kolonnegeometrien kommer direkte fra Excel: hver kolonnebredde konverteres fra Excels breddeenhed til typografiske punkter, med en minimumsgrænse, så ingen kolonne kollapser til en tynd stribe. Når kolonnerne tilsammen er bredere end den anvendelige side, skalerer HotXLS dem ensartet ned, så de passer; når de allerede passer, lader den dem beholde deres naturlige bredde i stedet for at strække dem ud over arket

Rækkerne flyder derefter ned ad siden, indtil den næste række ville krydse den nederste margen, hvorpå HotXLS åbner en ny side og fortsætter, så et ark med tusind rækker sideinddeles af sig selv uden behov for bogføring af sideskift fra din side. Hver celle udskriver sin FormattedText, som er den visningsstreng, der produceres efter talformatering er anvendt, så en dato vises som den dato, arket viser, og en valutacelle bevarer sine tusindtalsseparatorer og symbol. Tekst, der overskrider sin kolonne, klippes til cellebredden i stedet for at flyde over i nabocellen

Styring af retning, margener og skriftstørrelse

For alt ud over standardlayoutet kan du styre eksportøren direkte. TXLSPDFExport er klassen bag en-linjes hjælperne, og den publicerer tre egenskaber: Orientation (xlsPdfPortrait eller xlsPdfLandscape, stående som standard), Margin (punkter, standard 40) og FontSize (punkter, standard 9). Indstil dem, før du kalder SaveAsPDF, så vil hele dokumentet anvende dem

uses
  lxHandle, lxPDF;

var
  Book: TXLSWorkbook;
  Exporter: TXLSPDFExport;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('wide-ledger.xlsx');
    Exporter := TXLSPDFExport.Create;
    try
      Exporter.Orientation := xlsPdfLandscape;  // fit wide sheets on the page
      Exporter.Margin := 28;                     // tighter page margin, in points
      Exporter.FontSize := 8;                    // denser rows
      Exporter.SaveAsPDF(Book.ActiveSheet, 'ledger.pdf');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

TXLSPDFExport accepterer også et område i stedet for et helt ark via SaveAsPDF(Range: IXLSRange; ...), hvilket er måden, hvorpå du eksporterer en sammenfatningsblok ud af et ark, der også indeholder kladderegninger. Den område-overbelastning er den samme, som regnearkshjælperen læner sig op ad internt, så layout, skalering og sideinddeling opfører sig identisk, uanset om du giver den et fuldt anvendt område eller et håndplukket udvalg

var
  Book: TXLSWorkbook;
  Exporter: TXLSPDFExport;
  Summary: IXLSRange;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('quarter.xlsx');
    // Export only the summary block, not the scratch columns beside it.
    Summary := Book.Sheets[1].Range['A1', 'F20'];
    Exporter := TXLSPDFExport.Create;
    try
      Exporter.SaveAsPDF(Summary, 'summary.pdf');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

Hvorfor HotXLS ikke indlejrer nogen skrifttype: Helvetica- og WinAnsi-kompromiset

HotXLS skriver teksten med PDF'ens indbyggede Helvetica og WinAnsiEncoding, hvilket er et bevidst valg uden eksterne afhængigheder med én reel begrænsning. Da Helvetica er en af de 14 standardskrifttyper, som enhver kompatibel PDF-læser allerede har, indlejrer eksportøren slet ingen skrifttypefil: filen forbliver lille og kan åbnes overalt, uden noget at licensere eller levere ved siden af. Prisen for det valg er det tegnrepertoire, siden kan vise

WinAnsiEncoding dækker Windows-1252-tegnsættet, så latinsk tekst, almindelig tegnsætning og de sædvanlige vesteuropæiske accenter gengives korrekt, og HotXLS folder en håndfuld typografiske tegn, krøllede anførselstegn, en- og em-tankestreger samt euro-tegnet ind i deres CP1252-pladser. Tegn uden for det interval, såsom CJK-ideogrammer, kyrillisk, græsk og arabisk, falder sammen til et spørgsmålstegn på siden. Hvis dine ark indeholder ikke-latinsk tekst, er denne eksportør det forkerte værktøj, og en fuldt stilet PDF-gengiver er det job, der passer

Hvor regneark-til-PDF-eksporten stopper

HotXLS gengiver indhold og struktur, ikke regnearkets fulde visuelle stil. Celleudfyldninger, kantstile pr. kant, skrifttyper og farver pr. celle, diagrammer og indlejrede billeder ligger uden for, hvad eksportøren tegner; det, du får, er tekstgitteret med ensartede gitterlinjer. Det er den samme kontrakt, som HTML- og RTF-eksportørerne overholder, og den er den rigtige til en rapport eller en dataoverdragelse, hvor tallene bærer betydningen, og temaet ikke gør

Når målet er et stilet, brand-konsistent dokument, er det sædvanlige mønster at samle tallene i en regnearksskabelon først, hvilket den skabelondrevet rapportgenerering dækker i dybden. Og fordi intet af dette berører COM eller en kørende Excel-instans, passer pipelinen til den samme Office-fri automatiseringsmodel, som HotXLS bruger overalt: ren Pascal, som kan distribueres på en headless-server, uden interop at licensere eller passe på

Den selvstændige PDF, byte for byte

HotXLS bygger PDF-filstrukturen i hånden og beregner dens krydsreferencetabel ud fra præcise byte-forskydninger (offsets), hvilket er årsagen til, at outputtet kan åbnes i enhver læser. Efterhånden som den serialiserer hvert objekt, HotXLS registrerer det objekts startforskydning, før dens bytes tilføjes, og rykker derefter den løbende position frem med den længde, den lige har skrevet, så xref-tabellen lander præcist på hvert objekt, og startxref markerer, hvor tabellen begynder. En læser, der finder disse forskydninger blot én byte forkert, afviser hele filen, hvilket gør den selvberegnede forskydning til eksportørens bærende kontrakt

Den kontrakt medfører en streng konsekvens, som er værd at kende. Sidenoden (Pages) skrives først som objekt 1, men dens liste over underordnede sider er ikke kendt, før hver side er udsendt, så HotXLS reserverer den som en pladsholder og lapper de endelige underordnede (kids) og antallet ind, før forskydningsgennemgangen kører, aldrig efter. Når et objekts bytes først er målt til xref, er de frosset: at ændre en enkelt byte efterfølgende ville forskyde hver efterfølgende forskydning og beskadige tabellen. Det er een lille disciplin, der sikrer en standard-gyldig PDF 1.4 uden noget bibliotek under sig

SaveAsPDF-metoderne og TXLSPDFExport-klassen vist her leveres sammen med HotXLS Delphi Excel Component, sammen med CSV-, HTML- og RTF-eksportørerne og det fulde regnearks-API til Delphi og C++Builder