I recently needed to add a print capability to a Flex application to allow the user to print the results being displayed in a DataGrid control. The print out would need to span multiple pages since the number of rows displayed in the DataGrid exceeds the height of one printed page. Not having had to print a DataGrid's content before I consulted the Flex 3 documentation. The developer's guide (1,2) provides a good explanation of how to print (1) and shows an example of how to print a DataGrid that will span multiple pages (2). However, the multipage example (2) is a bit complex, has some convoluted logic (uses an endless loop) and is hard to follow since it makes use of several custom components to provide a header and footer to the printed pages. So I thought a simpler example and explanation of just printing the DataGrid on multiple pages might be beneficial.
Flex 3 provides the FlexPrintJob class to enable printing (1,3). In pseudo-code you need to do the following to print the DataGrid's contents over multiple pages.
- Create a custom component that will contain the content to print. Use the PrintDataGrid control (3) instead of the normal DataGrid control in this custom component.
- Create a button the user can click to print. Have the button's click event call a function that will contain the code to print the output.
- In the print function do the following
- Create an instance of the FlexPrintJob class (4)
- If calling the FlexPrintJob's start method returns true do the following
(note when the user clicks on OK in the print dialog window, the start method will return true, if the user clicks on cancel in the print dialog window, the start method returns false)
- Create an instance of the custom component that contains the content to print
- Add the custom component as a child of the application
- Set the height and width of the custom component to match the printed page's printable area height and width by using FlexPrintJob's pageWidth and pageHeight public properties
- Set the PrintDataGrid control's dataProvider to equal the dataProvider of the DataGrid that is being viewed. Now the content of the PrintDataGrid control that is contained by the custom component that will be printed has the same data as the DataGrid being viewed by the user. Note that when you create the PrintDataGrid control you should specify specific width's for each column that will not exceed the width of the printed page.
- The PrintDataGrid has a validNextPage property that is true or false. If this property is true, the PrintDataGrid control has more rows then are currently displayed. So if this property is true, there is another page of PrintDataGrid content to print. Wrap this property in an if statement and if it equals false (meaning the content of the PrintDataGrid can fit on just one page) then do the following
- Add the custom component to the FlexPrintJob by using the addObject method.
- Else if the validNextPage property is true (meaning the content of the PrintDataGrid spans more than one page) do the following
- Add the custom component to the FlexPrintJob by using the addObject method. This gets the first page of the custom component set for printing. Each call to addObject will setup a new page to print.
- Use a loop with the boolean expression being the validNextPage property. If validNextPage is true do the following in the loop body
- Call the PrintDataGrid's nextPage method, which causes the PrintDataGrid to load the next set of rows.
- Add the custom component to the FlexPrintJob by using the addObject method
- Note we will repeat these steps until we have added to the FlexPrintJob each page and the validNextPage property is false
- After the loop do the following
- remove from the application the custom component
- Call the FlexPrintJob's send method. Each object added to the FlexPrintJob is now sent to the printer.
If you follow the pseudo-code above while viewing the source code in my example application (5) it should be clear how each step above is executed in the code. The example application reads in an XML file, converts the XML to an XMLListCollection, and uses the XMLListCollection as the data provider for a DataGrid control. The example application has a custom component based upon a VBox control. All that is contained in the VBox control is a PrintDataGrid control. When viewing the example, just right-click on it to see the source code.
I hope the combination of the pseudo-code, the example application, and the references below will make it easier for you to understand how to print the contents of a DataGrid that spans multiple pages. The hard part for me was initially understanding the flow of instructions in the print function. Once you've mastered this simple example, you can better understand the more complex example shown in the Flex 3 Developer's Guide (2), which includes custom components to add a header and footer to each page (and even logic that controls whether or not the header and footer are displayed).
If you examine the printed output, you may notice the last row on the first printed page displays just part of the title. This seems to be caused when the title displayed in the last row spans more then one line. I'm researching how to fix this issue and will post an update once I figure it out. If you know how to fix this issue then please post a comment.