Aby wyeksportować arkusz Excela do pliku PDF z poziomu Delphi lub C++Builder bez zainstalowanego pakietu Office, wywołaj metodę SaveAsPDF na arkuszu lub skoroszycie HotXLS. HotXLS jest natywnym komponentem Excel dla VCL, a jego eksport z arkusza do PDF renderuje używany zakres arkusza do samodzielnego pliku PDF 1.4, mapując szerokości kolumn programu Excel i wyświetlany tekst komórek na strony A4 z automatycznym stronicowaniem wielostronicowym. W renderowaniu nie bierze udziału żadna kopia programu Excel, sterownik drukarki ani zewnętrzna biblioteka DLL
HotXLS traktuje PDF jako format prezentacji danych, odpowiednik swoich ścieżek eksportu CSV, TSV i HTML, a nie jako silnik renderujący z dokładnością do piksela. Eksport odtwarza zawartość tabelaryczną i układ: wartości widoczne w siatce, proporcje kolumn oraz linie siatki wokół komórek. Ta definicja ma znaczenie, ponieważ z góry ustala uczciwe oczekiwania, a reszta tego artykułu dotyczy dokładnie tego, gdzie przebiega ta granica
Jak przekonwertować Excel do PDF w Delphi bez programu Office?
Najkrótszą drogą jest pojedyncze wywołanie. Klasa TXLSWorksheet udostępnia metody SaveAsPDF(FileName) i SaveAsPDF(Stream), a TXLSWorkbook udostępnia te same dwa przeciążenia, które przekazują żądanie do aktywnego arkusza. Każda z nich zwraca wartość Integer, 1 w przypadku sukcesu i -1 w przypadku niepowodzenia, dzięki czemu można rozgałęzić kod w zależności od wyniku, bez konieczności obsługiwania wyjątków we własnym zakresie
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;
Po wywołaniu metody SaveAsPDF na arkuszu roboczym, HotXLS eksportuje UsedRange tego arkusza, czyli ramkę otaczającą każdą wypełnioną komórkę. Przeciżenie dla skoroszytu jest ułatwieniem, które deleguje zadanie do aktywnego arkusza, więc raport wieloarkuszowy albo przechodzi w pętli przez potrzebne arkusze, albo wybiera aktywny arkusz przed wywołaniem. Nie ma trybu obejmującego cały skoroszyt (wszystko w jednym przebiegu), który łączyłby każdą kartę: każde wywołanie renderuje jeden arkusz lub jeden zakres
How does HotXLS turn a used range into PDF pages?
HotXLS przechodzi używany zakres komórka po komórce i układa go jako stronicowaną siatkę. Geometria kolumn pochodzi bezpośrednio z programu Excel: szerokość każdej kolumny jest konwertowana z jednostki szerokości programu Excel na punkty typograficzne, z minimalnym limitem dolnym, dzięki czemu żadna kolumna nie zapada się do wąskiego paska. Gdy kolumny razem są szersze niż obszar roboczy strony, HotXLS skaluje je jednolicie w dół, aby się zmieściły; gdy już się mieszczą, pozostawia je przy ich naturalnej szerokości, zamiast rozciągać je na arkuszu
Wiersze płyną następnie w dół strony, aż kolejny przekroczy dolny margines, w którym to momencie HotXLS otwiera nową stronę i kontynuuje, więc arkusz składający się z tysiąca wierszy stronicuje się sam, bez potrzeby śledzenia podziału stron przez programistę. Każda komórka drukuje swój FormattedText, czyli łańcuch znaków uzyskany po zastosowaniu formatu liczb, dzięki czemu data wyświetla się tak, jak pokazuje ją arkusz, a komórka walutowa zachowuje separatory tysięcy i symbol. Tekst, który wykracza poza swoją kolumnę, jest obcinany do szerokości komórki, a nie przelewa się do sąsiedniej
Kontrolowanie orientacji, marginesów i rozmiaru czcionki
W przypadku czegokolwiek wykraczającego poza domyślny układ należy sterować bezpośrednio eksporterem. TXLSPDFExport to klasa stojąca za jednolinijkowymi metodami pomocniczymi, która publikuje trzy właściwości: Orientation (xlsPdfPortrait lub xlsPdfLandscape, domyślnie pionowo), Margin (w punktach, domyślnie 40) oraz FontSize (w punktach, domyślnie 9). Ustaw je przed wywołaniem SaveAsPDF, a cały dokument je przemie
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;
Klasa TXLSPDFExport przyjmuje również zakres zamiast całego arkusza poprzez metodę SaveAsPDF(Range: IXLSRange; ...), co pozwala wyeksportować blok podsumowania z arkusza zawierającego również brudnopis obliczeń. To przeciążenie dla zakresu jest tym samym, z którego wewnętrznie korzysta pomocnik arkusza, więc układ, skalowanie i stronicowanie zachowują się identycznie, niezależnie od tego, czy przekażesz pełny używany zakres, czy ręcznie wybrany fragment
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;
Dlaczego HotXLS nie osadza czcionki: kompromis między czcionką Helvetica a kodowaniem WinAnsi
HotXLS zapisuje tekst przy użyciu wbudowanej w PDF czcionki Helvetica i kodowania WinAnsiEncoding, co jest celowym wyborem bez żadnych zewnętrznych zależności, ale wiąże się z jednym realnym ograniczeniem. Ponieważ Helvetica jest jedną ze standardowych 14 czcionek, które posiada każdy zgodny czytnik PDF, eksporter nie osadza żadnego programu czcionkowego: plik pozostaje mały i otwiera się wszędzie, nie wymagając licencjonowania ani wysyłania czegokolwiek wraz z nim. Kosztem tego wyboru jest repertuar znaków, które strona może wyświetlić
Kodowanie WinAnsiEncoding obejmuje zestaw Windows-1252, więc tekst łaciński, popularne znaki interpunkcyjne i zwykłe zachodnioeuropejskie akcenty są renderowane poprawnie, a HotXLS składa garść znaków typograficznych, cudzysłowy drukarskie, myślniki i półpauzy oraz znak euro w ich gniazda CP1252. Znaki spoza tego zakresu (ideogramy CJK, cyrylica, greka i arabski) na stronie zmieniają się w znaki zapytania. Jeśli Twoje arkusze zawierają tekst niełaciński, ten eksporter jest niewłaściwym narzędziem i potrzebujesz pełnego renderera PDF obsługującego style
Gdzie kończy się eksport z arkusza do PDF
HotXLS renderuje zawartość i strukturę, a nie pełny styl wizualny arkusza. Wypełnienia komórek, style obramowania poszczególnych krawędzi, czcionki i kolory poszczególnych komórek, wykresy oraz osadzone obrazy leżą poza obszarem rysowania eksportera; to, co otrzymujesz, to siatka tekstowa z jednolitymi liniami siatki. Jest to ten sam kontrakt, który honorują eksporterzy HTML i RTF, i jest on właściwy dla raportu lub przekazania danych, gdzie znaczenie niosą liczby, a nie stylistyka wizualna
Gdy celem jest ostylowany, spójny z marką dokument, zwykle najpierw składa się liczby w szablonie arkusza kalkulacyjnego, co szczegółowo omawia przepływ pracy generowania raportów oparty na szablonach. Ponieważ nic z tego nie dotyka COM ani uruchomionej instancji programu Excel, potok ten pasuje do tego samego modelu automatyzacji bez pakietu Office, z którego korzysta HotXLS: czysty Pascal, wdrażalny na serwerze bezgłowym (headless), bez konieczności licencjonowania i opiekowania się bibliotekami zewnętrznymi
Samodzielny plik PDF, bajt po bajcie
HotXLS ręcznie buduje strukturę pliku PDF i oblicza jego tabelę odsyłaczy na podstawie dokładnych przesunięć bajtowych, dzięki czemu plik wynikowy otwiera się w każdym czytniku. Podczas serializacji każdego obiektu HotXLS rejestruje jego przesunięcie początkowe przed dołączeniem bajtów, a następnie przesuwa bieżącą pozycję o właśnie zapisaną długość, tak aby tabela xref lądowała precyzynie na każdym obiekcie, a startxref wskazywało miejsce, w którym ta tabela się zaczyna. Czytnik, który stwierdzi przesunięcie tych wartości nawet o jeden bajt, odrzuca cały plik, co czyni samodzielnie obliczane przesunięcie kluczowym elementem kontraktu eksportera
Kontrakt ten niesie za sobą jedną surową konsekwencję, którą warto znać. Węzeł Pages jest zapisywany jako pierwszy (jako obiekt 1), ale lista jego stron podrzędnych nie jest znana, dopóki wszystkie strony nie zostaną wyemitowane, więc HotXLS rezerwuje go jako symbol zastępczy i wstawia ostateczne podstrony oraz liczbę przed wykonaniem przebiegu przesunięcia, nigdy po nim. Po zmierzeniu bajtów obiektu na potrzeby tabeli xref są one zamrażane: zmiana pojedynczego bajtu po tym fakcie przesunęłaby każde kolejne przesunięcie i uszkodziłaby tabelę. To drobna dyscyplina, która pozwala uzyskać zgodny ze standardami plik PDF 1.4 bez żadnej dodatkowej biblioteki
Pokazane tutaj metody SaveAsPDF i klasa TXLSPDFExport są dostarczane z komponentem HotXLS Delphi Excel, wraz z eksporterami CSV, HTML i RTF oraz pełnym interfejsem API arkusza dla Delphi i C++Builder