Custom Printing with Flex, Part 3: Printing Data
In the first article of this series, I discussed how to prevent users from printing directly from Flash’s default context menu. In the second article, I wrote about using the AlivePDF library to create PDFs from your application for printing or saving. Today I will be covering how to print application data from Flex.
The Flex framework comes with several classes to assist you in printing; however, they don’t tend to produce the greatest results. The PrintDataGrid class is probably your best option when it comes to printing data, but whenever I’ve worked with it in the past I’ve always ended up disappointed. Even after formatting, there are always issues; like rows getting cut off and pages breaks in weird places.
There have been talks about AlivePDF offering a Grid class to the library, which may be interesting, but it hasn’t been released and would probably only handle DataGrid data. So the best option I’ve found for printing data is to allow a server to generate a PDF, which can then be sent back to Flex and output however you want.
A great benefit of this option is the ability to easily format the print results. You can use simple HTML and CSS to customize the printout much easier than you could using ActionScript. You can also add custom styles, letterheads, and footers to fit your needs.
Here is an example, you can view the source here.
This will work with any server-side script that can generate PDF content. In this demo I am using a ColdFusion script which simply generates an HTML table and returns it in PDF format. You can view the ColdFusion code along with the rest of the source code here.
The data from the server is returned to Flex as a ByteArray. You can take that ByteArray and output it to the user in several different ways:
Using the Browser
Similar to the last article in this series, you can send the results to a server-side script to either display the PDF in the browser or prompt the user to open or save the document. This time, however, the AlivePDF library is no longer necessary since the PDF binary has already been created.
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
var urlString:String = "http://kalengibbons.com/assets/pages/pdfCreator.cfm";
if(method == "inline")
else
var sendRequest:URLRequest = new URLRequest(urlString);
sendRequest.requestHeaders.push(header);
sendRequest.method = URLRequestMethod.POST;
sendRequest.data = pdfBinary;
navigateToURL(sendRequest, "_blank");
}
Save locally from Flash
Thanks to new capabilities in Flash Player 10, you can also provide users the option to save the PDF directly from Flash. This eliminates the need for the second server-side script.
fileRef.save(pdfBinary, "yourPrintout.pdf");
}
If you plan to use the save functionality you’ll need to set the “Required Flash Player version” in your project preferences to 10.0.0 or higher or else Flex Builder will complain. You have to remember that only users with Flash Player 10 or above will be able to use this functionality, so some type of version validation is a necessity.
Another caveat is that the save method must be triggered by some type of user interaction, that’s why the sample application prompts for system access before saving. Although the user has clicked the “Print Data” button, that event is lost when the server call is made, so we need another interaction from the user.
Tags: AlivePDF, Custom Printing with Flex, series
HI, very nice project..!!, but I couldn’t get it work because i don’t have coldfusion. How can I test it with a php version of your printData.cfc. Do you have a php version..?
Thank you..
Regards..
Hi Victor,
Unfortunately, I do not know much PHP so I can’t really help you. However, I can tell you that the ColdFusion code is not doing anything that PHP can’t do.
All that’s happening in the ColdFusion script is that it’s looping through the data to create an HTML table, which is rendered by the <cfdocument format=”pdf”> tag as a PDF. That data is then rendered to Flex.
Check out the following tutorial about creating PDF documents in PHP:
http://devzone.zend.com/article/1254-PDF-Generation-Using-Only-PHP—Part-1
Good luck.
Very nice Kalen. I didn’t realize FP10 allowed you to save directly like that, that’s awesome
Thanks Kalen, you are rigth there is no problem with your ColdFusion script, but as far as I know it’s not possible to pass a complex object (arrayCollection in this case from your dbgrid dataprovider) directly to php file as you do in your CF to go throw and loop it, besides I have my php server installed and I would like to avoid installing another one (…by the way I don’t know much CF and how to setup..).
Regards…
for java solucion???????? exist?????
flex+weborb+java +objectremoting exist solucion???
Hi kalengibbon!!
Thanks for such a nice tutorial on alive pdf. I do have a problem & i need your help in solving it. I want to generate PDF from flex app & i don’t want to add any server side scripting to do the same.Now as far as i have understood flash player 10 is sufficent to solve mine problem but i am unable to do so.
var fileRef:FileReference = new FileReference();
fileRef.save(pdfBinary, “yourPrintout.pdf”);
above line always gives me error at fileRef.save (saying call is to a possibly undefined method)
i have included alivepdf.swc from this location http://alivepdf.googlecode.com/files/AlivePDF%200.1.4.8.zip
I am unable to fix this problem.Can you help me how to fix this problem & get pdf from flex app without using any server side code( i am using flex builder 3 & app is flex app & not AIR app)
thanks & regards
Saurabh
Hi Saurabh,
If Flex Builder is saying that save() is an undefined method, the likely cause is your project settings. In Flex Builder go to Project >> Properties >> Flex Compiler and make sure the “Require Flash Player version” checkbox is checked and that the value proceeding is at least 10.0.0. That should fix your problem. Good luck.
Hi Kalen,
Thanks for prompt reply. the problem was due to old version of flex sdk (i was using sdk 3.0) now i have got 3.3 & its working perfectly.
Thanks alot for such a prompt reply.
You have got really a nice tutorial for alive pdf thanks for that
Regards
Saurabh
Hi Kalen,
I am preparing an application using AlivePDF, I am giving user options to get which all screens in application user wants to be in PDF.For eg user do some playaround in UI & save a page to be added in pdf. nOw he again goes on doing some changes & again add page to desiarble pdf. Now we are having 2 pages which userwants to be added to pdf.now when he clicks on a button say generate pdf ;then o/p is pdf having required 2 pages.
Can you let me know how to proceed on same.
Regards
Montu
good ! but please tell me how to print data with AlivePDF in Adobe AIR Application ?
Here’s an example of printing from Adobe AIR, taken straight from the AlivePDF Documentation:
http://alivepdf.bytearray.org/alivepdf-asdoc/org/alivepdf/pdf/PDF.html#save%28%29
var f:FileStream = new FileStream();
file = File.desktopDirectory.resolvePath(“generate.pdf”);
f.open( file, FileMode.WRITE);
var bytes:ByteArray = myPDF.save( Method.LOCAL );
f.writeBytes(bytes);
f.close();
I generate pdf documents using microsoft reports.
is there a way to send a pdf document to printer without showing windows print dialog in Flex?
appreciate any input.
You might try using a client side reporting component in Flex. BentBit Report is great if your users need to view or print out reports. The website is http://www.bentbit.com/?goto=main/product.asp
I’m getting Property save not found on flash.net.FileReference and there is no default value error for this coding in my air application
var newfilename:string = _form.txt_rdl_name.text;
var fname:string
var refuploadfile:filereference = new filereference();
if(newfilename.length > 1)
{
var file:file = file.desktopdirectory.resolvepath(“files/” + newfilename + “.pdf”);
fname=file.nativepath;
refuploadfile.save(data,fname);
}
Hi Aarthi,
There are two common reasons why this error could be occurring. First, for regular Flex apps, there is a project property called “Require Flash Player version” which needs to be set to 10.0.0 or above, because System File Access wasn’t available before Flash Player 10. To change this setting you can go to Project >> Properties >> Flex Compiler and you’ll see three input boxes towards the bottom.
Secondly, and the more likely scenario in the case of an AIR app, the Flex SDK is outdated. If you’re using the 3.0 SDK you will encounter this problem. The current version is 3.4.0 and I suggest you download and use that; everything should work properly after you update.
http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk
i’m using 3.4 only. since its a air application i don’t have Flash Player 10 option
I’m sorry I didn’t catch this earlier, but if you’re developing an AIR application you don’t want to use the save method of the FileReference class. You should use the FileStream class to write the data to disk. You’ll need to turn your PDF into a ByteArray using AlivePDF’s save method, and then write the ByteArray to disk using the writeBytes() method. Here is an example:
var f:FileStream = new FileStream();
file = File.desktopDirectory.resolvePath(“generate.pdf”);
f.open( file, FileMode.WRITE);
var bytes:ByteArray = myPDF.save( Method.LOCAL );
f.writeBytes(bytes);
f.close();
I hope this helps. Please let me know if you still have any issues.
I’m not using Alivepdf
how to save the url without open save dialog box
how save rdl file in url as pdf file without open save dialogue box in flex
In your code you open the pdf in http://kalengibbons.com/assets/pages/pdfCreator.cfm. How do I get this to open on my server?
Hi Mike,
In the generatePDF() method, simply change the following variable to point to your server:
var urlString:String = “http://kalengibbons.com/assets/pages/pdfCreator.cfm”;
First, thanks for the quick response and your code.
I get the following error when I point to my server:
“HTTP Error 405 – The HTTP verb used to access this page is not allowed.
Internet Information Services (IIS)”
Any ideas?
Hi Mike,
I’ve never seen that before but I did some quick digging and found that the error is being caused by the setting on your IIS server. The Flex application is doing a POST to your server and it appears that your server will only allow posts from certain “verbs.” Here’s how to change this:
from Experts-Exchange
Kalen,
There is no Executable Path for the .cfm Extension. Should there be?
I’m not familiar with IIS, but basically, you just need to make it so that the application can do an HTTP POST to a URI pointing to your .cfm file.
I’m a bit late to the party but very useful, thanks
Small point but is it possible to script closing the browser with the pdfCreator.cfm page
The code is working great in my windowed program. I am having an issue if I use #NumberFormat(arguments.dataToPrint[i].phone, “999.99″)#
instead of #arguments.dataToPrint[i].phone# in the printdata.cfc. It will throw an error. Can you help please.
@Alan,
It looks like you are trying to NumberFormat() a telephone number. But a telephone number isn’t typically a valid number, it’s a string with dashes (-) or dots(.). So you can’t use the NumberFormat() method on it.
can we print all images which i’m showing in tilelist ?
Currently only visible images r printed , i want to pring all images whithout scrolling.
Hi Abhishek,
AlivePDF basically creates an image of what it sees, so if the user can’t see it – AlivePDF can’t see it – so it cannot print it. So you have two basic options:
1. You can create a “print” version of the TileList that is big enough to show all the items in the list. You can create the print TileList at runtime when it’s need to print and quickly remove it after the print it complete. This can usually happen so quickly that the user is unaware of the change. This is the same technique that is often used with the PrintDataGrid class. Check out the example at the end for more info:
http://livedocs.adobe.com/flex/3/langref/mx/printing/PrintDataGrid.html
2. You could pass the TileList’s dataProvider to a server-side script that can duplicate the layout and print it from the server.