【问题标题】:Add calculation script to pdf form fields with PDFBox使用 PDFBox 将计算脚本添加到 pdf 表单字段
【发布时间】:2021-09-26 13:53:28
【问题描述】:

也许有人可以帮助我解决这个问题。我有一个 java 应用程序,它使用 fly-saucer-pdf 从 HTML 模板生成 PDF 文件。由于不支持 JavaScript,我打算在使用 PDFBox 创建 PDF 后添加我的 JavaScript。

我想添加 JavaScript 以从字段 A 中读取一个值,根据该值计算一个新的总和并将其写入另一个字段 B。每次输入字段 A 中的值发生更改时,都应该进行此计算。

我的问题是,我不知道如何将我的 JavaScript 添加到现有的 PDF 文件中。我在网上找到了这个example 关于如何添加 JavaScript,但它只显示了如何将动作注册到 PDF 的打开事件。这无济于事,因为我想添加计算脚本下Acrobat JS Developer Guide 中所述的计算。

我想我必须以某种方式修改文档PDAcroForm。甚至还有一个getScriptingHandler()-Method,这似乎很有希望,它在我的文档中是空的。到目前为止,我添加 JavaScript 的代码如下所示:

try (var document = PDDocument.load(pdfFile)) {
  var documentDocumentCatalog = document.getDocumentCatalog();
  var documentAcroForm = documentDocumentCatalog.getAcroForm();
  var javascriptString = FileUtils.readFileToString(
                           javascriptFile, 
                           StandardCharsets.UTF_8,
                         );
  var javascript = new PDActionJavaScript(javascriptString);
  documentAcroForm.getScriptingHandler().calculate(javascript, "99");
} catch (IOException e) {
  e.printStackTrace();
}

>>更新

感谢您的意见,我已经成功地实现了计算新值的目标。我的 Java 代码现在看起来像这样:

try (var document = PDDocument.load(pdfFile)) {
  var catalog = document.getDocumentCatalog();
  var acroForm = catalog.getAcroForm();

  var fieldActions = new PDFormFieldAdditionalActions();
  var javascriptString = FileUtils.readFileToString(javascriptFile, StandardCharsets.UTF_8);
  var actionJavaScript = new PDActionJavaScript(javascriptString);
  actionJavaScript.setAction(javascriptString);
  fieldActions.setC(actionJavaScript);

  var field = (PDTextField) acroForm.getField("fieldA");
  field.setActions(fieldActions);
  var coArray = new COSArray();
  coArray.add(field);
  acroForm.getCOSObject().setItem(COSName.CO, coArray);

  document.save(pdfFile);
} catch (IOException e) {
  e.printStackTrace();
}

我的 JavaScript 代码如下所示:

calculateValue("fieldA", "fieldB");

function calculateValue(sourceFieldName, targetFieldName) {
    this.getField(sourceFieldName).value = Math.floor(this.getField(targetFieldName).value / 2 - 5)
}

这很有效,虽然我偶然发现了一些奇怪的行为,但也许我只是误解了 change 事件。使用此代码,即使我只在重新计算顺序中添加了“fieldA”,似乎任何字段的任何更改都会触发事件。我真正想要实现的是,只有特定字段的更改才会触发另一个特定字段的重新计算。这是重新计算应该如何工作的方式吗?

>>更新2

好吧,没关系,我只是犯了一个错误,并在每次重新计算事件时更新了两个字段...在调整了我的 JavaScript 之后,现在一切都按预期工作了。

还有一个问题,如何在文档中全局添加一个 JavaScript 函数,然后在字段事件中调用它?

感谢您的帮助!

【问题讨论】:

  • 还可以查看示例 UpdateFieldOnDocumentOpen.java 和 AddJavascript.java 。 getScriptingHandler() 返回一个接口,所以如果你没有创建一个处理程序,你将一无所获。

标签: javascript java pdfbox


【解决方案1】:

在 PDF 级别上,它看起来像这样:

//The text field
10 0 obj
<</AA<</C 12 0 R>>/AP<</N 100 0 R>>/F 4/FT/Tx/Ff 2/MK<</BC[0.0 0.0 0.0]>>/P 23 0 R/Rect[339.288 570.374 443.231 589.985]/Subtype/Widget/T(Textfield10)/Type/Annot/V(7)>>
endobj

//The JS function which writes the result of 'Textfield1'+'Textfield3' into Textfield10
12 0 obj
<</JS(AFSimple_Calculate\("SUM", new Array \("Textfield1", "Textfield3"\)\);)/S/JavaScript>>
endobj

14 0 obj
<</CO[10 0 R]/DA(/Helv 0 Tf 0 g )/Fields[10 0 R 16 0 R 18 0 R] ...>>

如您所见,附加操作 (AA) 属性是使用的关键。网上或SO 上有几个关于如何做到这一点的答案。它看起来像这样:

PDFormFieldAdditionalActions pdFormFieldAdditionalActions = new PDFormFieldAdditionalActions();
PDActionJavaScript jsSumAction = new PDActionJavaScript();
jsSumAction .setAction("AFSimple_Calculate\("SUM", new Array \("Textfield1", "Textfield3"\)\);");
pdFormFieldAdditionalActions.setC((PDAction) jsSumAction);

请注意,这里使用的 JS 语法是 *dobe JS 语法 - 所以它可能不适用于其他查看器。但这就是 PDF 中的 JS 脚本的问题,也是 PDF/A 中禁止使用它的原因之一......

【讨论】:

  • 我得到了它的工作,但现在我正在努力解决一些意外行为......我更新了我的问题。
  • 请提供示例 PDF 或显示 PDF 代码 sn-p(就像我在帖子的上半部分所做的那样)
  • 我刚刚意识到我在 JavaScript 中犯了一个错误,我更新了我的帖子,计算现在按预期工作。
猜你喜欢
  • 1970-01-01
  • 2012-01-21
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
相关资源
最近更新 更多