Teknisk artikel

Exportera Excel-kalkylblad till PDF i Delphi utan Office

För att exportera ett Excel-kalkylblad till PDF från Delphi eller C++Builder utan installerat Office, anropa SaveAsPDF på ett HotXLS-kalkylblad eller en arbetsbok. HotXLS är en inbyggd VCL-Excel-komponent, och dess export från kalkylblad till PDF renderar bladets använda område till en självförsörjande PDF 1.4-fil, och mappar Excels kolumnbredder och cellernas visningstext på A4-sidor med automatisk paginering över flera sidor. Ingen kopia av Excel, ingen skrivardrivrutin och ingen extern DLL deltar i renderingen

HotXLS behandlar PDF som ett format för datapresentation, ett syskon till sina exportvägar för CSV, TSV och HTML snarare än en bildpunktsexakt renderingsmotor. Exporten återger tabellinnehåll och layout: värdena du ser i rutnätet, kolumnproportionerna och stödlinjerna runt cellerna. Den inramningen spelar roll eftersom den sätter en ärlig förväntan från början, och resten av den här artikeln handlar om exakt var gränsen går

Hur konverterar du Excel till PDF i Delphi utan Office?

Den kortaste vägen är ett enda anrop. TXLSWorksheet exponerar SaveAsPDF(FileName) och SaveAsPDF(Stream), och TXLSWorkbook exponerar samma två överlagringar som skickar vidare till det aktiva bladet. Var och en returnerar ett Integer, 1 vid framgång och -1 vid misslyckande, så du kan grena på resultatet utan att linda anropet i egen undantagshantering

uses
  lxHandle;

var
  Book: TXLSWorkbook;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('sales-june.xlsx');
    // Rendera det aktiva bladets använda område rakt till report.pdf.
    if Book.SaveAsPDF('report.pdf') = 1 then
      Writeln('PDF written');
  finally
    Book.Free;
  end;
end;

När du anropar SaveAsPDF på ett kalkylblad exporterar HotXLS det bladets UsedRange, den omslutande rutan runt varje ifylld cell. Arbetsboksöverlagringen är en bekvämlighet som delegerar till det aktiva bladet, så en rapport med flera blad antingen loopar över de blad den behöver eller väljer det aktiva bladet före anropet. Det finns inget läge för hela arbetsboken i ett svep som slår ihop varje flik: varje anrop renderar ett blad eller ett område

Hur gör HotXLS ett använt område till PDF-sidor?

HotXLS går igenom det använda området cell för cell och sätter det som ett paginerat rutnät. Kolumngeometrin kommer rakt från Excel: varje kolumnbredd konverteras från Excels breddenhet till typografiska punkter, med ett minsta golv så att ingen kolumn kollapsar till en strimma. När kolumnerna tillsammans är bredare än den användbara sidan skalar HotXLS ned dem enhetligt så att de får plats; när de redan får plats lämnar den dem vid sin naturliga bredd snarare än att sträcka ut dem över arket

Raderna flyter sedan ned för sidan tills nästa skulle korsa nedre marginalen, varvid HotXLS öppnar en ny sida och fortsätter, så ett blad på tusen rader pagineras av sig självt utan sidbrytningsbokföring från din sida. Varje cell trycker sin FormattedText, den visningssträng som framställs efter att talformatet tillämpats, så ett datum visas som det datum bladet visar och en valutacell behåller sina tusentalsavskiljare och sin symbol. Text som spiller ut ur sin kolumn klipps till cellbredden istället för att rinna in i grannen

HotXLS Delphi-diagram över SaveAsPDF som paginerar ett kalkylblads använda område över flera A4-PDF-sidor
SaveAsPDF renderar det använda området med Excels kolumngeometri och automatisk paginering — raderna flyter till en ny sida när nästa rad skulle korsa nedre marginalen

Att styra orientering, marginaler och teckenstorlek

För allt bortom standardlayouten, styr exportören direkt. TXLSPDFExport är klassen bakom enradshjälparna, och den publicerar tre egenskaper: Orientation (xlsPdfPortrait eller xlsPdfLandscape, stående som standard), Margin (punkter, standard 40) och FontSize (punkter, standard 9). Sätt dem innan du anropar SaveAsPDF så plockar hela dokumentet upp 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;  // få breda blad att rymmas på sidan
      Exporter.Margin := 28;                     // snävare sidmarginal, i punkter
      Exporter.FontSize := 8;                    // tätare rader
      Exporter.SaveAsPDF(Book.ActiveSheet, 'ledger.pdf');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

