[Looking for Charlie's main web site?]

Did you know you can store CFDOCUMENT and CFREPORT output in a variable?

Note: This blog post is from 2007. Some content may be outdated--though not necessarily. Same with links and subsequent comments from myself or others. Corrections are welcome, in the comments. And I may revise the content as necessary.
This may not be news to some, but it was to me. I just noticed that the CF7 tag, CFDOCUMENT (as well as the new form of CFREPORT), has an available NAME attribute. This allows you to save the resulting PDF or FlashPaper (or Excel, in the case of CFREPORT) output (in binary form) to a variable.

Some may know the available FileName attribute, which allows you to save the output to a file. This NAME attribute is simply an interesting alternative.

Here's a quick example:

<cfdocument format="PDF" name="test">
test
</cfdocument>

This creates a variable named test. How would you output it? CFCONTENT, of course, with the appropriate content type. If your page has created any other output, don't forget the Reset attribute as well:

<cfcontent variable="#test#" type="application/pdf" reset="Yes">

To output a Flashpaper format report, use a CFCONTENT type of "application/x-shockwave-flash", and for a CFREPORT Excel spreadsheet, use a CFCONTENT type of "application/vnd.ms-excel".

Why might you do this?

Of course, if you just did that above, you might as well not have bothered, right? The point is that you may do something between when you create the variable and when you output it. For one thing, you may create it in one CFC, custom tag, or CFFUNCTION-based UDF and then output it later in the request.

More likely, you may choose this approach to facilitate caching and later reusing the generated output. Just as with creating a variable with any tag, you could have instead provided a prefix scope like session, application, or server. Then you could manage that cached result any of the many ways that have long existed for caching other tag results in shared scope variables.

Comments
Yup. You can do this with CFCHART too (for the same reasons you mentioned).
Didn't know that. Super cool, thanks.
it's just a single variant (generic object) variable, yes? just looking at what possibilities there might be for pre-output processing.
# Posted By barry.b | 1/14/07 6:11 PM
Thanks, Todd, and happy to help, John.

Barry, I'm not clear about your question. I did mention that the variable holds the data in a binary form (it returns true if passed to IsBinary() and you can see it in a a CFDUMP as well). So as for pre-processing, I'd say there's not much chance. Maybe someone else knows better.
# Posted By Charlie Arehart | 1/14/07 8:37 PM
That is very handy. I'll have to try that out when we move to BD 7.
# Posted By Rudi Shumpert | 1/15/07 3:42 PM
Rudy, I don't know if BD 7 supports the NAME attribute. On your asking, I tried a test (am running BD 7 beta 2 on BD.NET--the version with CFDOCUMENT support) but I don't get a PDF using the example above. The page just hangs waiting for a response, it appears. If the feature interests you, I'd recommend you report it to them as a bug. (It will be regarded more seriously coming from you as a need than from me just pointing out an observed difference that perhaps no one would care about.)
Thanks for testing that out Charlie. I'll put in a report about this to New Atlanta.
# Posted By Rudi Shumpert | 1/16/07 6:56 AM
When trying to output to MS Excel I get an error. What should the format attribute of the cfdocument tag be set to?
# Posted By Andrew | 1/17/07 9:27 AM
Andrew, please reread the blog entry. In both places I mentioned Excel, I said that it was for CFREPORT only.
Not to sidetrack the blog, but for excel I use a combination of <cfsavecontent> & <cffile>. In fact use a template that lets me export reports to word or excel by passing in the extension I want to use along with the other variables I need for the specific report.
# Posted By Rudi Shumpert | 1/17/07 9:45 AM
"Why might you do this?"
Another reason to do this worthy of mention is that if all you want to do is generate and return a PDF, you can do so without resorting to file i/o.

I use this with a particular report I generate for external users. I could potentially have to persist 50,000 PDFs / year for customers. It was much simpler to code the app just to generate the PDF on the fly and email it as an attachment (and leave storage up to the user).
Sure, Jon. That's what I meant by the point I made under 'why might you do this?" where I said, "More likely, you may choose this approach to facilitate caching and later reusing the generated output". You're right, though, that it can be a great benefit.
# Posted By Charlie Arehart | 1/23/07 3:29 PM
For those reading this who may want to send the resulting variable result (from CFDOCUMENT/CFREPORT/CFCHART) in an email, you'll learn that CFMAIL doesn't support it. It requires that any attachment be written to disk first. I've asked around and it just doesn't appear that CFMAIL can or will be made to permit this.

Here's good news though. Dan Switzer, of QForms fame, has written a blog entry (in response to my pointing the problem out on another list), showing how to do it using the Javamail API (but all in CFML), so enjoy:

http://blog.pengowor...
# Posted By Charlie Arehart | 2/8/07 4:36 PM
I have just finished getting this to work. You can, in fact, send the report out as an attachment to cfmail. You just have to write your own headers. If you are using CFMX, you will need to include this inside a <cfmailpart> (because cfmail no longer supports explicity type=multitype).

Here's the code assuming your <cfreport> data is stored in a variable called "reportOutput":

<cfmail to="#Attributes.strEmailTo#" from="#Attributes.strEmailFrom#" subject="Your Event Pass">
   <cfmailpart type="multipart/mixed; boundary=#CHR(34)##variables.boundary##CHR(34)#">
This is a multi-part message in MIME format.

--#boundary#
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

Your PDF is attached. To get the latest PDF viewer, visit http://www.adobe.com...

--#boundary#
Content-Type: application/pdf
Content-Disposition: attachment; filename=eventpass.pdf
Content-Transfer-Encoding: Base64

#BinaryEncode(reportOutput, "Base64")#

--#boundary#--
   </cfmailpart>
   <cfmailpart type="application/x-unsupported">
   This should not be rendered by a mail user agent because it does not support the MIME-type.
   </cfmailpart>
</cfmail>
Very nice, Jon. One thing that may trip up readers is that you use a variable called boundary, without explaining to folks what it is. I did some searching and found an explanation of it that suggests it can be any string (so folks can either create such a variable or modify the 4 places it's used within ).

But I'm guessing you must have had a reason to make it a variable. Can you explain what you're thinking is? BTW, after you answer, I am going to move this out to a new blog entry. I think it's too important for folks to miss (as many, even Adobe folks, have said "it can't be done"). Of course, I will credit you for the code.
Gasp! I missed a critical line in mycopy-n-paste. The following should precede the listing I posted earlier:
<cfset variables.boundary = CreateUUID()>
Jon you're a star!

How did you get to the bottom of this!

You've made me a hero at work today but I *have* credited you :-)

@Charile - Any progress on that new blog entry?
# Posted By dickbob | 3/30/07 8:10 AM
This is excellent news, however I'm having a problem with Outlook receiving these emails.

If I create a pdf on the fly & use the above method to send it to a list of email address' I've noticed that Outlook receives a message with a .dat file attached, whereas my gmail account receives everything exactly as I expected. This happens on 2 seperate POP accounts, one using Outlook 2003 Pro & one with Outlook 2007 Enterprise.

Any ideas?
# Posted By Steff Mills | 4/24/07 8:22 AM
Ooops.

No sooner did I post a comment than I realised my error. I had simply mis-typed a couple of lines. The first 2x "--#boundary#" lines I had coded as "--#boundary#--". My mistake.

This works a treat. Thank you, I can't recommend it enough.
# Posted By Steff Mills | 4/24/07 8:52 AM
Excellent write-up ...! As I'm a CFNewb though I'm trying to implement the same solution but I need to attach a dynamically generated XLS and I'm stuck.

Right now I'm using CFHEADER to create the XLS. How can I attach the XLS using your method Jon?
# Posted By mikeagimp | 5/6/07 10:43 PM
Hi, nice one! Anyone got an idea how to save it to a file? This would round up this useful page! Thanks a lot!
# Posted By Manu | 10/5/07 7:58 AM
Manu, I mention in the start of the 2nd paragraph that both CFDOCUMENT and CFREPORT offer a FileName attribute for writing to a file. This NAME attribute is for when you don't want to do that.

I'll add that since writing this, CF8 has come out and one of its many hidden gems is that CFDOCUMENT now offers a SaveAsName attribute, permitting you to provide a name for a file to be saved as if you do show it to the user and they may use File>Save As.
I've blogged the technique Jon Wolski shows above with a full working example that also shows how you can embed images into an HTML document:

http://blog.pengowor...

My code shows using the CFDOCUMENT and CFCHART tags to generate in-memory binary data and then sending an e-mail without ever writing the binary data to disk.
Thanks for taking care of that, Dan. :-)
Great tip! Is there a way to generate an MS Word or RTF file using a similar technique? I know CFDocument only supports FlashPaper and PDF (as of CF8).

TIA
# Posted By Jose | 8/4/08 12:18 PM
Nope, sorry Jose. CFDocument still does not (as of 8.01) support creation of RTF or Word documents. The only built-in feature that does is the Report Builder (and CFREPORT using it). Not quite as straightforward as CFDOCUMENT, but not worth dismissing entirely as many do. You should check that out.

(If any would ask, "but what about spreadsheets?", I'd point them to a resource I created:http://carehart.org/...)
if a run two reports and they store in a differents variables, is there any way to join these two reports and show them in one file?

Can anyone give me an idea how to do this.

Thanks.
# Posted By Monik | 8/15/08 10:36 AM
Monik, if you're running CF8, this would be something you could do with the new CFPDF and CFPDFPARAM tags (merging two PDFs into one). Turns out it's not as easy as it could be. I'll do a new blog entry on it in a moment.

If it's that you're on 7 and can't use CFPDF anyway, I don't know of a good answer for you. I suppose someone may know a way to hack the underlying itext libraries that are in fact embedded within CF7 also (for some of what CFDOCUMENT does, and perhaps other tags/functions.)
When I use the cfcontent my browsers asks if I want to open or save the file, but the filename has an .cfm extension instead of a .pdf extension. I have tried saveasname, mimetype but nothing seems to work, it still puts the .cfm extension to the file. The content however is fine because when I save it with extension .pdf and open it it's fine. Any idea's?
# Posted By Mike Baak | 9/25/08 3:26 PM
Mike, the SaveAsName attribute works only with CFDOCUMENT, the subject of this entry. CFCONTENT, which is one way to send a PDF file (or variable) to the browsers, does not support that attribute.

Instead, your answer is in the docs on CFCONTENT, such as at http://livedocs.adob... See the discussion there under "usage" about using the CFHEADER tag (which should be specified BEFORE the CFCONTENT.)
Hello,

how can I convert pdf to excel?

thanks,

David
# Posted By David | 9/30/08 11:22 AM
David, I'm afraid that really has nothing to do with the entry here (ok, it's about PDFs, and so is yours, but it's a stretch).

I just don't think it's in anyone's interest to let comments on a blog entry go off on a real tangent. Instead, I'd point you to other places where you can ask and get answers to questions. See my list of CF-based forums and mailing lists at http://www.cf411.com...

I'll also point out that I also have a pretty substantial list of nearly a dozen different ways to do CF/Excel integration, at http://www.cf411.com... Still, I don't know if any of them really focus on PDF to Excel. That's quite a curious leap. Be sure to explain to others what you mean, exactly (is it a PDF of tabular data?) when you bring your question to the other resources suggested. Also, do you mean to ask how to do it from CF, necessarily? That's not obvious from your question.

But again, please do not offer those clarifications here. It's just not germane to the topic of the entry. Sorry to have to play traffic cop. Just trying to help you when you present the question elsewhere.

Hope the resources offered may help.
The CFHEADER did the trick thanx a lot!
# Posted By Mike Baak | 9/30/08 11:40 AM
Great to hear, Mike. Thanks for the update.
This might help someone.. I had 2 issues with PDF attachments using cfdocument.

1. Filesize was way too large for some reason.
2. Some .PDF files were being sent as .DAT.(only some people see it as .DAT and some see as PDF)

My resolution after breaking my head searching thru so many forums was:

1. There is an option in Coldfusion 8 cfdocument tag called fontembed. It is set to yes by default, and increases file size greatly. Use fontembed = "no".

2. Check the file name of the PDF. If it has blank or special characters, it will cause this behavior. Use Coldfusion rereplace and replace functions to change the filename to something that doesnt have spaces or special characters. Viola! It worked for me!
# Posted By MJ | 12/26/08 3:50 PM
Copyright ©2024 Charlie Arehart
Carehart Logo
BlogCFC was created by Raymond Camden. This blog is running version 5.005.
(Want to validate the html in this page?)

Managed Hosting Services provided by
Managed Dedicated Hosting