HotXLS eksportuje skoroszyt lub pojedynczy arkusz bezpośrednio do PDF/A z Delphi i C++Builder, bez Excela i bez sterownika drukarki PDF. Ustaw UsePDFA i wybierz profil na TXLSPDFExport, a wyeksportowany plik będzie niósł osadzony profil ICC sRGB jako swoją intencję wyjściową, blok identyfikacyjny pdfaid w metadanych XMP oraz nagłówek wersji PDF odpowiedni dla poziomu zgodności
Ten wymóg zwykle wynika z polityki przechowywania dokumentacji, a nie od programisty. Sprawozdania finansowe, wyniki laboratoryjne, dokumenty regulacyjne i wszystko, co instytucja publiczna musi przechowywać przez dziesięciolecia, muszą być zapisane w formacie, który renderuje się identycznie za pięćdziesiąt lat, i właśnie to ma gwarantować PDF/A, ISO 19005. Arkusz kalkulacyjny to żywe obliczenia; zarchiwizowana kopia arkusza musi być ich nieruchomym obrazem
Co czyni PDF plikiem archiwalnym?
Większość pracy wykonują trzy wymogi. Plik musi być samowystarczalny, więc każda używana przez niego czcionka jest osadzona i nie ma odwołań do zasobów zewnętrznych. Jego kolor musi być jednoznaczny, co oznacza intencję wyjściową nazywającą przestrzeń kolorów, dla której plik został przygotowany. I musi się identyfikować za pomocą metadanych XMP deklarujących numer części i poziom zgodności
HotXLS zapewnia wszystkie trzy. Profil sRGB jest osadzony jako obiekt strumieniowy z trzema składowymi i DeviceRGB jako alternatywą, przywoływany z intencji wyjściowej GTS_PDFA1, której warunek i identyfikator oba wskazują sRGB IEC61966-2.1. Pakiet XMP niesie wpisy części i zgodności pdfaid. Bajty profilu są wkompilowane w bibliotekę, a nie wczytywane w czasie działania, więc nie ma etapu wdrożenia ani ryzyka, że brakujący plik zamieni eksport archiwalny w zwykły
uses
lxHandleX, lxPDF;
var
Book: TXLSXWorkbook;
Exporter: TXLSPDFExport;
begin
Book := TXLSXWorkbook.Create;
Exporter := TXLSPDFExport.Create;
try
if Book.Open('quarterly-results.xlsx') <> 1 then
Exit;
Exporter.UsePDFA := True;
Exporter.PDFAProfile := xlsPdfA2b; // ISO 19005-2 poziom B
Exporter.DocumentLanguage := 'en-GB';
Exporter.TagMode := xlsPdfTagsAutomatic;
if Exporter.SaveAsPDF(Book, 'quarterly-results-archive.pdf') <> 1 then
raise Exception.Create('archival export failed');
finally
Exporter.Free;
Book.Free;
end;
end;
Który profil wybrać?
Wyliczenie profili obejmuje PDF/A-1, PDF/A-2 i PDF/A-3, każdy w wariancie dostępnym (accessible) i podstawowym (basic). Praktyczne różnice są węższe, niż sugeruje ta lista
Poziom B, wariant podstawowy, gwarantuje, że wygląd wizualny jest odtwarzalny. Poziom A dodaje wymagania strukturalne i semantyczne, przede wszystkim znakowane drzewo struktury i zdefiniowaną kolejność czytania, dzięki czemu dokument jest dostępny dla technologii wspomagających. Część 2 łagodzi niektóre ograniczenia części 1 i dopuszcza strumienie obiektów oraz JPEG 2000; część 3 dodatkowo pozwala na dowolne osadzone pliki, z czego korzystają formaty faktur elektronicznych, aby nieść czytelny maszynowo XML obok strony czytelnej dla człowieka
Dla zarchiwizowanego arkusza kalkulacyjnego PDF/A-2b jest pragmatycznym domyślnym wyborem: jest szeroko akceptowany przez archiwa, nie wymaga dyscypliny znakowania, którą poziom A narzuca na siatkę komórek, i pozwala na zwarte struktury, które nie dopuszczają do rozdęcia 200-stronicowego eksportu skoroszytu. Wybierz część 3, gdy archiwum musi nieść też dane źródłowe jako załącznik, co eksporter obsługuje przez AddAttachment
Reguła dotycząca czcionek, na której najwięcej osób się przejeżdża
Każdy glif rysowany w pliku PDF/A musi pochodzić z osadzonej czcionki. To najczęstsza pojedyncza przyczyna, przez którą skądinąd poprawny eksport nie przechodzi walidacji, a sposób, w jaki to zawodzi, jest podstępny: plik wygląda dobrze na maszynie, która go utworzyła, ponieważ ta maszyna ma zainstalowaną czcionkę
HotXLS osadza podzbiory TrueType dla używanych czcionek, ale ścieżka zapasowa base-14 istnieje na wypadek, gdy czcionki nie da się rozwiązać, a zapasowa czcionka base-14 z definicji nie jest osadzona. Do wyjścia archiwalnego skonfiguruj jawny plik czcionki Unicode, aby ścieżka zapasowa nigdy nie została użyta. Mechanika podziału na podzbiory i łańcucha zapasowego jest opisana w podziale czcionek TrueType na podzbiory; praktyczną zasadą jest przetestowanie eksportu na maszynie, na której nie są zainstalowane twoje firmowe czcionki
Co gwarantuje eksporter, a czego nie
Precyzja jest tu ważniejsza niż brzmienie pewne siebie. Eksport tworzy aparat identyfikacyjny PDF/A — intencję wyjściową, osadzony profil ICC, metadane pdfaid, odpowiedni nagłówek wersji — i kieruje tekst przez ścieżkę osadzania. Nie uruchamia pełnego walidatora nad własnym wynikiem, więc nie egzekwuje każdego zakazu ze specyfikacji, takiego jak reguły dotyczące przezroczystości, niektórych typów adnotacji i treści opcjonalnej
W eksporcie arkusza kalkulacyjnego te konstrukcje pojawiają się rzadko, dlatego praktyczny wskaźnik powodzenia jest wysoki. Ale wysoki nie znaczy gwarantowany, a dla prawdziwego potoku archiwalnego właściwą architekturą jest eksport, a następnie walidacja niezależnym narzędziem, traktująca niepowodzenie walidacji jako błąd potoku, a nie ostrzeżenie. Porównywalny podział odpowiedzialności dla dokumentów PDF opisano w walidacji preflight PDF/A
Układ strony jest częścią wierności archiwalnej
Zarchiwizowany arkusz kalkulacyjny, który jest technicznie zgodny, ale wizualnie nieczytelny, nie spełnił swojego właściwego zadania. Ustawienia strony mają większe znaczenie w eksporcie archiwalnym niż przy codziennym drukowaniu, ponieważ nikt później nie będzie mógł go przepłynąć na nowo
Trzy ustawienia zwracają się same. Dopasowanie do szerokości zapobiega klasycznemu błędowi, w którym tabela o szerokości 14 kolumn trafia jako siedem stron po dwie kolumny każda. Powtarzające się wiersze nagłówka utrzymują czytelność każdej strony z osobna. A jawne obszary wydruku wykluczają robocze notatki znajdujące się na prawo od rzeczywistych danych. Pełny zestaw ustawień wydruku i strony opisano w ochronie, ustawieniach strony i drukowaniu
// Ustawienia strony gotowe do archiwizacji, zastosowane przed eksportem
Sheet := Book.Sheets[0];
Sheet.PageLandscape := True;
Sheet.FitToWidth := 1;
Sheet.FitToHeight := 0; // tyle stron wysokości, ile potrzeba
Sheet.SetPrintArea('A1:N480');
Sheet.PrintTitleRows := '$1:$3';
// Metadane też należą do archiwum
Book.Title := 'Quarterly results 2026 Q2';
Book.Author := 'Finance';
Lista kontrolna przed pierwszym uruchomieniem wsadowym
Sprawdź, czy plik się identyfikuje: niczego nie rozpakowuj, po prostu otwórz PDF w edytorze tekstu i poszukaj wpisów części i zgodności pdfaid oraz intencji wyjściowej GTS_PDFA1. Sprawdź czcionki: upewnij się, że każda czcionka w dokumencie zgłasza się jako osadzona. Sprawdź wygląd: porównaj wyeksportowane strony z wydrukowaną kopią, ponieważ ustawienie dopasowania do strony, które po cichu zmniejsza tekst do czterech punktów, jest zgodne ze specyfikacją i bezużyteczne
Następnie uruchom niezależny walidator na reprezentatywnej próbce i zachowaj raport. Archiwa coraz częściej wymagają dowodu walidacji, nie tylko samego pliku, a wygenerowanie go w chwili eksportu jest o wiele tańsze niż odtwarzanie go po latach. Codzienną, niearchiwalną ścieżkę eksportu i jej opcje renderowania opisano w eksporcie arkusza do PDF
Eksport archiwalny, ustawienia strony i stojący za nimi silnik renderujący są dostarczane w jednej bibliotece dla Delphi i C++Builder; pełną listę funkcji znajdziesz na stronie komponentu arkusza kalkulacyjnego HotXLS dla Delphi