PDF Library for Delphi spaja dva AcroForm dokumenta sa eksplicitnom politikom za polja koja dele ime. MergeDocumentEx uzima identifikator izvornog dokumenta i jednu od tri strategije: dfsReject odbija spajanje, dfsMerge zadržava deljeno ime i sinhronizuje vrednosti, a dfsAutoNumber deterministički preimenuje dolazna polja. Skeniranje imena se dešava pre nego što se ijedan broj objekta pomeri, tako da odbačeno spajanje ostavlja oba dokumenta potpuno upotrebljivim
Svako ko je sastavljao paket PDF aplikacije se susreo sa ovim. Tri obrasca, svaki sa poljem nazvanim Signature ili Date ili Total, spajaju se u jedan fajl. U AcroForm-u, potpuno kvalifikovano ime polja je identitet tog polja, pa dva polja sa istim imenom uopšte nisu dva polja: popunjavanje jednog popunjava i drugo, a potpis primenjen na jedno pokriva opseg koji niko nije nameravao
Zašto se sudar imena rešava pre spajanja?
Stariji MergeDocument spaja korene nizove AcroForm polja oba dokumenta i ne nudi izbor. Gore od toga, kada je rezultat neupotrebljiv, otkriće se dešava nakon što su brojevi objekata ponovo numerisani i stabla stranica sašivena, što ostavlja pozivaoca sa dokumentom u stanju u kom nijedan original nije bio
MergeDocumentEx preokreće redosled. Prikuplja imena polja najvišeg nivoa iz oba dokumenta, upoređuje ih, i primenjuje strategiju pre nego što se bilo šta pomeri. Odbijanje je stoga čist bez-efekta korak: ciljni dokument je netaknut, izvorni dokument je netaknut, i oba ostaju otvorena i upotrebljiva, što test spajanja potvrđuje čitanjem vrednosti polja nazad iz izvora nakon odbijenog spajanja
Poređenje koristi uređen, na velika i mala slova osetljiv skup imena, tako da je cena proporcionalna kombinovanom broju polja puta logaritamski faktor, a ne proizvodu dva broja. Osetljivost na velika i mala slova je ovde ispravan izbor jer su imena polja u PDF-u osetljiva na velika i mala slova; sklapanje njih bi spojilo polja koja specifikacija tretira kao različita
Tri strategije, i kada je svaka ispravna
dfsReject je strategija za automatizovane pipeline-ove koji ne smeju da proizvedu dvosmislene dokumente. Spajanje vraća nulu, a LastErrorCode prijavljuje 705, poseban kod tako da se duplirana imena mogu razlikovati od svakog drugog otkaza spajanja i usmeriti ka specifičnom rešenju, obično preimenovanju polja uzvodno
dfsMerge namerno zadržava deljeno ime i sinhronizuje ciljnu vrednost i podrazumevanu vrednost u izvorno polje, tako da usaglašen pregledač tretira nekoliko vidžeta kao jedno logički imenovano polje, što je standardno AcroForm ponašanje za polje sa više anotacija vidžeta. Ono što ne radi jeste sklapanje različitih rečnika polja u jedan objekat. Svako polje zadržava sopstvenu vezu sa stranicom, izgled i akcije, jer bi njihovo sklapanje tiho odbacilo formatiranje i ponašanje koje pripada dolaznom dokumentu
dfsAutoNumber preimenuje dolazne duplikate dodavanjem numeričkog sufiksa počevši od _2 i uzimanjem prvog slobodnog. Rezultat je reprodukovatan: zavisi samo od prisutnih imena, nikada od brojeva objekata polja, tako da spajanje istog para dokumenata daje ista imena oba puta. To svojstvo je bitno kada se nizvodni kod, uvoz FDF-a ili mapiranje baze podataka odnose na polja po imenu
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 dokumenta su i dalje netaknuta - pokušaj ponovo sa politikom
Log('duplicate field names; retrying with auto-numbering');
Lib.MergeDocumentEx(SourceDoc, dfsAutoNumber);
end;
end;
Lib.SaveToFile('application-complete.pdf');
finally
Lib.Free;
end;
end;
Obratite pažnju na dvokoračni obrazac u tom kodu, koji je moguć samo zato što je odbijanje ne-destruktivno. Prvo probajte striktnu politiku, pregledajte grešku, zatim odlučite. Sa spajanjem koje ne uspe na pola puta, rezervni plan bi morao da počne ispočetka ponovnim učitavanjem oba fajla
Kako izgleda spojen obrazac nakon toga
Pod dfsMerge, ciljno polje nazvano Shared koje nosi "Target value" i izvorno polje sa istim imenom proizvode dva polja, oba nazvana Shared, oba prijavljuju ciljnu vrednost, jer su ciljna vrednost i podrazumevana vrednost sinhronizovane u dolazno polje. To je namerna semantika za deljeno ime: jedno logičko polje, nekoliko vidžeta, jedna vrednost
Pod dfsAutoNumber, isti ulaz proizvodi Shared i Shared_2 kao odvojena polja sa nezavisnim vrednostima. Birajte između njih postavljanjem jednog pitanja: da li popunjavanje jednog treba da popuni drugo? Za potpisnikovo ime ponovljeno na svakom delu paketa, da, i dfsMerge je ispravno. Za ukupan iznos koji znači nešto drugo na svakom obrascu, ne, i automatsko numerisanje je ispravno
// Nakon spajanja, nabroji šta si zapravo dobio
for I := 1 to Lib.FormFieldCount do
Log(Format('%d: %s = %s',
[I, Lib.GetFormFieldTitle(I), Lib.GetFormFieldValue(I)]));
Praktične napomene za sastavljanje paketa obrazaca
Uspešno spajanje troši izvorni dokument: uklanja se sa liste dokumenata biblioteke, zbog čega DocumentCount pada sa dva na jedan. Ne koristite više identifikator izvora nakon toga. Verzija dokumenta se podiže na višu od dve, tako da spajanje PDF 2.0 obrasca u 1.7 dokument daje fajl verzije 2.0
Redosled je bitan za imena. Spajanje A u B i spajanje B u A daju drugačije automatski numerisane rezultate, jer dokument koji vrši spajanje zadržava svoja imena nepromenjena. Kada paket ima kanonski primarni obrazac, učinite taj cilj
Polja za potpis zaslužuju sopstveno razmatranje. Potpis primenjen pre spajanja pokriva samo reviziju koju je potpisao, tako da spajanje poništava validnost u praktičnom smislu jer se fajl promenio od trenutka potpisivanja. Sastavite prvo, a zatim potpišite sastavljen dokument, umesto da spajate potpisane delove. Kada se spajanje odnosi na sadržaj stranice, a ne na obrasce, brža putanja opisana u brzom spajanju PDF-a sa pomeranjem bajt referenci je bolji alat
Konačno, planirajte stranu podataka paketa zajedno sa spajanjem. Ako vrednosti polja stižu iz eksternog sistema, odlučite da li taj sistem adresira polja po imenu pre biranja automatskog numerisanja, jer se Shared_2 neće poklopiti sa mapiranjem koje očekuje Shared. Formati uvoza i izvoza su obrađeni u razmeni podataka obrazaca FDF, XFDF i XFA, a ponašanje skriptovanja na nivou polja koje takođe može biti pogođeno preimenovanjem je obrađeno u interaktivnim akcijama obrasca i JavaScript-u
Spajanje obrazaca, razmena podataka i potpisivanje se izvode u istoj biblioteci za Delphi, C++Builder i Free Pascal; kompletna lista funkcija je na stranici PDF Library for Delphi