Maybe someone can help me with this. I have a java application, which generates a PDF file from an HTML template using flying-saucer-pdf. Since there is no support for JavaScript, I'm planning to add my JavaScript after creating the PDF using PDFBox.
I want to add JavaScript to read a value from field A, calculate a new sum based on that value and write it to another field B. This calculation should take place every time the value in the input field A changes.
My problem is though, that I have no clue on how to add my JavaScript to the existing PDF file. I found this example online on how to add JavaScript, but it only shows how to register an Action to the opening event of the PDF. This doesn't help since I want to add calculations as described in the Acrobat JS Developer Guide under Calculation script.
I guess I have to modify the Documents PDAcroForm somehow. There is even a getScriptingHandler()-Method, which seems promising, it's null on my document. My code to add the JavaScript looks like this sofar:
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();
}
>>Update<<
Thanks to your input I have managed to achieve my goal of calculating new values. My Java code now looks like this:
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();
}
And my JavaScript code looks like this:
calculateValue("fieldA", "fieldB");
function calculateValue(sourceFieldName, targetFieldName) {
this.getField(sourceFieldName).value = Math.floor(this.getField(targetFieldName).value / 2 - 5)
}
This works, although I stumbled on some weird behaviour, maybe I'm just misunderstanding the change event. With this code, even though I only added "fieldA" to the recalculation order, it seems that any change in any field triggers the event. What I actually wanted to achieve was, that only the change in a specific field triggers a recalculation of another specific field. Is this how the recalculation is supposed to work?
>>Update2<<
Ok never mind, I just made mistake and updated both fields on every recalculation event...after adjusting my JavaScript, everything works now as intended.
Just one more question, how do I add a JavaScript function globally to the document to then call it on field events?
Thanks for the help!
