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:
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:
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.
For more content like this from Charlie Arehart:Need more help with problems?
- Signup to get his blog posts by email:
- Follow his blog RSS feed
- View the rest of his blog posts
- View his blog posts on the Adobe CF portal
- If you may prefer direct help, rather than digging around here/elsewhere or via comments, he can help via his online consulting services
- See that page for more on how he can help a) over the web, safely and securely, b) usually very quickly, c) teaching you along the way, and d) with satisfaction guaranteed
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.
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).
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...
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>
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.
<cfset variables.boundary = CreateUUID()>
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?
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?
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.
Right now I'm using CFHEADER to create the XLS. How can I attach the XLS using your method Jon?
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.
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.
TIA
(If any would ask, "but what about spreadsheets?", I'd point them to a resource I created:http://carehart.org/...)
Can anyone give me an idea how to do this.
Thanks.
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.)
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.)
how can I convert pdf to excel?
thanks,
David
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.
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!