2016-10-19 20 views
0

フィールドがある簡単なPDFの複数ページ文書を作成しようとしています。これを行うために、私はテンプレートpdfを持っています。このpdfは、ドキュメント自体を作成するために必要なだけこのテンプレートをクローンします。複数ページの文書にデータを挿入するPDFBox

いくつかのデータを挿入すると問題が発生します。ドキュメントに挿入しようとするデータの種類は、ページ間で変更されることは想定されていません。それよりむしろ、このドキュメントに含まれるページの数を表す「ページ」桁のように、すべてのページに静的にとどまります。

私のテンプレートの中には、「Shipper1」や「Pages」のようなテキストフィールドがあります。このテキストフィールドにデータを挿入して、ドキュメント内のすべてのページに「Shipper1」と「Pages」フィールドにこの値を設定できるようにしたいと考えています。

現在のところ、自分のコードでは最初のページにしか表示されません。それはデータを完全に示しています。一方、私が別のページに行くと、データはそこに表示されません。空のフィールドが表示されます。

static void initiatePdf() { 
     // Initiate a new PDF Box object and get the acro form from it 
     File file = new File(Constants.Paths.EMPTY_DOC) 
     PDDocument tempDoc 

     Evaluator evaluator = new Evaluator(metaHolder) 
     int numPages = evaluator.getNumOfPagesRequired(objects) 

     FieldRenamer renamer = new FieldRenamer() 

     PDResources res = new PDResources() 
     COSDictionary acroFormDict = new COSDictionary() 

     List<PDField> fields = [] 

     Closure isFieldExist = {List<PDField> elements, String fieldName -> 
      elements.findAll{it.getFullyQualifiedName() == fieldName}.size() > 0 
     } 

     for(int i = 0; i < numPages; i++) { 
      tempDoc = new PDDocument().load(file) 

      PDDocumentCatalog docCatalog = tempDoc.getDocumentCatalog() 
      PDAcroForm acroForm = docCatalog.acroForm 

      PDPage page = (PDPage) docCatalog.getPages().get(0) 

      renamer.setCurrentForm(acroForm) 

      if(i == 0) { 
       res = acroForm.getDefaultResources() 
       acroFormDict.mergeInto(acroForm.getCOSObject()) 
       renamer.renameFields(1) 
      } else 
       renamer.renameFields(i*10+1) 

      List<PDField> newFields = acroForm.fields.findAll { PDField newField -> 
       isFieldExist(fields, newField.getFullyQualifiedName()) == false 
      } 

      fields.addAll(newFields) 
      document.addPage(page) 
     } 

     PDAcroForm acroForm = new PDAcroForm(document, acroFormDict); 
     acroForm.setFields(fields) 

     acroForm.setDefaultResources(res); 

     document.documentCatalog.setAcroForm(acroForm) 
    } 

最初のもののカップルは: metaHolderインスタンスはアクロフォームの中に存在するすべての フィールドに関する情報を保持している。ここ

は、私は、PDFドキュメントを開始するコードです。情報は次のとおりです:フィールド名、フィールドウィジェット幅、フィールドフォントおよびフォントサイズ

evaluatorは、Evaluatorクラスの単なるインスタンスです。その目的は、動的データを分析し、すべてのテキストデータを含むページ数を決定することです。

static void populateData() { 
    def properties = ["$Constants.Fields.SHIPPER" : "David"] 
    FieldPopulater populater = new FieldPopulater(document, metaHolder) 

    populater.populateStaticFields(properties) 
} 

FieldPopulaterクラス:

package app.components 

import app.StringUtils 
import app.components.entities.DGObject 
import app.components.entities.FieldMeta 
import org.apache.pdfbox.pdmodel.PDDocument 
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm 
import org.apache.pdfbox.pdmodel.interactive.form.PDField 

/** 
* Created by David on 18/10/2016. 
*/ 
class FieldPopulater { 

    PDAcroForm acroForm 
    FormMetaHolder metaHolder 
    FieldPopulater(PDDocument document, FormMetaHolder metaHolder) { 
     this.acroForm = document.getDocumentCatalog().acroForm 
     this.metaHolder = metaHolder 
    } 

