Odborný článok

Pridať polia AcroForm do načítaného PDF v Delphi

Máte šablónu faktúry od tretej strany alebo archivovanú zmluvu, ktorú niekto pred rokmi vygeneroval v softvéri, ktorý už nikto nevie nájsť, a úlohou je urobiť z nej interaktívny dokument: pridať do rohu podpisové pole, doplniť niekoľko textových polí a z plochého kontrolného zoznamu spraviť skutočné zaškrtávacie políčka. Háčik je v tom, že tento PDF nevytvárate od nuly. Už existuje, už má stránky, dátové toky obsahu aj písma, ktoré nemáte pod kontrolou, a na tento objektový graf potrebujete bez prestavby napojiť widgety AcroForm. To je iný problém ako vytváranie formulára v novom dokumente, a časť, ktorá ľudí zradí, je neviditeľná, až kým neotvoríte výsledok vo vykresľovači a polia, ktoré ste práve zapísali, nie sú na stránke nikde viditeľné

HotPDF je natívny VCL PDF komponent pre Delphi a C++Builder a od verzie v2.247.0 ponúka vyhradenú sadu metód presne na toto: vytváranie všetkých šiestich štandardných typov polí priamo na dokumente načítanom pomocou LoadFromFile. Tento článok prechádza tým, čo tieto metódy robia, aký slovník ISO 32000-1 vytvárajú, a tým jedným príznakom, bez ktorého celý postup potichu vyprodukuje súbor, ktorý vyzerá prázdne

Prečo je vytváranie polí v načítanom dokumente vlastná vetva kódu

Keď vytvárate PDF od nuly, HotPDF vlastní celý objektový model. Každá stránka je zapisovateľný THPDFPageobal a pridanie textového poľa cez AddTextFieldzapojí nový widget do objektu anotácie stránky, objektu stránky aj zbierky polí formulára a potom vygeneruje appearance stream z fontových zdrojov dokumentu. Appearance stream je viditeľná plocha widgetu, rámček, okraj aj akýkoľvek predvolený text, vykreslené ako kresliace operátory PDF, ktoré vykresľovač zobrazí doslova

Na načítanom dokumente nič z toho nemáte. Stránky prišli ako surové slovníky; neexistuje zapisovateľný THPDFPageobal THPDFPage, na ktorý by ste widget zavesili, a čo je dôležitejšie, neexistuje ani žiadny fontový kanál pripravený kresliť appearance streamy. Načítaná cesta preto ide inou trasou. Zapíše slovníky polí priamo do parsovaného objektového grafu a adresuje stránky podľa indexu od nuly namiesto objektu stránky. Typy polí aj bity príznakov sa presne zhodujú s cestou od nuly, takže Text field je Text field v oboch prípadoch; mení sa pod tým len zapojenie a, čo je rozhodujúce, aj to, ako sa kreslí povrch widgetu

Príznak /NeedAppearances tu nie je voliteľný

Toto je jediný fakt, ktorý rozhoduje o tom, či sa vaša práca zobrazí. Keďže načítaná cesta nevytvára appearance streamy, novo pridaný widget dorazí do vykresľovača bez /APpoložky /AP: pole bez opísaného povrchu. Mnohé vykresľovače, keď majú vykresliť widget bez appearance a bez pokynu, aby ho vytvorili, nevykreslia vôbec nič. Pole je v súbore, štruktúrne platné, dostupné nástroju na vypĺňanie formulára a pre človeka úplne neviditeľné

Úniková cesta je definovaná v ISO 32000-1 §12.7.3: slovník AcroForm nesie /NeedAppearancesboolean /NeedAppearances a keď je truetrue, vyhovujúci čítač je povinný sám zostaviť chýbajúce appearance streamy z každého poľa z jeho /DA(default appearance) reťazca a hodnoty. HotPDF to nastaví za vás. Keď prvýkrát pridáte akékoľvek pole do načítaného dokumentu, EnsureLoadedAcroFormbeží: ak katalóg nemá /AcroForm, vytvorí ho, ak neexistuje /Fieldspole, vytvorí aj to a vynúti /NeedAppearances true. Priamo ho nevoláte, ale keď viete, že existuje, vysvetľuje to správanie. Zároveň vysvetľuje aj jedno obmedzenie nasadenia, ktoré sa oplatí povedať otvorene: hŕstka minimalistických alebo nevyhovujúcich vykresľovačov ignoruje /NeedAppearancesa aj tak nič nevykreslí. Pre bežných čitateľov príznak funguje, ale ak vaše publikum používa nezvyčajný zabudovaný renderer, otestujte to tam skôr, než niečo prisľúbite

Pridávanie šiestich typov polí

Každá metóda sleduje rovnaký tvar. Zadáte index stránky od nuly, štyri rohy obdĺžnika widgetu v súradniciach PDF user-space, názov poľa a všetky ďalšie argumenty, ktoré daný typ potrebuje. Obdĺžnik je X1, Y1, X2, Y2s počiatkom PDF v ľavom dolnom rohu stránky, takže väčšie hodnoty Y ležia vyššie; toto je súradnicová konvencia formátu súboru, nie konvencia obrazovky s počiatkom vľavo hore, a pomýliť si to je druhá najčastejšia chyba po zabudnutí na príznak. Každé volanie vráti index nového poľa od nuly alebo -1ak bol index stránky mimo rozsahu alebo sa objekt stránky nepodarilo vyriešiť

var
  Pdf: THotPDF;
  Idx: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('contract.pdf') <= 0 then Exit;

    // Text field: name, initial value, max length (0 = unlimited)
    Idx := Pdf.AddLoadedTextField(0, 72, 680, 320, 700, 'FullName', '', 0);

    // CheckBox: export value, initial checked state
    Pdf.AddLoadedCheckBox(0, 72, 640, 90, 658, 'AgreeTerms', 'Yes', False);

    // Signature field: just a name and a rectangle
    Pdf.AddLoadedSignatureField(0, 360, 72, 540, 132, 'ApproverSig');

    if Idx >= 0 then
      Pdf.SaveLoadedDocument('contract-interactive.pdf');
  finally
    Pdf.Free;
  end;
end;

Tretí a štvrtý stringový argument textového poľa sú názov poľa a jeho počiatočná /Vhodnota; celé číslo je /MaxLen, zapisované len vtedy, keď je väčšie ako nula. HotPDF dáva každému upraviteľnému poľu predvolený reťazec vzhľadu /Helv 12 Tf 0 0 0 rg, ktorý je to, podľa čoho /NeedAppearancesrešpektujúci vykladač číta rozhoduje o písme a farbe, ktorou hodnotu vykreslí. Checkbox prijíma exportnú hodnotu, reťazec, ktorý formulár odošle, keď je políčko zaškrtnuté, plus boolean pre počiatočný stav; interne zapíše zodpovedajúce /V, /ASa /DVpoložky názvu, aby bol stav on/off konzistentný presne v momente otvorenia súboru. Prázdna exportná hodnota sa predvolene nastaví na Yes, tradičný názov checkboxu pre stav "on"

Polia výberu a bitové príznaky /Ff

ComboBox aj ListBox sú výberové polia, typ poľa /Chv ISO 32000-1 §12.7.4. Rozdiel medzi rozbaľovacím zoznamom a posuvným zoznamom je jeden bit v celočíselných príznakoch poľa /Ff: bit 18, Combo flag, hodnota $40000. HotPDF nastaví tento bit pre AddLoadedComboBoxa nechá ho vypnutý pre AddLoadedListBox; inak sú obidve totožné a obidve prijímajú svoje voľby ako otvorené pole reťazcov zapísané do /Optpoložky

// Dropdown (Combo flag set internally) with an initial selection
Pdf.AddLoadedComboBox(0, 72, 600, 300, 620, 'Country', 'Canada',
  ['United States', 'Canada', 'Mexico']);

// Scrolling list, no initial value
Pdf.AddLoadedListBox(0, 72, 520, 300, 590, 'Priority', '',
  ['Low', 'Normal', 'High']);

// Push button with a caption drawn through /MK
Pdf.AddLoadedPushButton(0, 360, 600, 480, 626, 'SubmitBtn', 'Submit');

Dve poznámky k zoznamu volieb. HotPDF zapisuje každú /Optpoložku ako obyčajný reťazec, kde exportná hodnota aj zobrazený popis sú ten istý text. ISO 32000-1 §12.7.4.4 povoľuje aj dvojprvkový [export display]formát, keď potrebujete, aby sa odoslaná hodnota líšila od toho, čo používateľ číta; metódy načítaného vytvárania používajú jednoduchší jednoreťazcový formát, takže ak potrebujete odlišné exportné a zobrazované hodnoty, nastavíte ich sami na výslednom slovníku. A hodnota, ktorú odovzdáte ako aktuálny výber poľa, by mala byť jednou z ponúknutých možností, pretože ju vykresľovač porovnáva so zoznamom

