PDF Library for Delphi zlučuje dva dokumenty AcroForm s explicitnou politikou pre polia, ktoré zdieľajú rovnaký názov. MergeDocumentEx prijíma identifikátor zdrojového dokumentu a jednu z troch stratégií: dfsReject odmietne zlúčenie, dfsMerge ponechá zdieľaný názov a synchronizuje hodnoty, a dfsAutoNumber deterministicky premenuje prichádzajúce polia. Skenovanie názvov prebieha pred akýmkoľvek posunom čísel objektov, takže odmietnuté zlúčenie ponechá oba dokumenty plne použiteľné
Toto zažil každý, kto niekedy zostavoval balík formulárov PDF. Tri formuláre, z ktorých každý má pole s názvom Signature, Date alebo Total, sa zlúčia do jedného súboru. V AcroForm je plne kvalifikovaný názov poľa identitou poľa, takže dve polia s rovnakým názvom vôbec nie sú dve polia: vyplnenie jedného vyplní aj druhé, a podpis aplikovaný na jedno pokryje rozsah, ktorý nikto nezamýšľal
Prečo sa kolízia názvov rozhoduje pred zlúčením?
Staršia MergeDocument zreťazí polia oboch koreňových polí AcroForm a neponúka žiadnu voľbu. Horšie je, že keď je výsledok nepoužiteľný, objaví sa to až po tom, čo boli čísla objektov prečíslované a stromy stránok zošité, čo volajúcemu ponechá dokument v stave, v akom nebol žiadny z originálov
MergeDocumentEx obracia poradie. Zozbiera názvy polí najvyššej úrovne z oboch dokumentov, porovná ich a aplikuje stratégiu skôr, než sa čokoľvek pohne. Odmietnutie je preto čistá no-op operácia: cieľový dokument je nedotknutý, zdrojový dokument je nedotknutý, a oba zostávajú otvorené a použiteľné, čo test zlúčenia overuje spätným prečítaním hodnoty poľa zo zdroja po odmietnutom zlúčení
Porovnanie používa zoradenú množinu názvov citlivú na veľkosť písmen, takže náklady sú úmerné súčtu počtu polí krát logaritmický faktor, nie súčinu oboch počtov. Citlivosť na veľkosť písmen je tu správnou voľbou, pretože názvy polí PDF sú na veľkosť písmen citlivé; ich sklopenie by zlúčilo polia, ktoré špecifikácia považuje za odlišné
Tri stratégie, a kedy je ktorá správna
dfsReject je stratégia pre automatizované pipeline, ktoré nesmú produkovať nejednoznačné dokumenty. Zlúčenie vráti nulu a LastErrorCode hlási 705, vyhradený kód, aby sa duplicitné názvy dali odlíšiť od každého iného zlyhania zlúčenia a nasmerovať na konkrétnu nápravu, zvyčajne premenovanie polí vyššie v reťazci
dfsMerge zámerne ponecháva zdieľaný názov a synchronizuje cieľovú hodnotu a predvolenú hodnotu do zdrojového poľa, takže vyhovujúci prehliadač zaobchádza s viacerými widgetmi ako s jedným logicky pomenovaným poľom, čo je štandardné správanie AcroForm pre pole s viacerými anotáciami widgetov. Čo nerobí, je zlúčiť odlišné slovníky polí do jedného objektu. Každé pole si ponecháva vlastné priradenie stránky, vzhľad a akcie, pretože ich zlúčenie by ticho zahodilo formátovanie a správanie, ktoré patrí prichádzajúcemu dokumentu
dfsAutoNumber premenúva prichádzajúce duplicity pripojením číselnej prípony počnúc _2 a vezme prvú voľnú. Výsledok je reprodukovateľný: závisí iba od prítomných názvov, nikdy od čísel objektov polí, takže zlúčenie tej istej dvojice dokumentov dvakrát dá oba razy rovnaké názvy. Táto vlastnosť je dôležitá, keď nadväzujúci kód, import FDF alebo mapovanie databázy odkazuje na polia podľa názvu
uses
PDFlibrary;
var
Lib: TPDFlib;
TargetDoc, SourceDoc: Integer;
begin
Lib := TPDFlib.Create;
try
TargetDoc := Lib.SelectedDocument;
Lib.LoadFromFile('application-part1.pdf', '');
SourceDoc := Lib.NewDocument;
Lib.LoadFromFile('application-part2.pdf', '');
Lib.SelectDocument(TargetDoc);
if Lib.MergeDocumentEx(SourceDoc, dfsReject) = 0 then
begin
if Lib.LastErrorCode = 705 then
begin
// Oba dokumenty sú stále neporušené - skúste znova s politikou
Log('duplicate field names; retrying with auto-numbering');
Lib.MergeDocumentEx(SourceDoc, dfsAutoNumber);
end;
end;
Lib.SaveToFile('application-complete.pdf');
finally
Lib.Free;
end;
end;
Všimnite si dvojkrokový vzor v tomto kóde, ktorý je možný iba preto, že odmietnutie je nedeštruktívne. Najprv vyskúšajte prísnu politiku, preskúmajte chybu a až potom sa rozhodnite. Pri zlúčení, ktoré zlyhá v polovici, by náhradné riešenie muselo začať odznova opätovným načítaním oboch súborov
Ako vyzerá zlúčený formulár potom
Pod dfsMerge cieľové pole s názvom Shared nesúce „Target value" a zdrojové pole s rovnakým názvom vyprodukujú dve polia, obe s názvom Shared, obe hlásiace cieľovú hodnotu, pretože cieľová hodnota aj predvolená hodnota sa synchronizujú do prichádzajúceho poľa. Toto je zamýšľaná sémantika pre zdieľaný názov: jedno logické pole, niekoľko widgetov, jedna hodnota
Pod dfsAutoNumber ten istý vstup vyprodukuje Shared a Shared_2 ako samostatné polia s nezávislými hodnotami. Vyberte medzi nimi jednou otázkou: má vyplnenie jedného ovládacieho prvku vyplniť aj druhý? Pri mene podpisujúceho opakovanom na každej časti balíka áno, a správna je dfsMerge. Pri súčte, ktorý na každom formulári znamená niečo iné, nie, a správne je automatické číslovanie
// Po zlúčení vypíšte, čo ste v skutočnosti dostali
for I := 1 to Lib.FormFieldCount do
Log(Format('%d: %s = %s',
[I, Lib.GetFormFieldTitle(I), Lib.GetFormFieldValue(I)]));
Praktické poznámky pre zostavovanie balíkov formulárov
Úspešné zlúčenie spotrebuje zdrojový dokument: odstráni sa zo zoznamu dokumentov knižnice, a preto DocumentCount klesne z dvoch na jeden. Zdrojový identifikátor potom ďalej nepoužívajte. Verzia dokumentu sa zdvihne na vyššiu z oboch, takže zlúčenie formulára PDF 2.0 do dokumentu 1.7 vytvorí súbor 2.0
Na poradí pri názvoch záleží. Zlúčenie A do B a zlúčenie B do A produkujú odlišné automaticky číslované výsledky, pretože dokument, ktorý vykonáva zlúčenie, si ponecháva svoje názvy nezmenené. Keď má balík kanonický primárny formulár, urobte z neho cieľ
Polia podpisu si zaslúžia vlastnú úvahu. Podpis aplikovaný pred zlúčením pokrýva iba tú revíziu, ktorú podpísal, takže zlúčenie ho v praktickom zmysle znehodnotí, pretože súbor sa od podpísania zmenil. Najprv zostavte a podpíšte zostavený dokument, namiesto zlučovania podpísaných častí. Keď zlúčenie rieši obsah stránok, nie formuláre, lepším nástrojom je rýchlejšia cesta opísaná v časti rýchle zlučovanie PDF s posunom bajtových referencií
Napokon naplánujte dátovú stránku balíka spolu so zlúčením. Ak hodnoty polí prichádzajú z externého systému, rozhodnite, či tento systém adresuje polia podľa názvu, skôr než zvolíte automatické číslovanie, pretože Shared_2 sa nezhodne s mapovaním, ktoré očakáva Shared. Formáty importu a exportu opisuje časť výmena dát formulárov FDF, XFDF a XFA, a správanie skriptovania na úrovni polí, ktoré tiež môže ovplyvniť premenovanie, opisuje časť interaktívne akcie formulárov a JavaScript
Zlučovanie formulárov, výmena dát a podpisovanie bežia v tej istej knižnici pre Delphi, C++Builder a Free Pascal; kompletný zoznam funkcií nájdete na stránke PDF Library for Delphi