    void populateStaticFields(properties) { 
     List<PDField> fields = [] 
     properties.each {fieldName, data -> 
      FieldMeta fieldMeta = metaHolder.getMetaData(fieldName) 

      fields = acroForm.fields.findAll { PDField field -> 
       String currentName = field.getFullyQualifiedName() 
       char lastChar = currentName[-1] 
       if(Character.isDigit(lastChar)) { 
        currentName = currentName.substring(0,currentName.size()-1) 
       } 

       currentName == fieldName 
      } 

      if(fields.size() > 1) { 
       int counter = 1 
       String tempData = data 
       String currentFitData 
       while(tempData.isEmpty() != true) { 
        int maxWords = Utils.getMaxWords(tempData, fieldMeta) 
        currentFitData = StringUtils.getTextByWords(tempData, maxWords) 
        tempData = StringUtils.chopTextByWords(tempData, maxWords) 

        PDField field = fields.find{it.getFullyQualifiedName()[-1] == "$counter"} 
        field?.setValue(currentFitData) 

        counter++ 
       } 
      } else { 
       PDField tempField = fields[0] 
       tempField.setValue(data) 
      } 
     } 
    } 
} 

結果は、最初のページには、フィールド「荷主」は値を持っている私は、テキストとフィールドを移入しようとするのはここ

です"David"の 2番目のページでは、 "Shipper"フィールドは空です。

ここに画像があります。最初のページ:

2ページ目:

は、ここでの問題は何ですか?

更新:すべてのフィールドがフィールドを表すいくつかの子供ウィジェットになるように、新しいacroフォームのすべてのウィジェットを現在のページに追加しようとしましたが、それでも動作しません。

// All the widgets that are associated with the fields 
List<PDAnnotationWidget> widgets = acroForm.fields.collect {PDField field -> field.getWidgets().get(0)} 

page.annotations.addAll(widgets) 

UPDATE:フィールドの現在のウィジェットを親フィールドのウィジェットのコレクションに追加しようとしました。ここでは、コードは次のとおりです。

List<PDAnnotationWidget> widgets = [] 
// All the widgets that are associated with the fields 
acroForm.fields.each {PDField field -> 
     PDAnnotationWidget widget = field.widgets.get(0) 

     // Adding the following widget to the page and to the field's list of annotation widgets 
     widgets.add(widget) 
     fields.find {it.getFullyQualifiedName() == field.getFullyQualifiedName()}?.widgets.add(widget) 
      } 

page.annotations.addAll(widgets) 
+0

ここに遅れているので、簡単なヒント:ページに同じ値を設定するには、フィールドごとに複数の注釈ウィジェット、つまりすべてのページに1つの注釈ウィジェットが必要です。フィールドには、これらのウィジェットが子供として必要です。ページにはそれぞれ、アノテーションリストにこのウィジェットが含まれている必要があります。このような機能を持つ既存のフォームドキュメントを入手(またはAdobe Acrobatを使用している場合はAdobe Acrobatで作成)し、PDFDebuggerで表示します。 –

+0

私はあなたが言ったこと、つまりアクロフォームのウィジェットをページに追加しようとしましたが、問題は残っています。投稿したコードを投稿に追加しました –

+0

いいえ、すべてのページに別々のウィジェットが必要です。私。フィールドには2つの子供用ウィジェットが必要です。私はacroformの例を拡張するために自分自身にメモを作った。 –

答えて

0

あなたが望むことは、同じフィールドのsereval視覚的表現を持つことです。これは、そのようなフィールドのための複数の注釈ウィジェットを持つことによって行われます。

フィールドにはアノテーションウィジェットが1つしかない場合、共通の辞書が共有されます。数がある場合、注釈ウィジェットはフィールドの子リストにあります。

1つのフィールドに複数の注釈ウィジェットが必要な場合は、field.getWidgets().get(0)を呼び出す代わりに、new PDAnnotationWidget()という注釈ウィジェットを作成し、それを使用する必要があります。これらのウィジェットはリストに追加する必要があり、このリストはsetWidgets()のフィールドに割り当てる必要があります。ウィジェットごとにsetRectangle()setPage()setParent()を呼び出す必要があります。

この例は、新しいCreateMultiWidgetsForm.java exampleです。 setParent()メソッドは、2.0.3ではまだ使用できません(しかし2.0.4にあります)。この答えでは、それはあまりエレガントな方法で同じことをする呼び出しに置き換えられます。

public final class CreateMultiWidgetsForm 
{ 
    private CreateMultiWidgetsForm() 
    { 
    } 

