The ability to programmatically access and manipulate PDF forms from within ColdFusion has been requested since, well, since we first demonstrated PDF generation abilities in ColdFusion MX 7. At CFUNITED a few weeks ago, Jason Delmore (ColdFusion Product Manager) demonstrated a planned ColdFusion "Scorpio" tag named <cfpdfform> which he used to populate (pre-fill) and extract values from a PDF form.
Scorpio is scheduled to be released in 2007. So what to do if you need PDF form support in ColdFusion right now? Well, here's a solution:
Adobe has a Java API named XPAAJ (which stands for XML/PDF Access API for Java). The API can be used to:
- Extract and insert PDF form field data.
- Convert PDF documents to XDP format.
- Access PDF metadata and file attachments.
- Add, replace, and delete embedded data objects, file attachments, and annotations.
- Obtain PDF file properties.
- ... and more.
Until a few days ago the XPAAJ license restricted use of the API to customers with licensed copies of LiveCycle servers. But that license has been updated to include other Adobe servers, including ColdFusion. As such, if you have a licensed copy of ColdFusion you may register and download XPAAJ and use it with ColdFusion.
Of course, using XPAAJ from within CFML code requires writing ColdFusion Java code. And so, to make life easier for us CFers, I wrote a Custom tag named <cf_pdfform> which makes it really easy to get and set PDF form field values. Want to pre-fill a PDF form? You can use this code:
<!--- PDF form --->
<cfset pdfForm=ExpandPath("Grant Application.pdf")>
<!--- Output PDF name --->
<cfset pdfResult=ExpandPath("Grant Application Filled.pdf")>
<!--- Generate filled in form --->
<cf_pdfform action="set"
form="#pdfForm#"
destination="#pdfResult#">
<cf_pdfformparam name="ProjectTitle" value="My Project">
<cf_pdfformparam name="RequestNum" value="1234567890">
<cf_pdfformparam name="RequestTitle" value="Widget Study">
</cf_pdfform>
Extracting PDF form field values is just as easy:
<!--- Output PDF name --->
<cfset pdfResult=ExpandPath("Grant Application Filled.pdf")>
<!--- Get field data --->
<cf_pdfform action="get"
form="#pdfResult#"
result="fields">
<!--- Dump it --->
<cfdump var="#fields#">
<cf_pdfform> is not as powerful or capable as Scorpio's planned <cfpdfform> tag family, but it'll help you in the interim.
To use <cf_pdfform> you must download and install XPAAJ.jar from the LiveCycle Developer Center XPAAJ page (you will need to register and accept the license before doing so). XPAAJ comes with extensive documentation and examples (none of which are actually needed to use <cf_pdfform>, although if you want to use XPAAJ to do more, this is all of the documentation you'll need). Then you'll need the attached ZIP file (see the download link below) which contains the <cf_pdfform> Custom Tag, documentation, and a CFML example.
Enjoy!
I'm wondering how this is different from using XFDF OR FDF to populate PDF forms?
XPAAJ uses XFDF internally for some forms (depends on the form type).
--- Ben
Although, the form file name is the same, PDF, the technology underneath that file format is different... For Acrobat forms, its PDF, but for forms created with LiveCycle Designer, its XDP.
Mike
--- Ben
I was wondering how the new tag stacks up performance-wise with something like IText which is what we currently use. Using this tag would be much easier for us but we do a lot of merging of PDF documents so it is very important to us that performance is equivalent and hopefully better than IText. I have a hunch it will be about the same. Thanks.
I've never used iText at that level, so can't really compare. I can tell you that XPAAJ is really fast. First request takes a moment (while Java classes are loaded and initialized) but subsequent requests fly.
--- Ben
Extend <CFDOCUMENT> please. The last thing the world needs is another CF tag!!
You've created:
<CFDOCUMENT TYPE="PDF" />
<CFDOCUMENT TYPE="FlashPaper" />
Just Use:
<CFDOCUMENT TYPE="PDF">
<CFDOCUMENTPARAM NAME="ProjectTitle" VALUE="My Project">
</CFDOCUMENT>
What about?
<CFDOCUMENT TYPE="OpenXML" />
<CFDOCUMENT TYPE="Custom" COMPONENT="components.myownone" />
Either use CFDOCUMENT (preferred) or use <CFPDF> and <CFFLASHPAPER> and lose the cfdocument tag, not both!! (since you already have <CFDOCUMENT> you may as well extend it!!
I am one of the biggest opponents of tag creep, so as a rule I agree with the sentiment. But not in this example. CFDOCUMENT is all about creating new generated content, PDF or FlashPaper for now. It has nothing to do with populating an existing form or extracting data from a form. And trying to make that existing tag do this will require too many attributes and actions and the simplicity of a tag like CFDOCUMENT will be lost. Think about it, CFDOCUMENT takes a body which is the content to be rendered, you don't need or want that for form fill in. CFDOCUMENT has tags for headers and footers which don't apply to form fill-in. CFDOCUMENT has no way to accept name=value pairs, so you'd need to add that. And there is no return value from CFDOCUMENT generation which you'd need ... So, nope, not in this case. But in many others, yes, we are very cautious when it comes to adding tags to CFML.
--- Ben
--- Ben
I am trying this out on a new development installation of CF7. I have added the jar file to wwwroot/cfide/classes folder and the wwwroot/web-inf/classes folder. I get a class not found: com.adobe.pdf.PDFFactory error.
Any ideas
Thanks
It's not going to find the JAR file automaically in that folder. Try putting it in its own folder (at least for testing) and add that path to the CLASSPATH.
--- Ben
--- Ben
It seems that I have an issue populating PDFs that contain a DataConnection to an embedded XML Schema. The PDF's I create in Designer are created with and XML Schema and fields are then bound. The SetPDFFormFields function does not work on these forms, however if I create an InputXML with the proper xml element naming instead of "Root" etc. and set the PDFData argument manually it works.
Here is a simple procedure to replicate the issue.
1. Open Designer & Create New Blank Document
2. Select Data View & Create New Data Connection Type XML Schema, browse to Purchase Order.xsd (provided in the samples installation directory of designer) and embed MXL Data.
3. Right Click DataConnection and select Generate Fields.
4. Save As Purchase Order.pdf
The resulting Purchase Order.pdf does not populate properly. Deleting the DataConnection and saving the document resolves the issue.
Although this is not an issue for me since I am actually creating the XML instead of using Form.Fields, thought you might be interested in my findings.
Allen Levine
Very nice blog. Has there been any consideration to add functionality like stamping, merging, and stitching to the CFPDF tag? Is there a way to do this using ColdFusion currently?
Those features would add tremendous flexibility when extracting data and generating new PDF docs on the fly. I'd love to be able to, without too much trouble, stitch two PDFs together - one PDF that takes in data and one that is a PDF graphical template(perfect for vector graphics) . If you want the graphics to be different, you could just stitch it with another template, rather than have to create a whole new PDF. I know of some plugins, like ActivePDF that can do this, but they run on VB or .NET... not so helpful for a Flasher who is now a CFer.
Jeff
Doc.Encrypt "", Request("Pwd"), 128
Thank you.
Matt
Any thought/ideas?
Matt
Here's the error I'm seeing:
--- ERROR BEGINS HERE ---
The system has attempted to use an undefined value, which usually indicates a programming error, either in your code or some system code.
Null Pointers are another name for undefined values.
The error occurred in D:\CFusionMX7\CustomTags\pdfform.cfm: line 37
Called from D:\CFusionMX7\CustomTags\pdfform.cfm: line 397
Called from D:\CFusionMX7\CustomTags\pdfform.cfm: line 354
Called from D:\CFusionMX7\CustomTags\pdfform.cfm: line 1
Called from \applications_forms\loan_liner_generatePDF.cfm: line 18
35 :
36 : // Perform actual import
37 : PDFdoc.importFormData(byteArrayIS);
38 :
39 : //Call the PDFDocument object's save method
--- ERROR ENDS HERE ---
I don't know if this error is indicative of *data* I'm sending in, or *fields* I'm sending in, etc. I've gone through the list of PDF form fields and am pretty sure I'm sending in all of the fields spelled correctly.
I'd appreciate any advice or help. Thank you.
Matt
--- Ben
--- Ben
The PDF was prepared with Designers and saved as a 6.x compatible format. Has anyone else run into this problem?
Can XPAAJ handle inline dynamic text replacement on a PDF or XDP? All the CF/java examples I have seen demonstrate form field replacement. I am new to LiveCycle Designer so I may be missing something.
Example:
PDF Input: Your balance as of #due_dt# is $#amt_due#.
PDF Output: Your balance as of 10/16/2006 is $1,234.56.
I can resolve dynamic text using the CF replace function on a XDP file. But then I can't figure out how to render to PDF.
Can XPAAJ convert XDP to PDF?
Preview on the Mac doesn't support this type of PDF document. I think it should work with Acrobat 6, but I may be mistaken there.
Greg:
XPAAJ cannot convert XDP to PDF, you'll need Adobe LiveCycle Forms for that. And I don't believe that dynamic text replacement is possible. You could do that with a text element and a few nicely placed text fields, but the spacing may not be perfect every time.
Mike
Ben Forta's CFMX7 web application contstruction kit book has an excellent chapter on dynamic text replacement. Chapter 33(Generating Non-HTML Content). Nate Weiss demonstrates how ColdFusion can generate and display a dynamic memo as an RTF document. I was hoping to do the same with XPAAJ and XDP/PDF.
<cfset thisFolder = getDirectoryFromPath(getCurrentTemplatePath())>
<cfset templatePath = thisFolder & "DocTemplate.rtf">
<cffile action="read" file="#templatePath#" variable="rtf">
<!--- Replace "placeholders" with specific information --->
<cfset todaysDate = dateFormat(Now(), "dddd, mmmm d, yyyy")>
<cfset rtf = replace(rtf, "%CurrentDate%", todaysDate,"ALL")>
<cfset rtf = replace(rtf, "%FreePrize%", sevPackage,"ALL")>
...
<cfheader name="Content-Disposition" value="filename=RetireMemo.doc">
<cfcontent type="application/msword"><cfoutput>#rtf#</cfoutput>
Ben, both of your ColdFusion books (CFMX7 web app and adv app dev) are amazing. I have never regretted upgrading my Allaire version 4.0 books with the latest editions. They are all well-worn.
I'm still having the same problem as before. I can't seem to clear the old pdf out of the cache. Here was my original post.
Hey guys, is there any way to force a cache delete of a pdf file out of the browser. I'm having trouble when I do a dynamic fill of a pdf, I then go back and make some changes to the data, fill that pdf again and the old data is there. If I open the pdf with the acrobat that is seperate from the browser it shows the data. It seems to be a cache problem. Any ideas?
The argument XMLDATA passed to function SetPDFFormFields() is not of type xml.
Any ideas
but I got a problem with text being truncated, for example if I try to fill the form fields with a string that contains extended characters like "Vous faites partie du Réseau Commercial" I end up with "Vous faites partie du R".
Any thought/ideas why this is happening?
Thanks
When will CF8 be in beta? Are their any books/manuals on Designer and LiveCycle products? The online help is OK, but nothing like training from the source books.
Greg, mid-2007. And there is far greater PDF integration planned.
Maxime, no idea. I am passing the strings through as is, and am not parsing them at all. But I can ask aroundd.
--- Ben
Sorry.
Regards,
--
Jon
(1) CF_PDFForm Parameter Name (i.e., PDF Field Name) can not contain "." and possibly some other characters.
(2) Don't waste time with CFREPORT. You will just consume endless hours tediously programming and beating your head against the Report Builder layout interface. Most of us just want to use existing PDFs and pass data to the fields. Consecutively numbering names of existing PDF fields is a who lot easier than creating temporary queries and wrestling with CFREPORT and Report Builder. Just loop out your query to produce CF_PDFForm parameters from list, table, array, or struct.
That is, Field.1, Field.2, and Field.3 would simply use "Field" under the property of the calculated field to SUM the three values.
Have I made another mistake? Or am I correct?
Another problem is that even after removing all the class prefixes, and passing simple variables used in a calculated column, a calculated field will not calculate unless one of the values in the calculated column is manually entered or changed. Maybe a client-side trigger could be scripted to calc the field, but web developers will not want to make every small issue like this a life’s work to solve.
As it stands, the application I spent 4 months developing will result in very primitive, much less flexible reports. Of course, I could use simple, “classless” variables throughout the entire form, and hope that Adobe Acrobat will accept long lists of comma-delimited variables in the “Calculate” properties of the field, but this would be very inefficient and time consuming. It may be possible to write a "Custom Calculate Script" to identify the field to be calculated by wildcard, but my common sense, and past experiences, tell me not to toss good money after bad by building entire system created using bizarre and clumsy work-arounds.
ColdFusionMX needs a solution for creating highly flexible on-the-fly FlashPaper/PDF forms, and some third-party needs to develop an environment for efficiently building the forms. Report Builder is a failure in this regard.
Report Builder could be used to produce very simplistic, non-interactive FlashPaper reports. Using RB with PDF to create very simple forms (the Adobe product) requires much more effort. CF_PDFForm also has some merit, but only where simplistic results are expected.
Yes, this tag is very limited. I created it not as a complete feature, but as a stop gap measure that could help some users, as well as a way to encourage users to dig further into Java APIs themselves. I am sorry if you have found limitations, just as I am sure that there are more of them yet to be found. The tag is not a complete feature, and was never intended as such.
We've already publicly stated that we're working on it. ColdFusion 'Scorpio' , the first version of ColdFusion released under the Adobe name will have the expected PDF integration and support, both PDF forms and PDF file manipulation.
--- Ben
Is it possible for CF_PDFForm to read the text of a PDF? I love how simple this is, and would rather use this, or something like it to read PDF text.
Thanks.
(1) TIP - If a field is selected in a CFRB form, and fill color palette is opened, the field will acquire a background color whether you like it or not, and there is no published method (that I can find) of clearing the background color. However, I accidentally discovered that if you reselect the field, open the fill color palette and select a color, then click the Undo icon, the background color will be cleared !!!
(2) NEW PROBLEM - Snap-to-Grid does not work in the Detail Pane.
(3) NEW PROBLEM - Cut and Paste operations do not work in the Detail Pane.
(4) NEW PROBLEM - You better save your form under a new name every minute or so, because the Undo is exceedingly buggy, and you will permanently loose your work.
(5) The list of additional bugs and glitches is too great for me to list here.
CF_PDFForm (previously identified field-naming limitation notwithstanding) seems to have much greater pdf form-building utility than CFRB.
First...thanks for all of your work in Coldfusion development.
Second...I'm a bit lost on how to overcome caching. For example: using your example, I submitted the form and the PDF reflected what I had submitted. BUT, if I hit the back button, changed some of the fields and submitted the form again I simply got what I submitted the first time. The only way I could get around this was by renaming the action.cfm page (ie. action1.cfm) and submitting to the new action page. Please tell me there is a better solution than this.
Thanks.
That worked for me.
Matt
If you are having problems with a document, try to remove or trim spaces at the end before you use XPAAJ. Unfortunately, that is not a solution for my situation since I do not control the creation of the PDFs I am working with.
Object Instantiation Exception.
Class not found: com.adobe.pdf.PDFFactory
Can anyone help me solve this issue or tell me whats wrong?
Thanks in advance@
Looking at, for example, block 9a, xexec, we've tried the following to trigger the checkbox with no success:
<cf_pdfformparam name="xexec" value="1">
<cf_pdfformparam name="xexec" value="yes">
<cf_pdfformparam name="xexec" value="checked">
<cf_pdfformparam name="xexec" value="on">
We're successful in populating the textual blocks, but we're not able to trigger the checkboxes. Can anyone offer any suggestions? Thanks.
For example, the checkbox "checked" value to indicate that this is an exec is "1_Commer1" -- which was probably a value that indicated this was a commercial versus an autovon phone line. Sheesh!
I tried running the test file – form.cfm. I received the following message.
Object Instantiation Exception.
Class not found: com.adobe.pdf.PDFFactory
The error occurred in D:\Testing WEB\pdfform.cfm: line 140
Called from D:\Testing WEB\pdfform.cfm: line 388
Called from D:\Testing WEB\pdfform.cfm: line 354
Called from D:\Testing WEB\pdfform.cfm: line 1
Called from D:\Testing WEB\action.cfm: line 27
Called from D:\Testing WEB\pdfform.cfm: line 140
Called from D:\Testing WEB\pdfform.cfm: line 388
Called from D:\Testing WEB\pdfform.cfm: line 354
Called from D:\Testing WEB\pdfform.cfm: line 1
Called from D:\Testing WEB\action.cfm: line 27
138 :
139 : // Get PDF document object
140 : PDFfactory=CreateObject("java", "com.adobe.pdf.PDFFactory");
141 : PDFdoc=PDFfactory.openDocument(formIS);
142 :
Any advice would be greatly appreciated.
Thank you.
Output is userName=jasonticketSubject=Helpticket=helpme
As there is no delimiters i can not access the info, or can i?
ctrlview,http://www.qweas.com/download/graphics/image_conve...
have a good time!
---- ERROR begins here ----
The error occurred in: D:\CFusionMC7\CustomTags\pdfform.cfm: line 140
Object Instantiation Exception
Class not found: com.adobe.pdf.PDFFactory
---- ERROR ends here ----
I just checked server and the XPAAJ.jar file is located where it has been. Can it have become disabled? The only thing I know of that has changed on that server is the installation of SQL Server 2005 and the installation of a virus scanning software.
Any ideas? Thank you.
Matt
The website is http://www.qweas.com/download/converters/pdf_conve...
Does the cf_pdfform tag cover extracting metadata from pdf files, as they are not actually form fields. If not is there a custom tag available for coldfusion to allow you to access this element of the XPAAJ jar file's functionalities.
Thanks
Paul
-- Ben
I found the pdfresponse.cfm page with the latest release of the XPAAJ.jar which will return the metadata for pdf docs. However a lot of the documents I am trying to query were created by GPL'S GhostScript and the pdfresponse tag/code will not process these. Do you know if there is a way to process these pdfs or are they not considered valid pdfs by XPAAJ.
Thanks
Paul
># Posted By Scott Casteel | 10/12/06 10:21 AM
I am seeing the same exact thing. In fact, I've noticed that you can open the dynamically generated pdf from a different machine and see the same cached content, which leads me to believe that the cache is pdf server-side.
Has no one else seen this or come across a solution?
What makes these forums powerful is when everyone gets the answer when you reply to the post.
Thanks,
<cf_pdfformparam name="myTextArea" value="#attributes.address# \n #attributes.city#, #attributes.state# #attributes.zip#">
I have tried \n and <br>. Any thoughts???
#chr(13)##chr(10)#
Thanks!
thanks, bl
However, I am having problems executing it on a Bluedragon server. It works great for me with MX7, but when I try to use it on Bluedragon it fails.
Can you help? I am getting the following error:
The function "SetPDFFormFields" was declared twice in different templates
Tag Context cf_pdfform: Line=9; Column=33
<cfargument name="PDFOutput" type="string" required="yes">
7 : <!--- XML data (form field values) --->
8 : <cfargument name="XMLData" type="xml" required="yes">
9 : <cfscript>
10: // Init all vars
Thank you for any help you can provide
1) I have never installed it used BlueDragon, so can't comment on why this is not working. I wrote it for CF, and it works on CF6,7, and even 8 (although unnecessary on 8).
2) Actually, using the XPAAJ.jar file with BlueDragon likely constitutes a license violation. That library is licensed for use with Adobe servers, including Live Cycle and ColdFusion.
3) That tag was s stop gap measure, the real functionality is in CF8 which is now in beta.
--- Ben
I thought you might tell me it had not been tried on Bluedragon. I know the client I am working for has Adobe Acrobat 8 which comes with some of the LIveCycle tools, but I doubt it comes with the server. I never looked in to it.
Given that my hands are tied to working with Bluedragon and Acrobat 8, I wonder if I will have to resort to FDF approach. And now that I have tried and love your tag, going to the FDF will be a pain!
--- Ben
now i need to suppress blank lines. my pdf is a business card template. (see chicago.jpg for example)
on the left top down
firstname middlename lastname
job title
address1
address2
address3
www.whatever.com
on the right bottom up:
phone:
fax:
mobile:
email:
aim:
this is where I'm stuck: if a user does not enter a fax number... I want the PDF preview to move 'phone:' down 1 line and not show the word 'fax'.
I did notice today that sometimes the data in the pdf doesn't change it stays the same of the prior entry.
This can be done, but not using this tag. I think you'll need to do some scripting in the PDF itself, you can write scripts that change/move/hide/show content based on other values. If the PDF itself is set up to work that way, then it'll do what you want when you use this tag (or <CFPDFFORM> in CF8) to set form field values.
--- Ben
> Class not found: com.adobe.pdf.PDFFactory
The CF server does need to be rebooted after you drop the JAR file into the correct directory, otherwise CF won't see it.
> The argument XMLDATA passed to function SetPDFFormFields() is not of type xml.
It seems that changing all the type="xml" to type="string" worked fine in CF6.1. The only other thing I needed to change was to remove the checks for whether variable names were valid (isValid).
Now everything seems to be working fine. Thanks so much!
So I know some software that can help you to convert your music formats to the formats you want, you can find your wanted Audio & MP3 Software in http://www.qweas.com/popular/popular-1.htm
Enjoy yourself!
I'm trying to get my ISP to download XPAAJ, but they maintain that it is not free and they won't pay for it ($1495). However, my understanding was that if you already own a license for CF (CFMX 7, in this case), you can register and use. Is that the case? (I hope so as I already wrote the app and my boss wants it up and running ASAP!)
Please advise,
Christian
--- Ben
I tried to download the XPAAJ.jar from the LiveCycle page, however I ran into "Because we are now offering the entire LiveCycle ES suite in a trial version, XPAAJ is no longer available.". Any ideas from here?
ive set the fields to be bound to their corresponding xml node, and im sending the data as a post variable, along with a couple other variables, but the form doesnt display the data. i can confirm that it does come through in the post, but no binding is occuring... shoudl i delete the databinding in the livecycle form?
im royally stuck.
"Object Instantiation Exception. An exception occurred when instantiating a Java object. The class must not be an interface or an abstract class. Error: ''."
Any ideas on what can be causing this? I have the XPAAJ.jar file in "Jrun4\servers\branch\cfusion.ear\cfusion.war\WEB-INF\lib"
Any help would be much appreciated.
># Posted By Scott Casteel | 10/12/06 10:21 AM
I am seeing the same exact thing. In fact, I've noticed that you can open the dynamically generated pdf from a different machine and see the same cached content, which leads me to believe that the cache is pdf server-side.
Has no one else seen this or come across a solution?
# Posted By Art | 3/6/07 11:20 AM
The problem still exists for me in Coldfusion MX 7. Does anyone know if this was resolved with 'Scorpio - Coldfusion 8', or if there was a solution to this problem?
I seem to have lost my XPAAJ.jar file and am needing it to run some old production code. Can someone please email that file to webmaster AT gomotorbids.com ? I would be grateful.
Thanks,
Josen
Did you just upgrade to CF8? If you did, that knocks out theXPAAJ library. But that's okay because instead of it being an external, add-on, now it is built in. Instead of using <CF_PDF...> tags, use the new <CFPDF...> tags. They do work better but have slightly different syntax.
Scott
I was in almost the exact same situation. I got around it by stopping the CF8 application service, starting the CF7 application service, then restarting the CF8 service. That has to be a temporary work around, just until I can convert everything to use the new <CFPDS...> tags.
I hop this helps.
Scott.
I thank you for continuing excellence
Thank you
I try to download XPAAJ sdk. But I find only XPAAJ.jar. Without any documentation It is very hard to work with XPAAJ.Instead of XPAAJ adobe providing LiveCycle ES SDK .which needs to deploy on windows server 2003.
Can anybody provide me XPAAJ SDK ?
Any Help will be appreciated.
Thanks & Regards,
-vinayak