After reviewing the article I wrote for the last edition about Crystal Reports, I found that I left some very important (and not well documented) topic untouched. I know that there are much more to cover but my goal is not to replace the books out there but only to give you tricks that may not be in those books!
This month demo application
This month, I will take last month demo and add new features to it. I will not explain what was in the previous article. I strongly suggest that you have a quick read if the reading is not fresh to your mind. Please refer to it for sections that may be unclear to you.
Exporting a report
The first feature I want to talk about is the one that let you export your report that you can preview at this point. Sure the user can select the “Export report” button (the first one from the left of the toolbar of the Crystal Reports viewer but there are time when you want to do it programmatically. It is almost identical to preview a report. Only the last step varies.
There are a couple different methods that export a report but the one you will surely rely the most on is the ExportToDisk method. As shown in figure 1, many formats are supported. This method only has 2 arguments: the format and the filename.
Figure 1: Available export formats
Notice that the report does not have to be shown or previewed in order to export it using the ExportToDisk method. The reason is that the method is a member of a ReportDocument object (and not of the CrystalReportViewer object).
The complete code to export is, again, the same as when you want to preview a report. The only thing that is modified is the last line where we actually export the report (instead of passing it to the viewer):
'Load the standalone report
mrptDoc.Load(Forms.Application.StartupPath & "\rptTest.rpt")
'Pass the dataset to the report
mrptDoc.SetDataSource(mdsData)
'Set values of some objects dynamically
ApplyTextObject("txtTitle", "Demo for the Level Extreme .Net magazine")
'Set the values of the parameters
mrptDoc.SetParameterValue("PopulationThreshold", 5000000)
'Export the Report Document object to a PDF file
mrptDoc.ExportToDisk( _
CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, _
Forms.Application.StartupPath & "\rptTest.PDF")
Feeding a custom chart
Another topic I forgot to mention last month is how to send images or charts you have on the screen to the report. I use this feature because I mainly use ChartFX to chart data which I prefer over the charting features of Crystal Reports (and that user’s can customize and send the customization to the report).
The trick is to create an array of bytes from your image and add it to the dataset you are sending to Crystal Reports. Easier said then done!
The first thing you need to do is to add field (I named it Chart) to the Countries table of your schema (DemoSchema.xsd) of the Reports project and set the DataType property to System.Byte() and be very careful here as you will find only the data type without the parenthesis. You will need to add them manually. Notice that we could also have used our Create Schema feature shown last month (after having modified the data source) but I wanted to show you another way of modifying the schema.
In order to be able to see your new field on the report, you will need to update your reports references. This is done by using Crystal Reports -> Database -> Verify Database option (see figure 2). After you did that, your new field (Chart is available for you to place it on your report (since I placed it in the Countries table, I have added the Chart field to group header).
Figure 2: Updating your report schema
We now need to give a value to this new field in our dataset before passing the dataset to the ReportDocument object. For the sake of simplicity, I have added 2 PictureBox to my form (one containing a US flag and the other one containing a US flag because I only have these 2 countries in my demo table).
dt.Columns.Add("Chart", GetType(Byte()))
Now, in the CreateDataSet method, you need to add a new column to the Countries data table (we have named that column Chart). That’s the easy part. We now need to transform the bitmaps that are in the PictureBox controls (or the chart you have, or any other image source) to an array of bytes. Depending on the object you are using, the method varies a bit (for example, ChartFX can save the image into a MemoryStream). This is the code required for a bitmap in a PictureBox:
'Save the Canadian flag into a Memory Stream object
'and from there to an array of byte
ms = New IO.MemoryStream
picCdn.Image.Save(ms, picCdn.Image.RawFormat)
arrBytes = ms.GetBuffer
ms.Close()
dt.LoadDataRow(New Object() {1, "Canada", arrBytes}, True)
See the CreateDataSet method for the complete implementation of this.
Now you can test your application (and don’t forget to copy your modified rptTest.prt file to the correct folder – see last month article for more on this).
Conclusion
We can never fully cover all the features of such a bug product but I think that these 2 features where really missing from my article of last month.
I hope you appreciated the topic and see you next month.