I have a PDF form with a number of text fields. The values entered in these fields are used to calculate values in other fields (the calculated fields are read-only).
When I open the form in Adobe Reader and fill in a field, the calculated fields automatically re-calculate.
However, I am using iTextSharp to fill in the fields, flatten the resulting form, then stream the flattened form back to the user over the web.
That part works just fine except the calculated fields never calculate. I'm assuming that since no user triggered events (like keydowns or focus or blur) are firing, the calculations don't occur.
Obviously, I could remove the calculations from the fillable form and do them all on the server as I am filling the fields, but I'd like the fillable form to be usable by humans as well as the server.
Does anyone know how to force the calculations?
EDIT:
I ain't feeling too much iText/iTextSharp love here...
Here are a few more details. Setting stamper.AcroFields.GenerateAppearances to true doesn't help.
I think the answer lies somewhere in the page actions, but I don't know how to trigger it...
Paulo Soares (one of the main devs of iText and current maintainer of iTextSharp) says:
iText doesn't do any effort to fix
calculated fields because most of the
times that's impossible. PdfCopyFields
has some support for it that sometimes
works and sometimes don't.
I have figured out how to do this. Please see my answer for the stackoverflow question:
How to refresh Formatting on Non-Calculated field and refresh Calculated fields in Fillable PDF form
I have updated all the calculated fields of my pdfs by calling the javascript method calculateNow on the Doc object.
According to the adobe javascript documentation this.calculateNow();
Forces computation of all calculation fields in the current document.
When a form contains many calculations, there can be a significant delay after the user inputs data into a field, even if it is not a calculation field. One strategy is to turn off calculations at some point and turn them back on later (see example).
To include the javascript call with iTextSharp :
using (PdfReader pdfReader = new PdfReader(pdfTemplate))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create)))
{
// fill f1 field and more...
AcroFields pdfFormFields = pdfStamper.AcroFields;
pdfFormFields.SetField("f1", "100");
//...
// add javascript on load event of the pdf
pdfStamper.JavaScript = "this.calculateNow();";
pdfStamper.Close();
}
On the server side, see if there is an answer in the calculated fields. If not, calculate them.
As Greg Hurlman says, you should do the calculations yourself on the server. This is for more than just convenience, there's actually a good reason for it.
Any file that the customer has, they have the potential to screw with. I don't know what the PDF forms are for, but chances are it's connected to money somehow, so the potential exists for people to cheat by making the calculations show the wrong result. If you trust the calculations done on the client side, you have no way of detecting it.
When you recieve the PDF form from the client, you should redo all calculations so that you know they're correct. Then if you also have the client's versions to compare to, you should check whether they've been screwed with.
Don't think your clients are that untrustworthy? Good for you, but the evidence disagrees. One of my earliest introductions to programming was opening up the savegames for SimCity to give myself more money. If the opportunity exists to cheat in some way, then at some point people will try it.