Tlačidlo PushButton je ďalší prípad riadený príznakom: typ poľa /Btns bitom 17, príznakom PushButton, hodnota $10000. Tento bit oddeľuje klikateľné tlačidlo od checkboxu, ktorý je tiež /Btnpoľom, ale bez neho. Popis, ktorý zadáte, sa zapíše do slovníka appearance characteristics /MKako normálny caption /CA. Je fér povedať otvorene aj rozsah tejto funkcie: tlačidlo sa vytvorí s vlastným popisom a obdĺžnikom, ale metóda vytvorenia pre načítaný dokument nepripája akciu, takže samo o sebe je to tlačidlo, ktoré vyzerá správne a po kliknutí nerobí nič. Napojenie akcií submit, reset alebo JavaScript je samostatná téma; na strane vytvárania od nuly je workflow field-plus-action pokrytý v vytváranie polí AcroForm a akcií v Delphi, čo je správny porovnávací bod pre to, čo načítaná cesta zámerne vynecháva

Slovník, ktorý zdieľa každé pole

Pod všetkými šiestimi metódami je jeden spoločný zostavovač, ktorý vytvára widget annotation a registruje ho na dvoch miestach. Zapíše /Type /Annota /Subtype /Widget, /Rectpole z vašich štyroch súradníc, príznaky anotácie /F 4ktoré nastavujú Print bit, aby sa pole zobrazovalo aj na papieri, aj na obrazovke, názov poľa /T, typ poľa /FT, príznaky /Ffa /Pspätný odkaz na objekt stránky. Potom pripojí nové pole do poľa AcroForm /Fieldsa do poľa tejto stránky /Annots, pričom po ceste vyrieši nepriame odkazy, aby rozšíril skutočné polia namiesto osamoteného widgetu

Táto dvojitá registrácia je dôležitá, pretože widget, ktorý žije len v jednom z týchto dvoch zoznamov, je poškodený na jemnom mieste. Pole prítomné v /Fieldsale chýbajúce v zozname stránky /Annotsje pre formulár známe, ale nikdy sa nevykreslí; opačný stav sa vykreslí, ale logika formulára o ňom nevie. HotPDF drží obe strany v súlade pri každom pridaní, čo je druh účtovníctva, ktorý by ste inak museli podľa špecifikácie urobiť presne ručne

Pár poctivých obmedzení

Nastavte očakávania ešte predtým, než na tomto postavíte workflow. Správanie flatten-and-regenerate závisí od toho, či vykresľovač rešpektuje /NeedAppearances, čo pokrýva Acrobat, moderné PDF jadrá prehliadačov aj bežné desktopové čítačky, ale nie je to pevná záruka naprieč každým rendererom v divočine. Ak musíte vytvoriť súbor, ktorého polia sa vykreslia rovnako všade, vrátane vykresľovačov, ktoré príznak ignorujú, ste v teritóriu appearance streamov a cesta vytvárania od nuly, ktorá vám vykresľuje /APje lepšia voľba. Podpisové pole sa rovnako vytvára ako prázdny podpisový widget pripravený na podpísanie; umiestniť pole nie je to isté ako použiť kryptografický podpis

Pri zmene toho, čo už existuje, namiesto pridávania, je súvisiaca operácia form flattening, kde interaktívne polia zapracujete späť do statického obsahu stránky, aby sa hodnoty stali trvalé a neupraviteľné; tento návratový krok, vrátane toho, ako sa spracúvajú formuláre s XFA, je rozobratý v flattening XFA and AcroForm fields in Delphi. Pridávanie polí a flattening polí sú dva konce rovnakého životného cyklu: tento článok je o tom, ako dostať interaktivitu na dokument, ktorému chýbala, a flattening je o tom, ako ju po tom, čo formulár splnil svoj účel, zasa zobrať preč

Načítaným dokumentom vytvárané formulárové API uvedené tu je súčasťou štandardného HotPDF Componentpre Delphi a C++Builder spolu s úplnou referenciou príznakov polí, spracovania appearance a zvyšku modelu AcroForm