TXLSPDFExport accepterar också ett område istället för ett helt blad genom SaveAsPDF(Range: IXLSRange; ...), vilket är hur du exporterar ett sammanfattningsblock ur ett blad som också håller kladdberäkningar. Den områdesöverlagringen är samma som kalkylbladshjälparen lutar sig mot internt, så layout, skalning och paginering beter sig identiskt vare sig du ger den ett fullständigt använt område eller ett handplockat urval

var
  Book: TXLSWorkbook;
  Exporter: TXLSPDFExport;
  Summary: IXLSRange;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('quarter.xlsx');
    // Exportera bara sammanfattningsblocket, inte kladdkolumnerna bredvid.
    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;

Varför HotXLS bäddar in inget typsnitt: avvägningen med Helvetica och WinAnsi

HotXLS skriver texten med PDF:ens inbyggda Helvetica och WinAnsiEncoding, ett medvetet val utan beroenden med en verklig gräns. Eftersom Helvetica är ett av de fjorton standardtypsnitt varje regelrätt PDF-läsare redan bär, bäddar exportören inte in något typsnittsprogram alls: filen förblir liten och öppnas var som helst, utan något att licensiera eller skicka med. Kostnaden för det valet är den teckenrepertoar sidan kan visa

WinAnsiEncoding täcker uppsättningen Windows-1252, så latinsk text, vanlig interpunktion och de sedvanliga västeuropeiska accenterna renderas korrekt, och HotXLS viker in en handfull typografiska tecken, böjda citattecken, tankstreck av en- och em-typ samt eurotecknet, i deras CP1252-platser. Tecken utanför det intervallet, CJK-ideogram, kyrilliska, grekiska och arabiska, kollapsar till ett frågetecken på sidan. Om dina blad bär icke-latinsk text är den här exportören fel verktyg, och en PDF-renderare med fullständig styling är det jobb som passar

HotXLS Delphi-diagram över den WinAnsi-teckenrepertoar som den inbyggda Helvetica-PDF-exporten använder
PDF-exporten bäddar inte in något typsnitt och skriver inbyggd Helvetica med WinAnsiEncoding — tecken utanför Windows-1252 kollapsar till ett frågetecken på sidan

Var exporten från kalkylblad till PDF stannar

HotXLS renderar innehåll och struktur, inte bladets fullständiga visuella stil. Cellfyllningar, kantlinjestilar per sida, typsnitt och färger per cell, diagram och inbäddade bilder ligger utanför vad exportören ritar; vad du får är textrutnätet med enhetliga stödlinjer. Det är samma kontrakt som HTML- och RTF-exportörerna håller, och det är rätt kontrakt för en rapport eller en dataöverlämning där siffrorna bär betydelsen och temat inte gör det

När målet är ett stylat, varumärkeskonsekvent dokument är det vanliga mönstret att först ställa samman siffrorna i en kalkylbladsmall, vilket arbetsflödet för malldriven rapportgenerering täcker på djupet. Och eftersom inget av det här rör COM eller en körande Excel-instans passar pipelinen in i samma Office-fria automationsmodell som HotXLS använder rakt igenom: ren Pascal, driftsättbar på en huvudlös server, utan någon interop att licensiera eller passa

Den självförsörjande PDF:en, byte för byte

HotXLS bygger PDF-filstrukturen för hand och beräknar dess korsreferenstabell ur exakta byteoffset, vilket är skälet till att utdatan öppnas i varje läsare. Allteftersom den serialiserar varje objekt registrerar HotXLS det objektets startoffset innan dess byte läggs till, och flyttar sedan fram den löpande positionen med den längd den just skrev, så att xref-tabellen landar precis på varje objekt och startxref markerar var den tabellen börjar. En läsare som finner de offseten ens en byte fel avvisar hela filen, vilket gör det självberäknade offsetet till exportörens bärande kontrakt

Det kontraktet bär en strikt följd värd att känna till. Pages-noden skrivs först som objekt 1, men dess lista av barnsidor är inte känd förrän varje sida avgetts, så HotXLS reserverar den som en platshållare och lappar in de slutliga barnen och antalet innan offsetpasset körs, aldrig efter. När ett objekts byte väl mätts för xref-tabellen är de frysta: att ändra en enda byte efteråt skulle förskjuta varje följande offset och korrumpera tabellen. Det är en liten disciplin som köper en standardgiltig PDF 1.4 utan något bibliotek under sig

HotXLS Delphi-diagram över självberäknade byteoffset som matar PDF:ens xref-tabell under SaveAsPDF-serialiseringen
HotXLS registrerar varje objekts offset innan dess byte läggs till — allt som mätts för xref-tabellen är fryst så att tabellen förblir exakt

Metoderna SaveAsPDF och klassen TXLSPDFExport som visas här levereras med HotXLS Delphi Excel Component, jämte exportörerna för CSV, HTML och RTF och det fullständiga kalkylblads-API:et för Delphi och C++Builder