21
Using ColdFusion to Generate a Custom Word Document
ColdFusion, Web development
Tags: ColdFusion, Word
Share
An oldie but a goodie, ColdFusion can be used to generate Word documents. Here is a quick example of writing to and opening a Word document.
Create Word Template
Create a Word template by adding “placeholders” in the document. This is done by wrapping a keyword with % (percent) signs as such: %firstname%. Put in as many as you want and add any necessary formatting in Word. Your replacement text will pick up the formatting. Save the file as an RTF (.rtf). For simplicity sake, put it in the same directory as the CF file used to generate it. Here an RTF file called homeworkpass.rtf is used.
Collect the Data
This example uses form fields to fill the document. Data from a database could be used just as easily. It’s a pretty standard form, nothing special.
<form action="index.cfm" method="post">
<fieldset>
<legend>Homework Pass Info</legend>
<p><label for="expirydate">Expiration Date:</label><br />
<input type="text" id="expirydate" name="expirydate" value="#DateFormat(DateAdd('d',10,Now()),'mm/dd/yy')#" /></p>
<p><label for="points">Points:</label><br />
<input type="text" id="points" name="points" value="100" /></p>
<p><label for="studentname">Student Name:</label><br />
<input type="text" id="studentname" name="studentname" /></p>
<p><label for="subject">Subject:</label><br />
<input type="text" id="subject" name="subject" /></p>
<p><label for="datereceived">Date Received:</label><br />
<input type="text" id="datereceived" name="datereceived" value="#DateFormat(Now(),'mm/dd/yy')#" /></p>
</fieldset>
<fieldset>
<legend>Version of ColdFusion:</legend>
<p><label><input type="radio" id="cfversion" name="cfversion" value="pre8" />CFMX or earlier</label><br />
<label><input type="radio" id="cfversion" name="cfversion" value="post8" />CF8 or later</label></p>
</fieldset>
<p><input type="submit" name="submit" value="Generate Word" /></p>
</form>
Replace Text with ColdFusion
After a little error checking, the file is opened and the placeholders are swapped out with the form field values using the Replace() function in the homeworkpass.rtf.
<cfset error = "" />
<cfif isDefined("form.submit")>
<cfloop collection="#form#" item="i">
<cfif NOT Len(form[i]) OR (NOT isDefined("form.cfversion"))>
<cfset error = "All fields must have a value" />
</cfif>
</cfloop>
<cfif NOT Len(error)>
<cfset pathToRTF = GetDirectoryFromPath(GetCurrentTemplatePath()) & "homeworkpass.rtf" />
<cflock name="homeworkpass" type="exclusive" timeout="30">
<cfif form.cfversion EQ "pre8">
<!--- CFMX7 or earlier --->
<cffile action="read" file="#pathToRTF#" variable="rtf">
<cfelse>
<!--- CF8 or later --->
<cfset rtf = FileRead(pathToRTF) />
</cfif>
<cfset rtf = Replace(rtf,"%expirydate%",form.expirydate) />
<cfset rtf = Replace(rtf,"%points%",form.points) />
<cfset rtf = Replace(rtf,"%studentname%",form.studentname) />
<cfset rtf = Replace(rtf,"%subject%",form.subject) />
<cfset rtf = Replace(rtf,"%datereceived%",form.datereceived) />
</cflock>
<cfheader name="content-disposition" value="filename=HomeworkPass.doc" />
<cfcontent type="application/msword"><cfoutput>#rtf#</cfoutput>
<cfabort>
</cfif>
</cfif>
There is a section here to allow for ColdFusion version specification. For ColdFusion 8 the FileRead() function can be used. All other versions of CF will need to use cffile.
<cfif form.cfversion EQ "pre8">
<!--- CFMX7 or earlier --->
<cffile action="read" file="#pathToRTF#" variable="rtf">
<cfelse>
<!--- CF8 or later --->
<cfset rtf = FileRead(pathToRTF) />
</cfif>
Offering a choice for ColdFusion will not be necessary in production; it’s here for illustrative purposes only. At this time all versions of Word can open .doc files.
Output the Word File
To output the Word file use cfcontent and stop processing the rest of the page.
<cfcontent type="application/msword"><cfoutput>#rtf#</cfoutput>
<cfabort>
To create multiple Word documents in a batch-like process see the Using ColdFusion to Generate Multiple Word Documents (Batch Creation) post.
If this post helped you out, please consider donating to help pay the hosting fees. 100% of the donations go to the web host.
Further Reading:
27 Comments for Using ColdFusion to Generate a Custom Word Document
Thanks! This post really helped me out.
@Bryan
You’re welcome. Sometimes these one-off solutions are just what you need.
covayntc
July 2, 2009
Please help me to solve problems: some of the textboxes of form have unicode characters, the outputted Word file can not display exactly. How to display unicode characters in Word file?
@covayntc
Look through Word help. You may have to set the encoding on the Word document itself.
This post is very timely. Just what I was looking for. Thank you very much Jen!
)
Hi Jen,
You wouldn’t know of a simply way of modifying your code to handle multiple pages (e.g. if you wanted to produce a home work pass for all the students in a class)?
I’ve got the script working nicely to generate certificates for people who attend training courses, but I can only generate one certificate at a time at the moment.
Thank you very much for your assistance…
@Simon
Here you go. Let me know if it’s what you needed.
http://www.jensbits.com/2009/07/08/using-coldfusion-to-generate-multiple-word-documents-batch-creation/
I really like the idea of using RTF documents instead of DOCs. Great tip!
Great post, however, if the placeholder document has a placeholder fed with input text from a Rich Text Editor, the ensuing output .RTF document shows raw html tags (such as etc).
Any tip on getting this html formatting to display properly once inside of the .RTF document?
@Michael
RTFs are limited in their ability to format. And, I haven’t played around with special characters or HTML in them; I haven’t needed to. CF plays nicer with other Adobe products – imagine that – than it does with anything Microsoft.
Hi Jen,
We’ve been doing HTML to Word conversions via CF for some time now, but recently I’ve run into a snag. I need to position a logo all the way at the papers top edge. This works fine with the generated HTML, but once opened in Word the document places the image at the top of the page (within the set margins). So NOT at the top of the page paperheightwise. Am I making myself clear?
Hope you’ve run into this once before and have found a solution. Thanx up front!
I have this:
/* Include header and footer margins in page definition */
@page Section1 {
size:21.0cm 842.0pt;
margin:70.9pt 70.9pt 70.9pt 70.9pt;
mso-header-margin:0;
mso-footer-margin:.5in;
mso-header:headerImage;
mso-title-page:no;
}
div.Section1 { page:Section1; }
And then this in a cf_bodycontent tag:
And what I want is for the image to be user as a headerimage only on the first page and NOT to be displayed in the content.
<div style=”mso-element:header” id=”headerImage”>
<cfoutput><img src=”#app_images#rijkslogo_600px_breed.png” alt=”" /></cfoutput>
</div>
@Sebastiaan
I feel for you. Word is a pain in the butt when it comes to positioning graphics. I don’t know what you can do other than use a template with a header that includes the graphic on the first page. You may lose that header when it’s saved as an RTF. I wish I could help more. Good luck.
Hi,
Thank you, just found it when needed.
BTW I figured a problem in replacing rtf variables, because i needed to have some carriage returns.
After some tries with chr(13) & chr(10), i found that the RTF specifications don't use this, but use \par instead.
http://www.biblioscape.com/rtf15_spec.htm
I invite everybody to check the specs, it helps a lot.
My best
@Christian
Thanks for the tip! Writing to Word with CF is a sticky wicket as it is. Every little nuance or tidbit brought to light helps.
The problem I have found is that this only replace variables on page 1 of the document. Is there any way to fix this?
Problem is I get garbage out of my RTF files when I try to read them with CFCONTENT. Each RTF file has a .dot file in the same folder if that makes a difference.
This used to work under CF5 on a W2K server that had Office 2k on it.
Now I get garbage like this:
???>?????????????????????????????????????????????????????????????????????????????????????????????????????????????3 ?????bjbj?? 1T??? ?@???lzzzz...B?*?*?*8?+?B??????%???47?z?|?|?|?|?|?|?$? ??.S??@%?S?S?
I do a fileread and then
<cfcontent type="application/msword"> or application/rtf and get nothing but trash.
Any ideas?
@Don
So if you open the file directly, without using CFCONTENT, it's OK?
There's a big difference between CF5/Word 2K/Win2000 and what we have now. Unfortunately, Adobe didn't exactly embrace compatibility with its competitor's products. It wants you to use PDFs instead.
BTW, CF5/Word 2K/Win2000 was the same environment where I first used this. Instructions are in the CF5 WACK book.
FIRST! Your anti-spam thing drives me nuts because I always forget it the first time around. grrrr
Anyway, yes, if I just put in the path to the file it opens right up correctly.
So what I tried doing was using an iframe to grab the old CF5 template that opened the RTF file. It worked except I could not edit it. I then ran it from the link on the page that lists the documents. No go. Says it can't find the RTF file. That is strange. The link opens a new window. That window is the one that I put the iframe on originally. Maybe too many layers and permissions involved.
Anyway, know of any workarounds for this? Before I go on a massive wild google chase, do you know if I can convert them to PDF?
Convert an RTF or Word doc to PDF with CF? Not that I know of. Neither cfdocument nor cfpdf will do that. This whole method is clunky at best and may not work as Word and CF evolve. Actually, I was kinda surprised it can still be done at all.
BTW, I LOVE the anti-spam because I no longer spend an hour a day deleting links to porn.
@Gary
You may be running into a caching issue. I was able to put variables in on the second page without a problem.
What I really need I think is to be able to open the docs in WordPad. Can't find any documentation on how to instantiate and use a WordPad object tho.
Leave the porn! It makes your site more popular. lol
And I keep guessing wrong anyway.
@Don
"Leave the porn! It makes your site more popular. lol"
That actually crossed my mind…
Joe
June 28, 2010
I bet the person wanting to know how to get variables on page 2 or beyond may be using the same variable on those pages that they used on page 1. Therefore, they simply need the "All" parameter at the end of the replace() function.
However, I will tell you that there may be some sort of limitation on the number of replacements in a single document because I'm fine up to maybe 100 statements or so and then it just stops replacing. It could be a memory limitation.
@Joe
Thanks for the info. It is a kludge at best no matter how it is done. But, it can be done, like you said, with limitations.
Joe
June 29, 2010
Just a note for Michael (above). You can also simply write html to a file with a .doc extension and Word will open it and it will have the html formatting. And if you have Word on your server, you can issue a read of the file and then issue a "save as" (via COM — you'll have to good that) with an rtf extension and it will save it. (It creates an instance of Word on the server though, so you wouldn't want this to be high volume.)
Also, ActivePDF will convert from html to PDF or Word to PDF. http://www.activepdf.com/products/serverproducts/docconverter/overview.cfm
Leave a comment
« Test Drivin’ Safari 4 | Using ColdFusion to Generate Multiple Word Documents (Batch Creation) »

Bryan
June 23, 2009