Tuesday, January 29, 2008

Submit PDF Form as HTML with ColdFusion - Part 1

I saw an interesting question on Raymond Camden's blog about adding a button to a PDF form with ColdFusion 8. I do not know if the asker was looking for a simple email hyperlink or a full fledged button. But the question got me to thinking about other things like: How do you add a button to a PDF form that will submit the form as HTML to a ColdFusion page?

It was not as difficult as I thought. Part of the process is covered in the iText API. The critical part was constructing the ColdFusion page to return a response that Adobe Reader can understand. Otherwise, the cfm script would successfully process the form information, but the end user would not know that. They would see only a cryptic message like "Cannot handle content type: text/html".

Creating the new form

Adding a button to my form, was simple. I used a PdfReader object to read in my source PDF, and PdfStamper to create a copy of the form. Then I created a new button and added a button action. The action is like a javascript onClick event. So when the button is clicked, the pdf form information will be submitted to the given URL as an HTML form.


<cfscript>
PdfAction = createObject("java", "com.lowagie.text.pdf.PdfAction");
buttonAction = PdfAction.createSubmitForm( javacast("string", submitFormDataToURL),
javacast("null", ""),
PdfAction.SUBMIT_HTML_FORMAT
);
</cfscript>
...


That is all there was to adding the form button. When you run the code below, it will create a new PDF file, with a submit button. In Part 2 I will show the ColdFusion code I used to process the form information and save it to a database table.

What you will need to run this example

  1. This example requires ColdFusion 8. It should also run under MX7 if you are using a newer version of iText


  2. A sample PDF Form. Download SimpleRegistrationForm.pdf from the iText site. Place it in the same web directory as your cfm script


  3. By default, the sample code will submit the form to the URL http://localhost/receivePDFForm.cfm. Just replace this value with the URL of the page you will use to process the form fields. For now it can be an empty .cfm script. I will show the ColdFusion code for this page in Part 2


Complete Code

<h1>Submit form as HTML example</h1>

<cfscript>
savedErrorMessage = "";

submitFormDataToURL = "http://localhost/receivePDFForm.cfm";
fullPathToInputFile = ExpandPath("SimpleRegistrationForm.pdf");
fullPathToOutputFile = ExpandPath("SendFormAsHTML.pdf");

try {
// step 1: read in the source pdf
reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( fullPathToInputFile );
// step 2: create an output stream for the destination file
outStream = createObject("java", "java.io.FileOutputStream").init( fullPathToOutputFile );
// step 3: open a stamper for generating the new pdf file
stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( reader, outStream );

// step 4: set the button dimensions
Rectangle = createObject("java", "com.lowagie.text.Rectangle");
buttonDimen = Rectangle.init( javacast("float", 200),
javacast("float", 600),
javacast("float", 300),
javacast("float", 650)
);

// step 5: create a pushbutton field
PushbuttonField = createObject("java", "com.lowagie.text.pdf.PushbuttonField");
newButton = PushbuttonField.init( stamper.getWriter(), buttonDimen, "sendButton" );
newButton.setText(" Send Form ");
newButton.setOptions( PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT );
Color = createObject("java", "java.awt.Color");
newButton.setBackgroundColor( Color.LIGHT_GRAY );

// step 6: create an action that will submit the form data
PdfAction = createObject("java", "com.lowagie.text.pdf.PdfAction");
buttonAction = PdfAction.createSubmitForm( javacast("string", submitFormDataToURL),
javacast("null", ""),
PdfAction.SUBMIT_HTML_FORMAT
);

// step 7: add the action to the button, and add the button to the pdf
field = newButton.getField();
field.setAction( buttonAction );
stamper.addAnnotation( field , javacast("int", 1) );

WriteOutput("Done!");
}
catch (java.language.Exception de) {
savedErrorMessage = de;
}

// step 8: close pdf objects
if (IsDefined("stamper")) {
stamper.close();
}
if (IsDefined("outStream")) {
outStream.close();
}
</cfscript>

<!--- show any errors --->
<cfif len(savedErrorMessage) gt 0>
Error - unable to create document(s)
<cfdump var="#savedErrorMessage#">
</cfif>

5 comments:

Brook July 26, 2009 at 6:48 PM  

This is very cool. Do you know how I would position the button on the page? Button Right Corner? How would I put the same button on each page if there were multiple pages?

I have been trying things out, but am having trouble converting the itext example JAVA code to the CF syntax. Maybe an article on the key differences and how to read/translate the itext examples would be extremely helpful!!

Looks like you are the master at this stuff though!

cfSearching July 27, 2009 at 2:50 AM  

@Brook,

You can change the button position by changing the Rectangle values used in step 4. The four (4) values you pass into the Rectangle determine both the button dimensions and the button position:

llx - lower left x
lly - lower left y
urx - upper right x
ury - upper right y

If you are not familiar with the iText coordinate system, I would highly recommend reading the faq's on coordinates and measurements. It requires a bit of adjustment in thinking at first ;)

iText-Measurements
iText-coordinates

Adding multiple buttons is not really that different than creating a single one. Just create a new instance and add it the writer/stamper.

-Leigh

cfSearching July 27, 2009 at 5:45 AM  

@Brook,

I threw together a quick example.

BTW, I like the idea of an entry on deconstructing an iText example and porting it to ColdFusion.

-Leigh

Anthony June 2, 2010 at 10:12 AM  

I tried the example, seems to be just what I am looking for. Alas, the link to the PDF you gave is blank, so I tried it with my own PDF form. It ran fine and threw no errors, even generated the output PDF. But in the output PDF there arent any buttons that were created. Any ideas? I'm trying to work on this problem:

http://stackoverflow.com/questions/2959810/saving-the-modified-contents-of-a-pdf

cfSearching June 2, 2010 at 2:25 PM  

@Anthony,

Yes, the example and links are really old. When version 5.x came out, I think they got rid of some of the older sites and examples.

First, have you asked the creator of the form? I say this because a lot depends on what type of form you are using: AcroForm (like the example) or LiveCycle. LiveCycle forms have a completely different structure. So a lot of what applies to AcroForms, does not even apply to LiveCycle forms.

-Leigh

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep