PDF Library for Delphi yhdistää kaksi AcroForm-dokumenttia selkeällä käytännöllä kentille, jotka jakavat nimen. MergeDocumentEx ottaa lähdedokumentin tunnisteen ja yhden kolmesta strategiasta: dfsReject kieltäytyy yhdistämisestä, dfsMerge säilyttää jaetun nimen ja synkronoi arvot, ja dfsAutoNumber nimeää saapuvat kentät uudelleen deterministisesti. Nimien skannaus tapahtuu ennen kuin mitkään objektinumerot siirtyvät, joten hylätty yhdistäminen jättää molemmat dokumentit täysin käyttökelpoisiksi
Jokainen, joka on koonnut PDF-hakemuspaketin, on törmännyt tähän. Kolme lomaketta, joista jokaisessa on kenttä nimeltä Signature, Date tai Total, yhdistetään yhdeksi tiedostoksi. AcroFormissa täysin määritelty kentän nimi on kentän identiteetti, joten kaksi kenttää samalla nimellä eivät ole lainkaan kaksi kenttää: yhden täyttäminen täyttää toisen, ja yhteen sovellettu allekirjoitus kattaa laajuuden, jota kukaan ei tarkoittanut
Miksi nimiristiriita ratkaistaan ennen yhdistämistä?
Vanhempi MergeDocument ketjuttaa kaksi AcroForm-juurikenttätaulukkoa eikä tarjoa valintaa. Vielä pahempaa, kun tulos on käyttökelvoton, havainto tapahtuu sen jälkeen, kun objektinumerot on numeroitu uudelleen ja sivupuut ommeltu yhteen, mikä jättää kutsujan käteen dokumentin tilassa, jossa kumpikaan alkuperäinen ei ollut
MergeDocumentEx kääntää järjestyksen. Se kerää ylätason kenttänimet molemmista dokumenteista, vertailee niitä ja soveltaa strategiaa ennen kuin mikään siirtyy. Hylkäys on siis puhdas ei-toiminto: kohdedokumentti on koskematon, lähdedokumentti on koskematon, ja molemmat pysyvät avoinna ja käyttökelpoisina, minkä yhdistämistesti vahvistaa lukemalla kentän arvon takaisin lähteestä hylätyn yhdistämisen jälkeen
Vertailu käyttää järjestettyä, kirjainkokoherkkää nimijoukkoa, joten kustannus on verrannollinen yhdistettyyn kenttämäärään kertaa logaritminen tekijä, ei kahden määrän tuloon. Kirjainkokoherkkyys on tässä oikea valinta, koska PDF:n kenttänimet ovat kirjainkokoherkkiä; niiden taittaminen yhdistäisi kenttiä, joita spesifikaatio kohtelee erillisinä
Kolme strategiaa ja milloin kukin on oikea
dfsReject on strategia automatisoiduille putkille, jotka eivät saa tuottaa moniselitteisiä dokumentteja. Yhdistäminen palauttaa nollan, ja LastErrorCode raportoi arvon 705, omistetun koodin, jotta kaksoiskappalenimet voidaan erottaa jokaisesta muusta yhdistämisvirheestä ja reitittää tiettyyn korjaustoimenpiteeseen, yleensä kenttien uudelleennimeämiseen ylävirrassa
dfsMerge säilyttää jaetun nimen tarkoituksella ja synkronoi kohdearvon ja oletusarvon lähdekenttään, joten vaatimustenmukainen katseluohjelma kohtelee useita widgetejä yhtenä loogisesti nimettynä kenttänä, mikä on tavanomainen AcroForm-käyttäytyminen kentälle, jolla on useita widget-merkintöjä. Mitä se ei tee, on eri kenttäsanakirjojen taittaminen yhdeksi objektiksi. Jokainen kenttä säilyttää oman sivuassosiaationsa, ulkoasunsa ja toimintonsa, koska niiden yhdistäminen hylkäisi hiljaa saapuvaan dokumenttiin kuuluvan muotoilun ja käyttäytymisen
dfsAutoNumber nimeää saapuvat kaksoiskappaleet uudelleen liittämällä numeerisen loppuliitteen alkaen arvosta _2 ja ottamalla ensimmäisen vapaan. Tulos on toistettavissa: se riippuu vain läsnä olevista nimistä, ei koskaan kenttien objektinumeroista, joten saman dokumenttiparin yhdistäminen kahdesti tuottaa samat nimet molemmilla kerroilla. Tällä ominaisuudella on merkitystä, kun jatkokoodi, FDF-tuonti tai tietokantakuvaus viittaa kenttiin nimellä
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
// Molemmat dokumentit ovat yhä koskemattomia - yritä uudelleen käytännöllä
Log('duplicate field names; retrying with auto-numbering');
Lib.MergeDocumentEx(SourceDoc, dfsAutoNumber);
end;
end;
Lib.SaveToFile('application-complete.pdf');
finally
Lib.Free;
end;
end;
Huomaa tuon koodin kaksivaiheinen malli, joka on mahdollinen vain siksi, että hylkäys ei ole tuhoisa. Kokeile ensin tiukkaa käytäntöä, tarkasta virhe, sitten päätä. Yhdistämisellä, joka epäonnistuu kesken, varasuunnitelman täytyisi aloittaa alusta lataamalla molemmat tiedostot uudelleen
Miltä yhdistetty lomake näyttää jälkikäteen
Asetuksella dfsMerge kohdekenttä nimeltä Shared, joka kantaa arvoa "Target value", ja samannimineen lähdekenttä tuottavat kaksi kenttää, molemmat nimeltä Shared, molemmat raportoiden kohdearvon, koska kohdearvo ja oletusarvo synkronoidaan saapuvaan kenttään. Se on tarkoitettu semantiikka jaetulle nimelle: yksi looginen kenttä, useita widgetejä, yksi arvo
Asetuksella dfsAutoNumber sama syöte tuottaa Shared- ja Shared_2-kentät erillisinä kenttinä itsenäisillä arvoilla. Valitse näiden kahden väliltä kysymällä yksi kysymys: pitäisikö yhden ohjaimen täyttämisen täyttää toinen? Allekirjoittajan nimelle, joka toistuu jokaisessa paketin osassa, kyllä, ja dfsMerge on oikea. Summalle, joka tarkoittaa jotain eri lomakkeessa, ei, ja automaattinen numerointi on oikea
// Yhdistämisen jälkeen luetteloi, mitä todella sait
for I := 1 to Lib.FormFieldCount do
Log(Format('%d: %s = %s',
[I, Lib.GetFormFieldTitle(I), Lib.GetFormFieldValue(I)]));
Käytännön huomioita lomakepakettien kokoamiseen
Onnistunut yhdistäminen kuluttaa lähdedokumentin: se poistetaan kirjaston dokumenttilistalta, minkä vuoksi DocumentCount laskee kahdesta yhteen. Älä jatka lähdetunnisteen käyttöä jälkikäteen. Dokumentin versio nostetaan kahdesta korkeampaan, joten PDF 2.0 -lomakkeen yhdistäminen 1.7-dokumenttiin tuottaa 2.0-tiedoston
Järjestyksellä on merkitystä nimille. A:n yhdistäminen B:hen ja B:n yhdistäminen A:han tuottavat eri automaattisesti numeroituja tuloksia, koska yhdistämistä tekevä dokumentti säilyttää nimensä muuttumattomina. Kun paketilla on kanoninen ensisijainen lomake, tee siitä kohde
Allekirjoituskentät ansaitsevat oman harkintansa. Allekirjoitus, joka sovellettiin ennen yhdistämistä, kattaa vain sen version, jonka se allekirjoitti, joten yhdistäminen mitätöi sen käytännön mielessä, että tiedosto on muuttunut allekirjoituksen jälkeen. Kokoa ensin ja allekirjoita koottu dokumentti sen sijaan, että yhdistäisit allekirjoitettuja osia. Kun yhdistäminen koskee sivusisältöä lomakkeiden sijaan, nopeampi polku, joka kuvataan artikkelissa nopea PDF-yhdistäminen tavuviittausten siirrolla, on parempi työkalu
Lopuksi, suunnittele paketin datapuoli yhdessä yhdistämisen kanssa. Jos kentän arvot saapuvat ulkoisesta järjestelmästä, päätä, osoittaako tuo järjestelmä kenttiä nimellä ennen automaattisen numeroinnin valitsemista, koska Shared_2 ei täsmää kuvaukseen, joka odottaa nimeä Shared. Tuonti- ja vientimuodot käsitellään artikkelissa FDF-, XFDF- ja XFA-lomaketiedon vaihto, ja kenttätason skriptauskäyttäytyminen, johon uudelleennimeäminen voi myös vaikuttaa, käsitellään artikkelissa interaktiiviset lomaketoiminnot ja JavaScript
Lomakkeiden yhdistäminen, tiedonvaihto ja allekirjoitus toimivat samassa kirjastossa Delphille, C++Builderille ja Free Pascalille; täydellinen ominaisuusluettelo on sivulla PDF Library for Delphi -sivulla