Technisch artikel

Excel-werkbladen exporteren naar PDF in Delphi zonder Office

Om een Excel-werkblad naar PDF te exporteren vanuit Delphi of C++Builder zonder dat Office is geïnstalleerd, roept u SaveAsPDF aan op een HotXLS-werkblad of -werkmap. HotXLS is een systeemeigen VCL Excel-component, en de werkblad-naar-PDF-export rendert het gebruikte bereik van het blad naar een onafhankelijk PDF 1.4-bestand, waarbij Excel-kolombreedtes en celweergavetekst worden toegewezen aan A4-pagina's met automatische paginering over meerdere pagina's. Geen kopie van Excel, geen printerstuurprogramma en geen externe DLL is betrokken bij het renderen

HotXLS behandelt PDF als een gegevenspresentatie-indeling, een equivalent van zijn CSV-, TSV- en HTML-exportpaden in plaats van een pixel-nauwkeurige rendering-engine. De export reproduceert tabulaire inhoud en lay-out: de waarden die u in het raster ziet, de kolomproporties en de rasterlijnen rond de cellen. Die inkadering is belangrijk omdat deze vooraf een reële verwachting schept, en de rest van dit artikel gaat over waar de grens precies ligt

Hoe converteert u Excel naar PDF in Delphi zonder Office?

De kortste weg is een enkele aanroep. TXLSWorksheet legt SaveAsPDF(FileName) en SaveAsPDF(Stream) bloot, en TXLSWorkbook legt dezelfde twee overloads bloot die doorsturen naar het actieve blad. Elk retourneert een Integer, 1 bij succes en -1 bij mislukking, zodat u kunt vertakken op basis van het resultaat zonder de aanroep in uw eigen uitzonderingsafhandeling te hoeven wikkelen

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;

Wanneer u SaveAsPDF aanroept op een werkblad, HotXLS exporteert dat sheet's UsedRange, de bounding box van elke gevulde cel. De werkmap-overload is een gemak dat delegeert naar het actieve blad, zodat een rapport met meerdere bladen ofwel door de benodigde bladen lusst of het actieve blad selecteert vóór de aanroep. Er is geen volledige werkmap-modus in één keer die elk tabblad aaneenschakelt: elke aanroep rendert één blad of één bereik

Hoe zet HotXLS een gebruikt bereik om in PDF-pagina's?

HotXLS doorloopt het gebruikte bereik cel voor cel en deelt dit in als een gepagineerd raster. De kolomgeometrie komt rechtstreeks uit Excel: elke kolombreedte wordt omgerekend van de Excel-breedte-eenheid naar typografische punten, met een minimale ondergrens zodat geen enkele kolom ineenkrimpt tot een reepje. Wanneer de kolommen samen breder zijn dan de bruikbare pagina, schaalt HotXLS ze uniform kleiner om ze passend te maken; wanneer ze al passen, laat het ze op hun natuurlijke breedte in plaats van ze over het blad uit te rekken

Rijen stromen vervolgens over de pagina naar beneden totdat de volgende de onderste marge zou overschrijden, op welk moment HotXLS een nieuwe pagina opent en doorgaat. Zo wordt een blad met duizend rijen vanzelf gepagineerd zonder dat u paginabreuken hoeft bij te houden. Elke cel drukt zijn FormattedText af, de weergavestring die wordt geproduceerd nadat de getalopmaak is toegepast, zodat een datum wordt getoond zoals het blad deze toont en een valutacel zijn duizendtallen-scheidingstekens en symbool behoudt. Tekst die zijn kolom overschrijdt, wordt afgekapt op de celbreedte in plaats van over te lopen in de buurcel

Richting, marges en lettergrootte beheren

Stuur voor alles wat verder gaat dan de standaardlay-out de exporteur rechtstreeks aan. TXLSPDFExport is de klasse achter de eenregelige helpers, en deze publiceert drie eigenschappen: Orientation (xlsPdfPortrait of xlsPdfLandscape, standaard staand), Margin (punten, standaard 40) en FontSize (punten, standaard 9). Stel ze in voordat u SaveAsPDF aanroept en het hele document neemt ze over

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 accepteert ook een bereik in plaats van een heel blad via SaveAsPDF(Range: IXLSRange; ...), en dat is hoe u een samenvattingsblok exporteert uit een blad dat ook kladberekeningen bevat. Die bereik-overload is dezelfde waarop de werkbladhelper intern leunt, dus de lay-out, schaling en paginering gedragen zich identiek, of u er nu een volledig gebruikt bereik of een handmatig gekozen selectie aan overhandigt

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;

