如何填写PDF文本框批注。

huangapple go评论65阅读模式
英文:

How to fill PDF textbox annotations

问题

我能够使用以下代码填充文本框注释,但是该文本在某些阅读器(如Adobe Acrobat)中不会显示,尽管在Chrome和其他基于Webkit的浏览器中会显示。我尝试填充的PDF文件不使用AcroForms或FDF。我使用的是Apache PDFBox,但我认为在PDF库中几乎没有什么区别,即使在不同的语言/平台上也是如此。

// 编辑以减少代码长度
PDAnnotation annotation = doc.getPages().get(0).getAnnotations().get(0);
COSDictionary cosObject = annotation.getCOSObject();
cosObject.setString(COSName.V, content);

<br />
一个示例文档是<a href="https://www.irs.gov/pub/irs-pdf/fw4.pdf">IRS表格W-4</a>。
<br />
<br />

到目前为止我尝试过的

我尝试将我的PDF输出与在Chrome中填写的文档进行比较,但我唯一看到的区别在于默认外观(DA)属性。我尝试设置默认外观文本内容,像这样,但无济于事:

COSString defaultAppearance = (COSString)cosObject.getItem(COSName.DA);
COSString newAppearance = new COSString(defaultAppearance.getString() + &quot;0 0 Td (&quot; + value + &quot;) Tj&quot;);
cosObject.setItem(COSName.DA, newAppearance);

我还尝试过一些听起来有希望的标志:

int FLAG_PRINT = 4;
int FLAG_READ_ONLY = 64;
annotation.setAnnotationFlags(annotation.getAnnotationFlags() | FLAG_PRINT | FLAG_READ_ONLY);

我还尝试过其他属性:

cosObject.setString(COSName.CONTENTS, content);

我认为PDF 1.7规范中的相关部分是<a href="https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf">第12.7.4.3节</a>。

<br />
我错过了什么?

英文:

I'm able to fill a textbox annotation with the following code, but the text won't appear in certain readers like Adobe Acrobat, though it does appear in Chrome and other Webkit-based browsers. The PDFs I'm trying to fill do not use AcroForms or FDF. I'm using Apache PDFBox, but I don't believe there is much difference in PDF libraries, even across languages/platforms.

// edited for brevity
PDAnnotation annotation = doc.getPages().get(0).getAnnotations().get(0);
COSDictionary cosObject = annotation.getCOSObject();
cosObject.setString(COSName.V, content);

<br />
An example document is <a href="https://www.irs.gov/pub/irs-pdf/fw4.pdf">IRS form W-4</a>.
<br />
<br />

What I've tried so far

I've tried comparing my PDF output against a document filled in Chrome, but the only difference I see is in the default appearance (DA) property. I've tried to set the default appearance text content like this, but to no avail:

COSString defaultAppearance = (COSString)cosObject.getItem(COSName.DA);
COSString newAppearance = new COSString(defaultAppearance.getString() + &quot;0 0 Td (&quot; + value + &quot;) Tj&quot;);
cosObject.setItem(COSName.DA, newAppearance);

I've also messed around with a few flags that sounded promising:

int FLAG_PRINT = 4;
int FLAG_READ_ONLY = 64;
annotation.setAnnotationFlags(annotation.getAnnotationFlags() | FLAG_PRINT | FLAG_READ_ONLY);

I've also tried other properties:

cosObject.setString(COSName.CONTENTS, content);

I believe the relevant section in <a href="https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf">the PDF 1.7 spec</a> is 12.7.4.3.

<br />
What am I missing?

答案1

得分: 1

Your PDF does use acroform fields. The widgets annotations are the visual representation of the field. What you want to do is to set the field. Here's the SetField.java example from the source code download. Call it with these parameters: filename, field name (the first name is "topmostSubform[0].Page1[0].Step1a[0].f1_01[0]") and a value.

To get the field names, download PDFDebugger and hover the mouse over the fields you like to set.

And here's how the field looks after being set:

如何填写PDF文本框批注。

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pdfbox.examples.interactive.form;

import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDCheckBox;
import org.apache.pdfbox.pdmodel.interactive.form.PDComboBox;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import org.apache.pdfbox.pdmodel.interactive.form.PDListBox;
import org.apache.pdfbox.pdmodel.interactive.form.PDRadioButton;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;

/**
 * This example will take a PDF document and set a form field in it.
 *
 * @author Ben Litchfield
 *
 */
