Saul contacted me with an interesting little problem. He was using a simple textarea form field as a way to generate PDFs. So a user could enter some text, hit a button, and generate a PDF. For example:
<cfparam name="form.text" default="">
<cfif trim(form.text) is "">
<form method="post">
<b>Text for PDF</b><br/>
<textarea cols="50" rows="10" name="text"></textarea><br/>
<input type="submit" value="Generate PDF">
<cfelse>
<cfheader name="Content-Disposition" value="inline; filename=print.pdf"><cfdocument format="pdf"><cfoutput>#form.text#</cfoutput></cfdocument>
</cfif>
This code uses a simple form that passes the field value to the cfdocument tag. Here is an example with some text typed in...

But when the PDF was generated, the text came out like so:
this is a test this is a second test and this is my last test
Not quite desirable, is it? Turns out that it was really just a simple matter. Saul forgot that CFDOCUMENT expects HTML, not plain text. If you had used the same text in a HTML page you would get the same result. I recommended Saul try the ParagraphFormat2 UDF from CFLib. It takes "plain" text and adds support for tabs and new lines automatically. Here is the modified version with the UDF included:
<cfscript>
/**
* An "enhanced" version of ParagraphFormat.
* Added replacement of tab with nonbreaking space char, idea by Mark R Andrachek.
* Rewrite and multiOS support by Nathan Dintenfas.
*
* @param string The string to format. (Required)
* @return Returns a string.
* @author Ben Forta (ben@forta.com)
* @version 3, June 26, 2002
*/
function ParagraphFormat2(str) {
//first make Windows style into Unix style
str = replace(str,chr(13)&chr(10),chr(10),"ALL");
//now make Macintosh style into Unix style
str = replace(str,chr(13),chr(10),"ALL");
//now fix tabs
str = replace(str,chr(9)," ","ALL");
//now return the text formatted in HTML
return replace(str,chr(10),"<br />","ALL");
}
</cfscript>
<cfparam name="form.text" default="">
<cfif trim(form.text) is "">
<form method="post">
<b>Text for PDF</b><br/>
<textarea cols="50" rows="10" name="text"></textarea><br/>
<input type="submit" value="Generate PDF">
<cfelse>
<cfheader name="Content-Disposition" value="inline; filename=print.pdf"><cfdocument format="pdf"><cfoutput>#paragraphFormat2(form.text)#</cfoutput></cfdocument>
</cfif>
Notice how I wrap the output of the form data with the call. This will take in the plain text and add the HTML that CFDOCUMENT will be happy with (and that's whats important - making our little CF tags happy, right?).
Archived Comments
Could you use rereplace() and '\n' as the pattern, to save to weird cases for different operating systems ?
This UDF _should_ work well cross-OS, at least as far as I know.
What if the user types in a few paragraphs of text and we need to text-align:justify it so it looks neat and tidy in the PDF? How can that be done with ColdFusion 7, 8 or 9? >:-)
No comment. :)
I'd really like to see a CFDocument and Styling article.
I ran an into a nasty bug with using font-family. It tries the first family in the list and goes no further. If you happen to not have that font installed, but you do have the second font available, you still get the wrong output.
How many other oddities are there like this with cfdocument?
Oh, and font-family names are case-sensitive (on linux at least). So that font-family: Helvetica, Arial ... example you see in every font-family example on the internet doesn't work in cfdocument. It must be helvetica, arial ....
The submitted text needs to be run through the 'HTMLEditFormat' function as well, lest HTML entered is rendered in the PDF output.