Waarom HotXLS geen lettertype insluit: de Helvetica- en WinAnsi-afweging

HotXLS schrijft de tekst met de in PDF ingebouwde Helvetica en de WinAnsiEncoding, een bewuste keuze zonder afhankelijkheden met één echte beperking. Omdat Helvetica een van de standaard 14 lettertypen is die elke conforme PDF-lezer al bij zich draagt, sluit de exporteur helemaal geen lettertypebestand in: het bestand blijft klein en opent overal, zonder dat er iets gelicentieerd of meegeleverd hoeft te worden. De prijs van die keuze is het karakterrepertoire dat de pagina kan tonen

WinAnsiEncoding dekt de Windows-1252-set, zodat Latijnse tekst, veelvoorkomende interpunctie en de gebruikelijke West-Europese accenten correct worden gerenderd. HotXLS vouwt een handvol typografische tekens, gekrulde aanhalingstekens, en- en em-streepjes en het euroteken in hun CP1252-slots. Tekens buiten dat bereik, zoals CJK-ideogrammen, Cyrillisch, Grieks en Arabisch, vallen op de pagina uiteen tot een vraagteken. Als uw bladen niet-Latijnse tekst bevatten, is deze exporteur het verkeerde hulpmiddel en is een PDF-renderer met volledige styling de taak die past

Waar de werkblad-naar-PDF-export ophoudt

HotXLS rendert inhoud en structuur, niet de volledige visuele stijl van het blad. Celvullingen, randstijlen per zijde, lettertypen en kleuren per cel, grafieken en ingebedde afbeeldingen vallen buiten wat de exporteur tekent; wat u krijgt is het tekstraster met uniforme rasterlijnen. Dat is hetzelfde contract dat de HTML- en RTF-exporteurs respecteren, en het is het juiste contract voor een rapport of een gegevensoverdracht waarbij de getallen de betekenis dragen en het thema dat niet doet

Wanneer het doel een gestyled document is dat consistent is met het merk, is het gebruikelijke patroon om de getallen eerst in een spreadsheetsjabloon te verzamelen, wat de sjabloongestuurde workflow voor rapportgeneratie diepgaand behandelt. En omdat niets hiervan COM of een draaiende Excel-instantie raakt, de pijplijn past in hetzelfde kantoorvrije automatiseringsmodel dat HotXLS overal gebruikt: pure Pascal, inzetbaar op een headless server, zonder interop om te licentiëren of te onderhouden

De onafhankelijke PDF, byte voor byte

HotXLS bouwt de PDF bestandsstructuur met de hand op en berekent de kruisverwijzingstabel (cross-reference table) op basis van exacte byte-offsets, wat de reden is dat de uitvoer in elke lezer opent. Terwijl het elk object serialiseert, HotXLS registreert de begin-offset van dat object voordat het de bytes ervan toevoegt, en schuift vervolgens de lopende positie op met de lengte die het zojuist heeft geschreven. Hierdoor landt de xref-tabel exact op elk object en markeert startxref waar die tabel begint. Een lezer die die offsets zelfs maar één byte verkeerd vindt, weigert het hele bestand. Dit maakt de zelfberekende offset tot het dragende contract van de exporteur

Dat contract brengt één strikte consequentie met zich mee die de moeite waard is om te weten. De Pages-knoop wordt eerst geschreven als object 1, maar de lijst met subpagina's is pas bekend nadat elke pagina is uitgestuurd. HotXLS reserveert deze dus als een tijdelijke aanduiding en voegt de uiteindelijke subpagina's en het aantal in voordat de offset-pass draait, en nooit daarna. Zodra de bytes van een object zijn gemeten voor de xref, worden ze bevroren: het achteraf wijzigen van een enkele byte zou elke volgende offset verschuiven en de tabel beschadigen. Het is een kleine discipline die een aan de normen voldoende PDF 1.4 oplevert zonder dat er een bibliotheek onder ligt

De SaveAsPDF-methoden en de TXLSPDFExport-klasse die hier worden getoond, worden geleverd bij de HotXLS Delphi Excel-component, samen met de CSV-, HTML- en RTF-exporteurs en de volledige werkblad-API voor Delphi en C++Builder