public class SetField
{
    /**
     * This will set a single field in the document.
     *
     * @param pdfDocument The PDF to set the field in.
     * @param name The name of the field to set.
     * @param value The new value of the field.
     *
     * @throws IOException If there is an error setting the field.
     */
    public void setField(PDDocument pdfDocument, String name, String value) throws IOException
    {
        PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
        PDAcroForm acroForm = docCatalog.getAcroForm();
        PDField field = acroForm.getField(name);
        if (field != null)
        {
            if (field instanceof PDCheckBox)
            {
                if (value.isEmpty())
                    ((PDCheckBox) field).unCheck();
                else
                    ((PDCheckBox) field).check();
            }
            else if (field instanceof PDComboBox)
            {
                field.setValue(value);
            }
            else if (field instanceof PDListBox)
            {
                field.setValue(value);
            }
            else if (field instanceof PDRadioButton)
            {
                field.setValue(value);
            }
            else if (field instanceof PDTextField)
            {
                field.setValue(value);
            } 
        }
        else
        {
            System.err.println("No field found with name:" + name);
        }
    }

    /**
     * This will read a PDF file and set a field and then write it the pdf out
     * again. <br>
     * see usage() for commandline
     *
     * @param args command line arguments
     *
     * @throws IOException If there is an error importing the FDF document.
     */
    public static void main(String[] args) throws IOException
    {
        SetField setter = new SetField();
        setter.setField(args);
    }

    private void setField(String[] args) throws IOException
    {
        PDDocument pdf = null;
        try
        {
            if (args.length != 3)
            {
                usage();
            }
            else
            {
                SetField example = new SetField();
                pdf = PDDocument.load(new File(args[0]));
                example.setField(pdf, args[1], args[2]);
                pdf.save(args[0]);
            }
        }
        finally
        {
            if (pdf != null)
            {
                pdf.close();
            }
        }
    }

    /**
     * This will print out a message telling how to use this example.
     */
    private static void usage()
    {
        System.err.println("usage: org.apache.pdfbox.examples.interactive.form.SetField <pdf-file> <field-name> <field-value>");
    }
}
英文:

Your PDF does use acroform fields. The widgets annotations are the visual representation of the field. What you want to do is to set the field. Here's the SetField.java example from the source code download. Call it with these parameters: filename, field name (the first name is "topmostSubform[0].Page1[0].Step1a[0].f1_01[0]") and a value.

To get the field names, download PDFDebugger and hover the mouse over the fields you like to set.

And here's how the field looks after being set:

如何填写PDF文本框批注。

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the &quot;License&quot;); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.pdfbox.examples.interactive.form;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDCheckBox;
import org.apache.pdfbox.pdmodel.interactive.form.PDComboBox;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import org.apache.pdfbox.pdmodel.interactive.form.PDListBox;
import org.apache.pdfbox.pdmodel.interactive.form.PDRadioButton;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
/**
* This example will take a PDF document and set a form field in it.
*
* @author Ben Litchfield
*
*/
public class SetField
{
/**
* This will set a single field in the document.
*
* @param pdfDocument The PDF to set the field in.
* @param name The name of the field to set.
* @param value The new value of the field.
*
* @throws IOException If there is an error setting the field.
*/
public void setField(PDDocument pdfDocument, String name, String value) throws IOException
{
PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
PDField field = acroForm.getField(name);
if (field != null)
{
if (field instanceof PDCheckBox)
{
if (value.isEmpty())
((PDCheckBox) field).unCheck();
else
((PDCheckBox) field).check();
}
else if (field instanceof PDComboBox)
{
field.setValue(value);
}
else if (field instanceof PDListBox)
{
field.setValue(value);
}
else if (field instanceof PDRadioButton)
{
field.setValue(value);
}
else if (field instanceof PDTextField)
{
field.setValue(value);
} 
}
else
{
System.err.println(&quot;No field found with name:&quot; + name);
}
}
/**
* This will read a PDF file and set a field and then write it the pdf out
* again. &lt;br&gt;
* see usage() for commandline
*
* @param args command line arguments
*
* @throws IOException If there is an error importing the FDF document.
*/
public static void main(String[] args) throws IOException
{
SetField setter = new SetField();
setter.setField(args);
}
private void setField(String[] args) throws IOException
{
PDDocument pdf = null;
try
{
if (args.length != 3)
{
usage();
}
else
{
SetField example = new SetField();
pdf = PDDocument.load(new File(args[0]));
example.setField(pdf, args[1], args[2]);
pdf.save(args[0]);
}
}
finally
{
if (pdf != null)
{
pdf.close();
}
}
}
/**
* This will print out a message telling how to use this example.
*/
private static void usage()
{
System.err.println(&quot;usage: org.apache.pdfbox.examples.interactive.form.SetField &lt;pdf-file&gt; &lt;field-name&gt; &lt;field-value&gt;&quot;);
}
}

huangapple
  • 本文由 发表于 2020年8月21日 01:04:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63509975.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定