    public static void main(String[] args) throws IOException 
    { 
     // Create a new document with 2 empty pages. 
     PDDocument document = new PDDocument(); 
     PDPage page1 = new PDPage(PDRectangle.A4); 
     document.addPage(page1); 
     PDPage page2 = new PDPage(PDRectangle.A4); 
     document.addPage(page2); 

     // Adobe Acrobat uses Helvetica as a default font and 
     // stores that under the name '/Helv' in the resources dictionary 
     PDFont font = PDType1Font.HELVETICA; 
     PDResources resources = new PDResources(); 
     resources.put(COSName.getPDFName("Helv"), font); 

     // Add a new AcroForm and add that to the document 
     PDAcroForm acroForm = new PDAcroForm(document); 
     document.getDocumentCatalog().setAcroForm(acroForm); 

     // Add and set the resources and default appearance at the form level 
     acroForm.setDefaultResources(resources); 

     // Acrobat sets the font size on the form level to be 
     // auto sized as default. This is done by setting the font size to '0' 
     String defaultAppearanceString = "/Helv 0 Tf 0 g"; 
     acroForm.setDefaultAppearance(defaultAppearanceString); 

     // Add a form field to the form. 
     PDTextField textBox = new PDTextField(acroForm); 
     textBox.setPartialName("SampleField"); 
     // Acrobat sets the font size to 12 as default 
     // This is done by setting the font size to '12' on the 
     // field level. 
     // The text color is set to blue in this example. 
     // To use black, replace "0 0 1 rg" with "0 0 0 rg" or "0 g". 
     defaultAppearanceString = "/Helv 12 Tf 0 0 1 rg"; 
     textBox.setDefaultAppearance(defaultAppearanceString); 

     // add the field to the AcroForm 
     acroForm.getFields().add(textBox); 

     // Specify 1st annotation associated with the field 
     PDAnnotationWidget widget1 = new PDAnnotationWidget(); 
     PDRectangle rect = new PDRectangle(50, 750, 250, 50); 
     widget1.setRectangle(rect); 
     widget1.setPage(page1); 
     widget1.getCOSObject().setItem(COSName.PARENT, textBox); 

     // Specify 2nd annotation associated with the field 
     PDAnnotationWidget widget2 = new PDAnnotationWidget(); 
     PDRectangle rect2 = new PDRectangle(200, 650, 100, 50); 
     widget2.setRectangle(rect2); 
     widget2.setPage(page2); 
     widget2.getCOSObject().setItem(COSName.PARENT, textBox); 

     // set green border and yellow background for 1st widget 
     // if you prefer defaults, just delete this code block 
     PDAppearanceCharacteristicsDictionary fieldAppearance1 
       = new PDAppearanceCharacteristicsDictionary(new COSDictionary()); 
     fieldAppearance1.setBorderColour(new PDColor(new float[]{0,1,0}, PDDeviceRGB.INSTANCE)); 
     fieldAppearance1.setBackground(new PDColor(new float[]{1,1,0}, PDDeviceRGB.INSTANCE)); 
     widget1.setAppearanceCharacteristics(fieldAppearance1); 

     // set red border and green background for 2nd widget 
     // if you prefer defaults, just delete this code block 
     PDAppearanceCharacteristicsDictionary fieldAppearance2 
       = new PDAppearanceCharacteristicsDictionary(new COSDictionary()); 
     fieldAppearance2.setBorderColour(new PDColor(new float[]{1,0,0}, PDDeviceRGB.INSTANCE)); 
     fieldAppearance2.setBackground(new PDColor(new float[]{0,1,0}, PDDeviceRGB.INSTANCE)); 
     widget2.setAppearanceCharacteristics(fieldAppearance2); 

     List <PDAnnotationWidget> widgets = new ArrayList<PDAnnotationWidget>(); 
     widgets.add(widget1); 
     widgets.add(widget2); 
     textBox.setWidgets(widgets); 

     // make sure the annotations are visible on screen and paper 
     widget1.setPrinted(true); 
     widget2.setPrinted(true); 

     // Add the annotations to the pages 
     page1.getAnnotations().add(widget1); 
     page2.getAnnotations().add(widget2); 

     // set the field value 
     textBox.setValue("Sample field"); 

     document.save("MultiWidgetsForm.pdf"); 
     document.close(); 
    } 
} 
関連する問題