Friday, May 25, 2007

Flex components to PDF

Printing Flex components or converting them to PDF is very easy. Here is a sample code which shows how to print a column chart. If you want to generate a PDF you need to have ADOBE PDF printer driver installed on the machine. In the print dialog instead choosing a printer you can choose ADOBE PDF printer listed and you get a PDF as output. Sunil has more info about printing charts with data tips here. More about Flex Printing can be found here too. ChartToPDF.mxml

19 comments:

Neha said...

Using FlexPrintJobScaleType.MATCH_WIDTH prints the chart fine. The chart also fits the page correctly width wise. But the height is too small. What do I need to do if I want to print the chart so that it also covers the whole page in height vertically? Please advise.

Sreenivas said...

In my testing I am finding the height to be correct maintaining the aspect ratio.

Play around with other values of FlexPrintJobScaleType and see if you can get what you want.

Neha said...
This comment has been removed by the author.
Neha said...

Yes it does maintain the aspect ration. But the requirement I have is to print it so that it cover the whole page. Currently it prints fine but 75% of the page is blank height wise. But width wise it fits the page. I have tried all options for FlexPrintJobScaleType. But does not solve my problem.

Sreenivas said...

Try this:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">

<mx:Script>
<![CDATA[
import mx.printing.FlexPrintJobScaleType;
import mx.printing.FlexPrintJob;

private function printChart():void
{
var fpj:FlexPrintJob = new FlexPrintJob();
if (fpj.start())
{
ChartContainer.width = fpj.pageWidth;
ChartContainer.height = fpj.pageHeight;
fpj.addObject(ChartContainer,FlexPrintJobScaleType.NONE);
fpj.send();
}
}

private var chartData:Array = [

{ bugCount:20, date:"05/20/07" },
{ bugCount:14, date:"05/21/07" },
{ bugCount:17, date:"05/22/07" },
{ bugCount:10, date:"05/23/07" },
{ bugCount:2, date:"05/24/07" }
];

]]>

</mx:Script>

<mx:Button label="Print" click="printChart()" x="174" y="399"/>

<mx:Canvas id="ChartContainer" backgroundColor="white" width="100%" height="100%">

<mx:ColumnChart id="myChart" x="31" y="10" width="100%" height="100%" dataProvider="{chartData}">

<mx:series>
<mx:ColumnSeries yField="bugCount" />
</mx:series>

<mx:horizontalAxis>
<mx:CategoryAxis categoryField="date" />
</mx:horizontalAxis>

</mx:ColumnChart>

</mx:Canvas>


</mx:Application>

Neha said...

May be I need scale the chart according to the print area. But how do I do that. Any help would really be appretiated. thanks in advance.

Neha said...

I tried the code that you gave. But that does not work. It prints only half of the graph. Also, after clicking on Print Button and selecting the printer from the dialogue, it resizes the graph on the screen to a smaller size and user is able to see the change in the size of the graph, which is not good. Any other ideas? Thanks.

Neha said...

Any updates on this one?

Thanks

Sreenivas said...

I don't see any half printing. The chart is getting printed completely as expected.

And I was hoping that you would figure out the logic yourself for the problems you have mentioned!

Either save and restore the current width/height of the chart in temp variables or just for printing create a chart (including its parent container etc etc)populate it with whatever data you want and print it. And discard whatever was created.

Neha said...

The current height and width of the graph is know so not a problem for that.

But when the height and width changes it is visible to the user. Even thought it is restored, the change is visible for a small amount of time, which does not seem to be good.

Thanks for your help. Will try out the other option.

Neha said...

The reason why it was just printing a part of the graph is because, it seems the resizing used to take some time. Hence, the chart wasn't resized when it went to the printer. Even though the size of the chart was changed before fpj.addObject(), as in your example. May be because the canvas is the container which is being resized and it has two charts and couple of text boxes. I got around the problem by adding an event hadler for resize on canvas. When this occurs I do a addObject and send. So, printing works fine now.

But the problem now I have is the canvas is inside a Vbox. Canvas height is 80% of the Vbox height. Hence, once I reset the size of canvas after fpj.send() it always maintains that fixed size and does not resize. So the issue is how do I specify the height and width of canvas as percent of vbox after fpj.send(). When specifying in the function it just accepts a number. Is there any property I can set after this or any other way ? Thanks in advance.

Neha said...

Got it, using percentHeight & percentWidth properties on canvas solves the problem.

Thanks.

Neha said...

Using only percentHeight & percentWidth properties, introduces the problem of the user being able to see the chage in the size of the graph to the size of the flexprintjob page and then again the original size.

But if I set the width and height properties first and then set precentHeight & percentWidth properties immediatedly, solves both the problems. Hence, user is not able to see the change in size of graph as well as the resize works fine. Hence, I have to use width, height, percentWidht and percentHeight properties all together.

Any other option to this?

Neha said...

Sorry one more question. Is there any event handler for Print. Currently I have implemented it on the click of a button. But I would like to get rid of the button and just use the default Print option which appears on the right click. Is there any such event handler?
Many Thanks.

Sreenivas said...

I don't think there is any event which gets fired for the "Print" option. You need to use some ui mechanism to start the Flex print job.

Regarding width/percentWidth I have not played around much with printing so cannot comment on this.

Neha said...

Thanks.

Harutyun said...

I got around the problem by adding an event handler for resize on canvas.

Can you explain how did you do this(in code) please.This will help me a lot and I will be very grateful:)

Harutyun said...

please reply on this quick!!

Victoryperfect said...

Looks like these are amazing.
Canvas Print