Komponent PDFium daje jedną metodę dzielenia plików PDF: ImportPages. Wszystko inne, niezależnie od tego, czy wyodrębniasz pojedynczą stronę, tniesz na dowolnych granicach, czy też podążasz za wewnętrzną strukturą zakładek dokumentu, to po prostu różne sposoby na to, by zdecydować, które numery stron trafią do każdego pliku wyjściowego. Mechanika pozostaje ta sama. Wczesne zrozumienie tego oszczędzi wielu błędnych kroków
Jak działa pętla dzieląca
Wzorzec jest ten sam niezależnie od tego, w jaki sposób dzielisz dokument źródłowy. Utwórz nową instancję TPdf, wywołaj na niej CreateDocument, aby zainicjować pusty plik PDF w pamięci, zaimportuj pożądane strony za pomocą ImportPages, zapisz wynik, a następnie zresetuj Active na False przed kolejną iteracją. Ten ostatni krok bywa przez użytkowników pomijany: CreateDocument nie zamyka niejawnie dokumentu będącego ciągle w pamięci, więc musisz zapisać wynik i jawnie zresetować Active := False przed ponownym wywołaniem; wykonanie resetu najpierw sprawia, że stan pozostaje czysty i zdefiniowany. Zewnętrzna instancja TPdf jest ponownie wykorzystywana we wszystkich iteracjach, co utrzymuje niskie zapotrzebowanie na alokacje przy dużych zadaniach
Oto jak wygląda dzielenie strona po stronie w najbardziej podstawowej formie:
procedure SplitIntoPages(Source: TPdf; const OutputDir: string);
var
I: Integer;
PdfOut: TPdf;
OutFile: string;
begin
PdfOut := TPdf.Create(nil);
try
for I := 1 to Source.PageCount do
begin
PdfOut.CreateDocument;
// Range is a 1-based page number string; insertion point 1 = first position
if not PdfOut.ImportPages(Source, IntToStr(I), 1) then
raise Exception.CreateFmt('Failed to import page %d', [I]);
OutFile := OutputDir + '\page_' + Format('%.4d', [I]) + '.pdf';
if not PdfOut.SaveAs(OutFile) then
raise Exception.Create('Failed to save ' + OutFile);
PdfOut.Active := False; // reset before next CreateDocument
end;
finally
PdfOut.Free;
end;
end;
Parametr Range dla ImportPages używa tego samego formatu ciągu, z którego PDFium korzysta wewnętrznie: oddzielonej przecinkami listy numerów stron lub zakresów połączonych myślnikiem, przy czym wszystko indeksowane jest od jedynki (1-based). '3' importuje stronę 3. '1-5' importuje strony od 1 do 5 po kolei. '2,5,8' importuje te trzy wymienione strony. Trzeci parametr to oparty na jedynce punkt wstawiania w dokumencie docelowym; przekazanie wartości 1 zawsze położy zaimportowane strony na samym początku skądinąd pustego pliku, a tego właśnie tutaj szukamy
Dzielenie według zakresów stron
Kiedy wywołujący przekazuje listę taką jak 1-12,13-24,25-36, parsujesz ją w pary początek/koniec i odpalasz tę samą pętlę, budując łańcuch z każdą kolejną pozycją z pary:
procedure SplitByRanges(Source: TPdf; const RangeList: array of string;
const OutputDir: string);
var
I: Integer;
PdfOut: TPdf;
OutFile: string;
begin
PdfOut := TPdf.Create(nil);
try
for I := 0 to High(RangeList) do
begin
PdfOut.CreateDocument;
if not PdfOut.ImportPages(Source, RangeList[I], 1) then
raise Exception.Create('Invalid page range: ' + RangeList[I]);
OutFile := Format('%s\section_%d.pdf', [OutputDir, I + 1]);
if not PdfOut.SaveAs(OutFile) then
raise Exception.Create('Failed to save ' + OutFile);
PdfOut.Active := False;
end;
finally
PdfOut.Free;
end;
end;
Zatwierdzanie (validation) przed dojściem do ImportPages ma tutaj znaczenie. ImportPages zwraca False, gdy numer strony we wprowadzonym ciągu przekroczy wymiar Source.PageCount, ale funkcja ta nie zgłosi błędu w postaci wyjątku, ani nie utworzy częściowego pliku wyjściowego o błędzie, który dałoby się wyłapać jedynie za sprawą specyficznej nazwy pliku. Sprawdź więc zadaną wartość wyjściową funkcji SaveAs i w logach przeanalizuj usterki oddzielnie; zakres, z powodu którego zostanie stworzony całkowicie pusty plik bezużyteczny nie staje się wcale taki rażąco wadliwy na zewnątrz, póki ktokolwiek nie podjąłby chęci do jego otwarcia
Dzielenie na granicach zakładek
Trzecie podejście wykorzystuje własną strukturę dokumentu zamiast list podawanych z zewnątrz. Każda zakładka (bookmark) na głównym poziomie niesie do określonej wartości jako przyporządkowany numer punktu ze stroną; sekcja definiująca podążanie rozpocznie akcję ze stron na punkt zaraz wyprzedzający miejsce wskazywane ze zbliżającej się zakładki lub w końcu ze stroną opisaną dokumentem poprzez wyjście dla ostatniej dodanej notatki
procedure SplitByBookmarks(Source: TPdf; const OutputDir: string);
var
Bm: TBookmarks;
I, StartPage, EndPage: Integer;
PdfOut: TPdf;
RangeStr, OutFile, SafeTitle: string;
begin
Bm := Source.Bookmarks;
if Length(Bm) = 0 then
Exit;
PdfOut := TPdf.Create(nil);
try
for I := 0 to High(Bm) do
begin
StartPage := Bm[I].PageNumber;
if I < High(Bm) then
EndPage := Bm[I + 1].PageNumber - 1
else
EndPage := Source.PageCount;
if (StartPage < 1) or (EndPage < StartPage) then
Continue;
RangeStr := Format('%d-%d', [StartPage, EndPage]);
PdfOut.CreateDocument;
if not PdfOut.ImportPages(Source, RangeStr, 1) then
begin
PdfOut.Active := False;
Continue; // skip a malformed section instead of writing an empty file
end;
SafeTitle := StringReplace(Bm[I].Title, '/', '_', [rfReplaceAll]);
SafeTitle := StringReplace(SafeTitle, ':', '_', [rfReplaceAll]);
OutFile := Format('%s\%02d_%s.pdf', [OutputDir, I + 1, SafeTitle]);
if not PdfOut.SaveAs(OutFile) then
raise Exception.Create('Failed to save ' + OutFile);
PdfOut.Active := False;
end;
finally
PdfOut.Free;
end;
end;
Dokument pozbawiony zakładek nie stanowi warunku błędu zasługującego, by zgłaszać to użytkownikowi w postaci takowego; oznacza to jedynie, że ów tryb podziału po prostu nie ma z czym pracować. Zabezpieczenie Length(Bm) = 0 w cichości ogarnie to zjawisko. Godne ujawnienia jest natomiast to, jeśli numer ze stroną pod zakładką będzie wykroczeniem zza ram obszaru dla zapisanego z dokumentem układu rzędu wielkości stron. Taka ewentualność wchodzi pod problem źle formowanego formatowania dla uszkodzonych zestawień, ułożonych z usuniętych z pliku u rzędów dokumentów a zapomnianych zaktualizowaniem dla nich spisu nawigacji (outline). Tak przeprowadzona pod kod w StartPage i z wartością z opcji w `EndPage` kontrola odrzuca niefortunne pomyłki z ignorancją unikającą ich wysłanie przez ImportPages przy u użyciu losowej wyrzuconej listy odczytanej zawartości z kosza
Nazewnictwo plików wyjściowych i reset flagi Active
Bezpieczeństwo nazw plików powiązane w całości do spisanego przy tytulaturach po liście nawigacyjnych dla zakładek punktuje wyjątkowe rzędy uwagi. Kwestie co przy formowaniu za zbiór ciągów pdf i dopuszcza standard form z łańcuchem w nich za to na użycie ich jako zapis ze strukturą docelowych na formatki systemu pliku z odpowiednimi o po ujęciach błędem nie przechodzi pod formą zapisu na ścieżce zapisu dysku systemu w komputerach. Co z punktów wymaganych trzeba z pewnością, tak na drodze konieczności, wymień u pętli zamianę z cięciami po używaniu od prawych (forward slash), odwróconych poprzecznych ukośnikach lewych (backslash) czy przy wymianie u znaków dzielonego wpisu przy ujętym wpisywanym znakiem punktowania dzielącego czyli dla połączonego razem u znaków z pod nazwą dwukropek, jako pierwsze jeszcze co by ukształtować połączoną całą drogą jako prawidłowy plik wyjściowy (output path). Po windowsie u operacji dla systemów uwarunkowania po pomyślnym zastosowaniu systemu, wprowadzane przy znakach pod *, ?, ", <, >, czy ze znakiem prostym oddzielającym (pipe) pod symbolem o wpisach | rygorem stanowią użycie dla wpisu jako zabronione (forbidden); a małe proste wykorzystujące pod kod układ przy rozwiązaniu po na sztywno ujętej linii z rozwiązaniem za pętlą u wybranych dla u bazy kodem znaków za rzędem w systemowej grupie ominie ci potrzebę obciążającą korzystaniem przy rozwiązaniach u skomplikowanych metod z wezwaniem pod wpisanie jako regularne używane (regex)
Linia na samym końcu każdego w poszczególnym odczytaniu za formą przy każdej zmianie u Active := False stanowi szczególną i niezbędną używaną uwagę, tym faktem na celownik od przyznania sobie z powodem ujętego, i stanowi od tego z wezwania na zewnątrz punkt w którym jest to z reguły jedną jedyną na użyte jako mało oczywistą cechę we wzorcu by u z nim korzystać. CreateDocument nie pozwala tak ukrytym zaprogramowaniu opisać opcję skasowania użytych wartości trzymanych przed używaną z funkcją jak dokument na zjawisko wyłączenia dla opcji otwartej w kodzie aplikacji. Po zostawionym niezmiennie Active przy formie rzucanej jako True i uruchamiającym powielonym trybie wykorzystanym kodowo do odczytu uruchomieniem po CreateDocument w pętli od razu wpierw jeszcze przy tym jako rzuconym wywołaniu, w systemowej osłonie za pozostawionym we systemach przetrzymywanej i udostępnionej do pobieranych na pamięć wartości we dokumencie to by pokazało o nim z faktu jako to obiektywnie nierozliczone wyjściem pod prawidłowo skasowanym procesie ani na cel z zabezpieczeniem wywołanym zapisem (saved), i po uwagach a stąd na uwarunkowania to zachowanie tego u stanu w ogóle u rzędach i odrzuconym wyjściem uważa ze to zachowanie przy formowaniu o braku zdefiniowania pod poprawny z definicji za proces u stabilności przy zjawiskach użytych błędów za program (well-defined behavior), zatem z tego faktu wykonaj po oświadczeniu do zastosowania przed zastosowaniem z otwarciem nowej bazy dokumentacji dla celowego u zapisanego projektu opcję jako udane zapisanie pliku by uświadomić cel o jawnym skasowaniu resetu. Po uwagach z powiązaniami przyjmij że opiera to od tego miano dla sparowania by funkcjonować taką zależnością jako z wezwaniem rzuconym dla bloków jako element w procedurze pod nazwę jako na typowe do opcji po parze użycia reguły wyłączenia przy systemie kodu (try/finally): pętla a funkcja za zewnętrznym systemem użytego kodu po `finally block` by skasować ostatecznie wartość zapisu, po oświadczonej za przypisaną funkcja z rzuceniem po komendzie u flagi (Active := False) u resetuje a z powrotem wprowadzając ustawienie za wewnętrznym zachowanym środowiskiem po systemach po etapach w pętli użytych do operacji między używanymi u procesami z uruchomionej linii
Zużycie wejściowe z alokacji na operacje w użyciach u pamięci po rozdzielonych operacjach za tak dużej dokumentacji zachowuje się niezmiennie z wykorzystaniem dla przy zaprezentowanym przy tym sposobem opartym bez utraty stabilnej opcji na stabilność układu utrzymywania pod równym rzędzie bez zmian z wydajnością u (stays flat), bo to unikanie od wprowadzonych przetrzymywanych za moment operacji od systemu dokumentu bywa z zaledwie z tylko jedną zapoczątkowaną i uwyjścioną bazą dla w formach jednego na dany raz pod formacją o użytym dokumencie na zapisany na wezwany cel operacyjny (output document). Za element rzucony wywołanym z oryginalnego (source document) z w trybie po opcji w ogólnej na o tylko pod oczyt pozostając po bezpiecznych a we wszystkich z uwag pozostającym otwarciu procesie u wezwanych (read-only); element z w opcjach w przypisanych miano z funkcji wyciągniętych przez (ImportPages) skopiuje materiał by skopiowane a przekopiowanych form danych powieliło zapisanymi jako nowe pod w nowym powiększonym od form pliku wyciągniętym przy nie dokonanym jakimkolwiek użytym za cel zmian wprowadzonych edytowaniem dla w pierwotnym do oryginalnego rzędu użytego na pliku. Jeśli u po stronie pod oryginałem pozostawałaby forma od zaszyfrowanej, z racji na powód to wykonaj przed wyciągnięciem w załączoną hasłem zadaną wpierw w sekwencje pętli formacją u uwolnione zapytanie dla kodu w wywoływaniach na system opcję wyjęcia po rzuconym kodzie by uzyskać u skopiowanych do docelowych we wyjściowym użyciu u formach na wpisanych formach format a uwzględniając pod opcję a zapytany po u plikach ze zniechęconym od użytych szyfrów w postaci na użycie opcję a uwolnionym (unencrypted), na ogólnym za przypisane wykorzystaniem rzucone u zachowaniem i zachowanym przy powiązanym dla dystrybuowanym dla na podzielonym pod różnych na w wejściowym zapleczu docelowym odbieranych pod ludzi odbiorcach
I jako końcowe o wpisanym od powiązaniach miano w oparciu od zwracania u funkcji jako u użyciu SaveAs: przynosi to jako z podaną wywołaniem w wyniku logicznej bazy miano logicznego dla formatów pod zwracanej z wezwanej przez ujętej formy (Boolean). Katalog po odzysku na cel po wyjściu w proces przy opcję której za brak i braku formy na użycie by istniał z założenia w systemowej opcji docelowego o u użytych wpisów, za pod adresem użytą docelowym ścieżką z z znakami jako pod wyrzuconymi oporowo dla nieuznanych systemowo poprzez zaplecze systemu z u oprogramowań w system operacyjnym (OS), bądź na podstawie zapełnionego w wykorzystanym przy opór miejsca do bazy (disk-full), wszystko dla za wyżej z w opcjach opisanych będzie zaowocowało użyciem jako w efekcie na opcja wyrzuci wynik zwrotu przez w u zapytaniu z u funkcjach podjętej przy nazwie miano z fałsz (False) przed uruchomieniem u operacji jako wezwaniem dla z wezwania pętli jakikolwiek dla użytej wprowadzanej flagi u zgłaszanym wyjątkami przy odwołaniach. W pracach z zrzuconym od na wielo procesowych u zadaniach formowanych ze wprowadzonych na po opcję seryjnie po kod o nazwie z (batch job) na działaniem formatowanej wartości form u dzielonego o rozmiarze pliku aż z formatów licząc w opcję na objętościach formatach 200 stron po docelowych o parametrach na formach do wyników z o na stron poszczególnym jednorazowo by plik osiągał a osiągniętych po na w sumie o ilości i liczbie w sztuk na rzędzie u wyników a wynikiem do pliku dla bazy 200 takich pod proces opcję dla formowaniu a rzuceniu form u wezwanym na w procesowym na dokument, głuche bez po opcji z sygnalizowaniu i wezwań ignorowanym wyjściowym użyciem przy niewykonanym dla pod wyjściem błędzie już obiektywnie dla od wpadki z u na wpisie ze stroną dla numerem opcji 147 łatwo z wejściem do bazy użycia przegapić. Wywołuj po za odpowiednim a wyciągniętym do odpowiednim sprawdzonym parametrze na pod kontrolę po wyjściowej z rzuconej i pod zwrotem pobieranej a używanej przy tym powrotną powracaną na pętlę cechą formatując i powtarzając i wyłapując w użyciu badanej o kontrolę i dolicz w używanych i na wyjściowych pod docelowych dla sprawdzanych wyników ilości o o formowaniu poprawnym wynikiem od u bazy (successes) nad u za wpisanej we wyjściowej a spodziewanej docelowych od opcji pod wyzwaniach na opcji rzędu przed wyjściem całkowitym spod a wpisanym dla wyjściem od wykorzystanej w pod system wywoływanej wyciągniętej w zakończeniu wpisanej a wyjściowej od uformowanej opcją za pętli (loop finishes)
Użyte tu procedury dla powołanych w formach od użyć pod komendę używane pod od wykorzystanej nazwie dla opcji dla po funkcji o zapytaniu dla kodowania (ImportPages) z po dla odpowiedniego CreateDocument dla pod wywołania w opcji jako użyta powołana we formach a opisywana od dokumentacji jako zaplecze z na od o funkcji stanowią a objęte od po powiązanym elemencie do pod o nazwie z pod opcję PDFium Component u na wykorzystywanym mianie u od jako na Delphi po za pod do w użyciach u wsparciu C++Builder