For report files that exist externally to your application (for instance, as a standalone report file, created with either this or a previous version of Crystal Reports) there is not much to creating a simple preview Form for your report.
In this example, we are going to be using the viewer_basic project, which you created earlier. In the project, there should be a default Form1 that we can use. Locate the CrystalReportViewer within the toolbox and drag or draw the Report Viewer onto your Form.
Once you have added the Report Viewer to your Form, we now need to set the ReportSource property to point to the existing report file. The sample files for this chapter include a sample report (ch3_worldsales.rpt) that we can use. Using the property pages for the Crystal Report Viewer, set the ReportSource property to the location of this report file. For instance, if you have put the sample files in your own personal directory, enter the full report file name and path, (C:\CrystalReports\Chapter03\ch3_worldsales.rpt).
You can now run your application and when you preview the Form, your report will be displayed in the Crystal Reports Viewer, as shown below:
The viewer interacts with the Crystal Reports print engine, runs the report, and displays the results.
From your report preview, you can drill-down into the details, search for a value, print, and export without having to do any additional coding. If you only have one or two reports that you want to integrate into your application and you don''''t need to customize any features at run time, this may be all you need. But for applications that require a more sophisticated integration with Crystal Reports.NET, you probably need to look at a bit further.
Still working in the same solution and project as before, we are going to add a Crystal Report to our application. In the previous walk-through, we looked at referencing a report that was external to our application through setting the file path and name. While this is one method of integrating Crystal Reports, actually adding the report file itself to our project makes it easier to edit and integrate reports into our application.
To add our World Sales report to our project, select Project | Add Existing Item which will open the dialog shown below. Change the drop-down list to show All files and specify *.rpt for the file name to filter the list to show only the available reports.
Once you have selected the ch3_worldsales.rpt report, click Open and this report will be added to your project in the Solution Explorer.
As this report was added to your project, you may have noticed that in addition to the report, another file with the same name as the report (except for a .vb extension) is also added, as shown.
This file is hidden until you select Show All Files from the Solution Explorer. This additional file is the report source file and contains a report class specific to this report called ReportDocument that is created automatically for you.
Earlier in the chapter, we quickly dragged the Report Viewer onto a Form and previewed your first report - the good news is that there is not much more involved in adding the Report Viewer to a Form in your application. The Crystal Report Viewer is available from the Windows Forms Toolbox and you can drag it directly onto your Form or draw the viewer on your Form to the size required.
You can easily add the Crystal Report Viewer to an existing Form, to display a report side-by-side with other controls or you could add the report to a new Form to have a separate window for previewing reports.
If you are going to use a separate Form for previewing reports, try changing the Dock property of the Crystal Report viewer to Fill so it will fill the entire page. To change this property, right-click on the Crystal Report viewer you have dragged or drawn on your Form and select the viewer''''s properties. From the property page shown below, locate the Dock property and use the drop-down list to select the docking for this component.
Important
You can also add a margin around the docked viewer by setting the Dock Padding properties, which would add blank space around the viewer using the settings and margin you specified.
With the Report Viewer added to your Form, we now need to let the viewer know what report it will be using and this process is called binding a report to the viewer. There are four different ways to bind a report to the Crystal Report Viewer:
By report name
By report object
By binding to an untyped report
By binding to strongly-typed report
To bind a report using the report name, all you need to do is set the ReportSource property, either through the property page or through the Form''''s code. You will want to add this to the Form''''s Load method, which can be accessed by double-clicking on the Form we are working with. To set the ReportSource property, we need to specify the report file name and path, as shown here:
CrystalReportViewer1.ReportSource = "C:\\CrystalReports\ \Chapter03 \ \ch3_worldsales.rpt"
But since we have already added the report to our application, we could also bind the report by creating a report object, load the report into the object, and bind the object to the Crystal report viewer.
Binding by a report object works slightly differently depending on if you have added the report to your project or if you are referencing it externally. For a report that resides externally to your application, we need to first specify an import of the CrystalDecisions.CrystalReports.Engine, which will allow us to create the object.
In the Solution Explorer, right-click on your project (in our case, viewer_basic) and select Properties from the right-click menu to open the dialog shown below, and click on Imports in the left-hand pane.
Under the Common Properties folder, use the Imports option to add the CrystalDecisions.CrystalReports.Engine namespace to your project and click Apply and OK to return to your Form.
With this namespace imported, we now need to create the report object as a ReportDocument, by inserting it into the CrystalReportViewer1_Load event, as shown:
Private Sub CrystalReportViewer1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CrystalReportViewer1.Load Dim myReport = New CrystalDecisions.CrystalReports.Engine.ReportDocument()
With our object now ready to be used, we can now load the external report file:
myReport.Load("C:\\CrystalReports\\Chapter03\\ch3_worldsales.rpt") CrystalReportViewer1.ReportSource = myReport End Sub
If the report you are using has actually been added to your project, a class was automatically generated for the report, so we could use the class instead to bind the report to the viewer (while the import and public declaration remain the same):
Private Sub CrystalReportViewer1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CrystalReportViewer1.Load Dim myReport As CrystalDecisions.CrystalReports.Engine.ReportDocument myReport = New ch3_worldsales() CrystalReportViewer1.ReportSource = myReport End Sub
or, if you wanted to eliminate the myReport variable, replace that code with the following:
CrystalReportViewer1.ReportSource = New ch3_worldsales()
Which method you choose will depend on where the report is physically located and how you wish to access it. With any of the examples above, you should be able to bind to the report and then run your application - the Report Viewer should display a preview of your report if you are successful.
Important
If you are having trouble binding to a report object, check the report file name and path are correct or for a report that has been added to your application, check the report name.
When working with Crystal Reports.NET, you can add individual report files to your project and use and reference them to print reports from your application. Taking this a step further, you could also use these reports as components, which is where we start to look at typing.
When integrating reports into an application, we can either use strongly-typed reports or untyped reports. If you have been working with Visual Studio .NET for any length of time, you have probably heard of strongly-typed objects. A strongly-typed object is predefined with a number of attributes that are specific to that object, giving programmers more structure and a rigorous set of rules to follow, thus making coding easier and the code more consistent.
Within the frame of reference of Crystal Reports.NET, a strongly-typed report can be any report that has been added to your project. What determines the "type" of a report is how it is added and used within your application. When you first add a report to your application, it is considered untyped - the same goes for any external reports that you may reference (such as the report we pointed to earlier, using the file path C:\CrystalReports\Chapter03\ch3_worldsales.rpt).
In the example below, we are going to look at binding to an untyped report. The first step to binding to an untyped report is to add a ReportComponent to the Form we are working with.
To add a report component to your Form, switch to the Layout view of your Form and look in the toolbox under Components. In this section, you should see a component labelled ReportDocument. Drag this component onto your Form, which will open the dialog shown below:
This is the dialog that we use to set whether our report document component is typed or untyped. If you select Untyped ReportDocument, a report component named ReportDocument1 is created and we can then load a report into this component and bind the component to the viewer.
Again, the code to perform the binding will appear in your Form''''s Form1_Load method and will look something like this:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim ReportDocument1 As New ReportDocument() ReportDocument1.Load("c:\CrystalReports\Chapter03\ch3_worldsales.rpt") CrystalReportViewer1.ReportSource = ReportDocument1 End Sub
When your application is run and the Form previewed, the viewer should show a preview the report and allow you to print, export, and perform other functions.
Important
If you are experiencing problems binding, check the file name and path of the report you are working with - alternately, if you are binding to a report that exists within your application, check that you have the correct report name.
Finally, if you have added a report to your project and then added a ReportDocument component, you can choose to add the report as a strongly-typed report component, which probably has the simplest binding method of all. To create a strongly-typed report document component, drag the ReportDocument component onto your Form.
You will then see the same dialog as before, with a drop-down list of all of the available reports that you have added to your project. Select the existing viewer_basic.ch3_worldsales report to create a strongly-typed report document.
From that point, we just need to set the ReportSource property in the Form''''s Load method:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load CrystalReportViewer1.ReportSource = ch3_worldsales1 End Sub
Here, ch3_worldsales1 is the name automatically assigned to the ReportDocument component when you added it to your Form.
Regardless of which method you choose to bind your report to the viewer, the result is the same. When you start your application and the Form is loaded, the Crystal Report Viewer will run the report you have set in the ReportSource property and display a preview of the same.
Most data sources that Crystal Reports can use are secure, requiring a user name, password, and other credentials. When working with the Crystal Report Viewer, we can pass this information through the use of the TableLogonInfo collection.
Important
If your report is based on an unsecured database or file, you don''''t need to pass any logon information at all to your report. To understand how the Crystal Reports Viewer works with database credentials, consider that each table in your report is its own unique identity and in turn, its own database credentials. All of these credentials are stored in the TableLogonInfos collection, part of the CrystalDecisions.Shared namespace, and for each table there is a corresponding TableLogonInfo object.
In order to set the database credentials for your report, you will need to loop through all of the tables and set the ConnectionInfo properties within TableLogonInfo for each. The properties in the ConnectionInfo class are:
Property
Description
DatabaseName Gets or sets the name of the database
Password Gets or sets the password for logging on to the data source
ServerName Gets or sets the name of the server or ODBC data source where the database is located
UserID Gets or sets a user name for logging on to the data source Since our Xtreme sample data is held within in an unsecured Access database, we are going to use another report in this example. Included with the sample files for this chapter is a copy of the World Sales report (ch3_worldsales_northwind) that was created from the Northwind database that ships with SQL Server. You can find this file in the download, through the path CrystalReports\Chapter03\ch3_worldsales_northwind.rpt.
We''''re going to open a new project and add it to our existing one. Click on File | New | Project and select Windows Application. Call the project viewer_database, saving it to CrystalReports\Chapter03. Make sure that the radio button Add to Solution is selected as opposed to Close Solution:
Right-click on the project name, and click Set As Startup Project. We''''re now ready to look at database access.
To add ch3_worldsales_northwind.rpt to your project, select Project | Add new item and browse for the report where you unzipped the downloaded sample files. Add it to the project and click the Open button.
Now drag and drop a CrystalReportViewer onto your Form. For the sake of attractiveness, set the Dock property to Fill.
You will also need to add this report as a component to your Form. Switch to the Layout view of your Form and look in the toolbox under Components. In this section, you should see a component labeled ReportDocument. Drag this component onto your Form.
From the drop-down list, select the ch3_worldsales_Northwind report and click OK. We are now ready to get on with setting the database credentials for this report.
This report has been written from a single table, Customer for which we are setting the ConnectionInfo. The name of our server is localhost, off of the Northwind database, with sa as the user ID, and no password.
Add this code to the Form1_Load method:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim myReport = New ch3_worldsales_northwind() Dim myTableLogonInfos = New CrystalDecisions.Shared.TableLogOnInfos() Dim myTableLogonInfo = New CrystalDecisions.Shared.TableLogOnInfo() Dim myConnectionInfo = New CrystalDecisions.Shared.ConnectionInfo() With myConnectionInfo .ServerName = "localhost" .DatabaseName = "Northwind" .UserID = "sa" .Password = " End With myTableLogonInfo.ConnectionInfo = myConnectionInfo myTableLogonInfo.TableName = "customers" myTableLogonInfos.Add (myTableLogonInfo) CrystalReportViewer1.LogOnInfo = myTableLogonInfos CrystalReportViewer1.ReportSource = myReport End Sub
Make sure that when you are finished setting the ConnectionInfo for the table, you specify the table name you are working with prior to using the Add method, otherwise you will receive an error message.
Compile and run the example. The report should appear, looking identical to the previous examples.
This is a very simple example, as our report only has one table to worry about. If you have a report that features multiple tables or if you don''''t know the names of the tables, you could also set up a loop to go through each report.database.table in report.database.tables and set the ConnectionInfo properties for each.
Important
In order to get all of the tables in your report and loop through them, you will need to use the Report Engine, which is covered in Chapter 8.
In addition to setting the database credentials for our report, we can also set the record selection formula that is used to filter our report records. The record selection formula within your report is created whenever you use the Select Expert within the Crystal Reports Designer by right-clicking on your report and selecting Report | Select Expert..., and then clicking on the table that you wish to see.
This opens up a second dialog box, containing the information on that table. You can choose to hide or show the formula on this box, as shown here:
Any selections you make in the Select Expert are translated into a record selection formula written in Crystal Syntax, and displayed in the textbox, as you can see in the case above.
If you click OK here, then the next time you run the report it will only return customers in the USA.
For more information on creating formulas and Crystal Syntax, turn over to Chapter 7: Formulas and Logic.
You can also edit the record selection formula that is generated by right-clicking on your report in the report designer and selecting Report | Edit Selection Formula | Records. When your report is run, this record selection formula is translated into the WHERE clause for the SQL statement that is submitted to the database and the results are returned to Crystal Reports, so while you can''''t change the SQL statement your report is based on, you can control the records that are returned to the report.
At run time, the SelectionFormula property gives us the ability to return or set this value. To return a record selection formula, we would simply request the property as a string, as shown here:
CrystalReportViewer1.SelectionFormula.ToString
Using the report and viewer we have been working with, we could set the record selection property when the Form loads, before the call to the database, ensuring that only records for customers in the USA are shown:
Dim myConnectionInfo = New CrystalDecisions.Shared.ConnectionInfo() CrystalReportViewer1.SelectionFormula = "{Customer.Country} = ''''USA''''" With myConnectionInfo ...
Alternately, another way we could use this property is to draw a drop-down list on our Form with all of the different countries in the report and allow the user to select which country they wanted to filter by. When working with record selection, you can come up with some pretty neat ways to deliver one report that could be used for many different types of users.
Speaking of different types of users - the next section deals with how to customize the appearance and layout of the viewer itself. So in addition to showing them only the records they want to see, you could also give them their own custom viewer with which to view the resulting report.