VS.NET Report Customization Object Models


While your application may not require any additional capabilities than are provided by a simple report bound to a viewer, there s a good possibility that you ll need to customize one or more aspects of the report at run time from within your application. These customizations can be as simple as supplying the user ID and password for a report s database connection from within your code (so that the user doesn t have to log in to the report s database again, after they ve already logged in to your application). Or, they may require more complex code that changes several report groups, formulas, parameter fields, formatting, or the report s record selection formula all on the fly based on other elements of your application.

Crystal Reports has always been the favorite of developers because of its flexible programming interfaces. And, the versions of Crystal Reports integrated with Visual Studio .NET carry on that tradition by providing rich object models that can control many aspects of report behavior at run time. Installing Crystal Reports 10 Developer or Advanced Developer editions after you ve installed VS.NET will improve on this programming flexibility even further.

There are two general ways of customizing your report at run time: using the Crystal Windows Forms Viewer object model or using the Crystal Reports Engine object model. You should look at both object models, as well as your application requirements, to determine which object model you wish to use for run-time customization. Business Objects documentation discourages mixing object model usage ”particularly when changing the same properties in both object models. For example, you will probably encounter confusion (and possibly application instability) if you, for example, change a parameter field using the Crystal Reports Engine object model and then change the parameter again using the Crystal Windows Forms Viewer object model before displaying the report in a viewer.

You ll notice that, in particular, the Windows Forms Viewer object model is improved if you install one of the developer editions of Crystal Reports 10. It s quite possible that the viewer object model will provide all the necessary customization you need. However, certain complex reporting requirements that require more involved section formatting, run-time addition or removal of fields, groups, and so forth, will not be satisfied with the viewer object model. These will require use of the Crystal Reports Engine object model that can make significant run-time modifications to a report object before it is passed to a report viewer.

Run-Time Customization with the Crystal Windows Forms Viewer

Some of the most obvious run-time customizations that you may wish to perform with the Crystal Windows Forms Viewer involve basic viewer appearance. You can, for example, control viewer properties at run time that you see in the Properties box at design time (the Anchor property mentioned earlier being a prime example). In addition, commonly used report options, such as the report s record selection formula and parameter field values, can be changed at run time only with calls to the Crystal Windows Forms Viewer object model.

These viewer object model choices are provided by assemblies installed with VS.NET and Crystal Reports 10. In particular, the CrystalDecisions.Windows.Forms namespace is added as a reference to your project automatically when you add a Crystal Windows Forms Viewer. This namespace exposes the object model available when using the viewer. When you install Crystal Reports 10 Developer or Advanced Developer edition on an existing computer containing Visual Studio .NET, this namespace is updated with additional version 10 capabilities.

Some initial customization you may wish to perform at run time involves simply viewer behavior, such as visibility of the group tree, appearance of individual toolbar buttons on the viewer toolbar, or complete invisibility of the entire toolbar. VS.NET intellisense technology will automatically show you available properties once you type the report viewer class, followed by a period. You can navigate through the various properties and, if necessary, see available arguments for available properties and methods .

click to expand

For example, the following code will hide the group tree in the viewer:

 CrystalReportViewer1.DisplayGroupTree = False 

And, more involved run-time customization to the viewer can involve instantiating additional objects, setting object properties, and passing the object to a viewer property to change viewer behavior. The following code will supply database credentials to each table object exposed by the Windows Forms Viewer:

 'Provide Database Credentials via Viewer object model 
Dim DatabaseInfo As CrystalDecisions.Shared.TableLogOnInfo
For Each DatabaseInfo In CrystalReportViewer1.LogOnInfo
DatabaseInfo.ConnectionInfo.ServerName = "x23"
DatabaseInfo.ConnectionInfo.DatabaseName = "xtreme"
DatabaseInfo.ConnectionInfo.UserID = "sa"
DatabaseInfo.ConnectionInfo.Password = "password"
Next

Notice the declaration of the TableLogOnInfo class, taken from the CrystalDecisions .Shared namespace. This namespace, also added to your project automatically when you add a Crystal Windows Forms Viewer, provides an object model that exposes common objects and properties that can be used in both Crystal web and Windows applications. For example, this same TableLogOnInfo object could also be applied to the Crystal Web Forms Viewer used in an ASP.NET application, or to objects associated with a report that doesn t even use a viewer.

Note  

The preceding example shows an object declaration with the fully qualified namespace. If you choose to add an Imports statement to import the namespace, then you would only need to declare the object using its class name without the need to precede it with CrystalDecisions.Shared .

The preceding code loops through the individual ConnectionInfo objects within the report viewer s LogonInfo class, setting credentials for each. All tables, regardless of original datasource, as well as subreport connection objects, will be included in the LogonInfo class. Accordingly, you ll need to take extra steps to properly assign values if the source tables in your main report or subreports come from different databases.

Other report properties can also be set with the Crystal Windows Forms Viewer object model. Some of the most obvious include:

  • Specifying database credentials If the report bound to the viewer is based on a secure database, the viewer will prompt for proper database credentials before displaying the report. If you have already gathered security information elsewhere in your application, you probably won t want your user to be prompted again. You can supply these credentials via the viewer object model, as shown in the previous example.

  • Modifying the record selection formula This is a very common requirement of report integration applications. You may wish to control report record selection based on some other control on the form or another element of your embedded application logic. This is accomplished by setting the viewer s RecordSelectionFormula property.

     'Set record selection using Viewer object model 
    CrystalReportViewer1.SelectionFormula = _
    "{Orders.Order Date} In #" & strStartDate & _
    "# To #" & strEndDate & "#"

    Make sure you pass a valid record selection formula, using Crystal Reports Crystal Formula Syntax, to this property. Don t forget to include proper punctuation, such as French braces around field names and apostrophes around string literals. In this example, pound signs are surrounding date data types. You may find discussions in Chapters 5 and 8 helpful in working with record selection formulas.

  • Supplying parameter field values In many cases, you may actually base your report s record selection on a parameter field. Or, perhaps you have created formulas based on parameter fields that change report grouping or formatting. As such, the ability to pass values to parameter fields at run time is crucial. Here s an example of passing a single value to a single-value (or discrete ) numeric parameter field:

     'Set parameter via Viewer object model 
    Dim Parameters As New ParameterFields
    Dim Parameter As New ParameterField
    Dim ParamValue As New ParameterDiscreteValue

    Parameter.ParameterFieldName = "Highlight Level"
    ParamValue.Value = sngHighlight
    Parameter.CurrentValues.Add(ParamValue)


    Parameters.Add(Parameter)

    CrystalReportViewer1.ParameterFieldInfo = Parameters

    Note that additional objects are instantiated to hold a parameters collection, a parameter field, and a parameter field discrete value. The parameter field name is supplied, using the parameter field s name in the underlying report. The actual discrete value is supplied via a previously defined variable that was properly cast to the appropriate data type. The discrete value object is added to the parameter s CurrentValues collection. The parameter is added to a parameters collection. And, finally, the viewer s ParameterFieldInfo property is set to the parameters collection.

    If you chose to simplify this approach with no extra object declarations, the following will perform the same task (note that the underscore is used in the book text only ”this line of code must not be separated onto two lines in the code window):

     CrystalReportViewer1.ParameterFieldInfo("Highlight Level")_ 
    .CurrentValues.AddValue(sngHighlight)

Windows Forms Viewer Events

Not only can you set report viewer properties at run time, but you can also trap report viewer events. As Crystal Reports blends into the entire .NET framework, you can trap viewer events in the Crystal Windows Forms Viewer and add code based on them. By selecting the desired Windows Forms Viewer in the Class Name list in the code window, you ll then be able to see a list of events that the viewer fires in the Method Name list.

click to expand

You may, for example, add code that traps a viewer drill-down event and performs some action based on the group that is drilled into.

 Private Sub CrystalReportViewer1_Drill(ByVal source As Object, _ 
ByVal e As CrystalDecisions.Windows.Forms.DrillEventArgs) _
Handles CrystalReportViewer1.Drill
If MsgBox("Are you sure you want to drill into " & _
e.NewGroupName & "?", MsgBoxStyle.YesNo, "Drill Down Detected...") _
= MsgBoxResult.No Then
e.Handled = True
End If 'MsgBox
End Sub

In this example, the event class exposes DrillEventArgs from the CrystalDecisions.Windows .forms namespace, including various properties to indicate what is being drilled into. Here, the code displays a message box asking the user to confirm the drill-down, including display of the group being drilled into via the event s NewGroupName property. If the user provides a response of No, the drill-down is canceled by setting the class s Handled property to True.

Run-Time Customization with the Crystal Reports Engine

So far, this chapter has concentrated entirely on run-time customization with the Crystal Windows Forms Viewer object model (with classes exposed by the CrystalDecisions.Windows .Forms namespace) and the shared object model (with classes exposed by the CrystalDecisions .Shared namespace). There s still yet another object model/namespace that exposes classes you can use to customize report behavior at run time.

By using the Crystal Reports Engine object model, you can customize report behavior at run time using techniques similar to those discussed previously in the chapter. However, this object model (exposed by the CrystalDecisions.CrystalReports.Engine namespace) offers properties, methods, and events that are strictly limited to the core report object you are integrating in your application, independent of any viewer you may have added to your application. Also, a much larger number of customization options are available with the Report Engine. In addition to setting parameter field values, supplying database credentials, and setting the report s record selection formula, the Report Engine offers the ability to control object formatting, supply new formula contents, export the report to various file formats, and much more.

Any customization you perform here typically takes place before you bind a report to a viewer (or, in situations where you don t even add a viewer to your project). Once you ve made these customizations to the report object, they will take effect when the report is bound to the viewer (or, in the case of a non-viewing application, whenever you execute a report method to ultimately output the report to a printer, exported file format, and so forth).

As discussed earlier in the chapter, you ll find properties and methods in the Report Engine that duplicate those found in the viewer object model. For example, you can supply database credentials, set the record selection formula, and supply parameter field values via either object model. The decision as to which object model to use is dependent upon your application particulars and how detailed your integration requirements are. Again, Business Objects recommends that you avoid duplicate calls from different object models in the same application. So, as you develop your application, look at which object model provides the best combination of simplicity and functionality depending on your requirements.

To make use of the Report Engine, you must ensure that the CrystalDecisions .CrystalReports.Engine namespace is being referenced in your project. In most cases, you ll also need references to the CrystalDecisions.Shared namespace. Typically, if you add a Crystal Windows Forms Viewer to the project, these namespaces will automatically be added. If, however, you are designing an application that does not make use of a Windows Forms Viewer, you ll need to use the VS.NET Add Reference option to add these namespaces to your project. Also, you ll need to declare references to several classes from these namespaces in your code and may prefer to use the Imports statement to allow class references without the fully qualified namespace name.

One of the first requirements of using the Report Engine is instantiation of a report object. As discussions earlier in the chapter indicate, there are several ways of adding reports to your project. And, there are several types of reports (un-typed, strongly typed, and so forth) that can be added. As an example, you may have added a strongly typed report to your project, either by using Add Add Existing Item with an existing .RPT file or by using Add Add New Item and designing a new Crystal Report. You then must declare an object to refer to the strongly typed report and expose the Report Engine s object model. Here s an example:

 Dim Report As New Orders 
'refers to strongly-typed Orders.rpt in project

Once you ve declared this object, you will notice many of the Report Engine properties and methods available via VS.NET s Intellisense technology.

click to expand

Some of the more common run-time customizations you can make with the Report Engine (but, by no means, an exhaustive list) include:

  • Supplying database credentials If your report is based on a secure database, you will probably prefer that your application code provide database credentials to prevent your report viewer from being prompted, or from your application failing if your report is not bound to a viewer. There are several ways for the Report Engine to supply these credentials. Examine the following:

     'Provide database credentials via Report object model 
    Report.SetDatabaseLogon("sa", "password")

    This single line of code (not including the comment) supplies a user ID and password to every datasource in the report, including those contained in subreports. The SetDatabaseLogon method greatly simplifies supplying database credentials if your report is based entirely on a single database connection.

    A second permutation of SetDatabaseLogon accepts four arguments:

     Report.SetDatabaseLogon("sa", "password", "SQLServer1", "xtreme") 

    This allows a database server and a database name to also be specified, in case you ve made use of several different connections in your report. You could repeat this line of code for each server used in the main report and subreports.

    If you need a more granular way of supplying database credentials for individual table objects in your main report and subreports, you ve got a little more coding ahead of you. Examine the following:

     Dim Logon As New TableLogOnInfo 
    Dim Tbl As Table
    For Each Tbl In Report.Database.Tables
    Logon = Tbl.LogOnInfo
    Logon.ConnectionInfo.ServerName = "SQLServer1"
    Logon.ConnectionInfo.DatabaseName = "xtreme"
    Logon.ConnectionInfo.UserID = "sa"
    Logon.ConnectionInfo.Password = "password"
    Tbl.ApplyLogOnInfo(Logon)
    Next Tbl

    'Provide database credentials to subreports
    Dim Subreport As ReportDocument
    For Each Subreport In Report.Subreports
    For Each Tbl In Subreport.Database.Tables
    Logon = Tbl.LogOnInfo
    Logon.ConnectionInfo.ServerName = "SQLServer1"
    Logon.ConnectionInfo.DatabaseName = "xtreme"
    Logon.ConnectionInfo.UserID = "sa"
    Logon.ConnectionInfo.Password = "password"
    Tbl.ApplyLogOnInfo(Logon)
    Next 'Tbl
    Next 'Subreport

    In the preceding code fragment, a TableLogonInfo class (from the CrystalDecisions .Shared namespace) and a Table class (from the CrystalDecisions.CrystalReports .Engine namespace) are instantiated. Then, each table in the main report is cycled through, supplying database credentials via the ConnectionInfo property.

    To accommodate subreports, a ReportDocument class is instantiated (this comes from CrystalDecisions.CrystalReports.Engine) to cycle through the main report s Subreports collection. For each subreport, similar loops through the Database.Tables collection are made to supply database credentials.

    While the preceding code will work with Crystal Reports 10, earlier versions (including Crystal Reports included with VS.NET) do not expose a Subreports collection. In this situation, code to deal with subreports must be even more granular, as the following example shows.

     crSections = Report.ReportDefinition.Sections 

    For Each crSection In crSections
    crReportObjects = crSection.ReportObjects

    For Each crReportObject In crReportObjects
    If crReportObject.Kind = ReportObjectKind.SubreportObject Then
    crSubreportObject = CType(crReportObject, SubreportObject)
    subrpt = _
    crSubreportObject.OpenSubreport(crSubreportObject.SubreportName)
    For Each subtbl In subReport.Database.Tables
    str &= subReport.Name & "-" & subtbl.Name & " - "
    objTableLogonInfo = subtbl.LogOnInfo
    objTableLogonInfo.ConnectionInfo = objConnInfo
    subtbl.ApplyLogOnInfo(objTableLogonInfo)
    subtbl.Location = _
    subtbl.Location.Substring(subtbl.Location.LastIndexOf(".") + 1)
    str &= subtbl.TestConnectivity() & vbCrLf
    Next
    End If
    Next
    Next
  • Setting record selection As with the viewer object model, you can set the report s record selection formula at run time via a simple property setting in the Report Engine. You will probably want to base this on other controls or conditions in your application. For example:

     Report.RecordSelectionFormula = "{Orders.Order Date} In #" _ 
    & strStartDate & "# To #" & strEndDate & "#"

    will return records where the order date is between values defined in two string variables . Ensure that you pass a syntactically correct formula using the Crystal Reports Crystal Syntax, including French braces around field names and apostrophes surrounding string literals (the pounds signs in this example indicate date values). Discussions on record selection and formula syntax can be found in Chapters 5 and 8 in this book.

  • Providing parameter field values A very common requirement of run-time report modification is dealing with parameter fields. As many report customizations can be accomplished by designing reports with parameter fields, you may find this one of the most common run-time modifications you ll be required to perform. While the viewer object model can change parameter field values at run time, you may prefer (or be required) to use the Report Engine to supply parameter values at run time. If you have installed Crystal Reports 10, the report object s SetParameterValue method is a simple way to supply a value to a parameter field:

     'Supply parameter field using Report object model 
    Report.SetParameterValue("Highlight Level", sngHighlight)

    The SetParameterValue method demonstrated here accepts two arguments: the parameter field to supply a value to (which can be specified either by name or index), and the value to pass to the parameter field (in this instance, a variable that has been cast elsewhere in the code to match the data type of the parameter field).

    The SetParameterValue method is fairly flexible in the data types and parameter field types (such as multi-value parameter fields) that it can accommodate. It can also be used to supply parameter values to subreports. The Crystal Reports 10 help collection contains complete details.

    If you have more complex parameter requirements that may not be accommodated by the SetParameterValue method, you may modify parameters via an additional object. Here s an example that sets a simple, single-value parameter field (note that the line continuation character is used in the book only ”the code must be on a single line in the code editor):

     Dim ParamValue As New ParameterDiscreteValue 
    ParamValue.Value = sngHighlight
    Report.ParameterFields("Highlight Level").CurrentValues._
    Add(ParamValue)

    A discrete parameter class is instantiated to hold a single discrete (single-value) parameter field. The object s Value property is set to a variable (again, properly cast earlier in the code). And, finally, the parameter object is added to the existing parameter field s CurrentValues collection (which, for a single-value parameter field, will contain only one member). The parameter field can be obtained from the report s ParameterFields collection, either by name or by numeric index.

  • Modifying existing formula contents One area of report customization that can be accomplished only with the Report Engine is run-time report formula modification. For example, you may wish to change some sort of calculation or string customization contained in a report formula to reflect a user control or other element of your custom application. By modifying a report formula at run time, you can change report calculations or customized fields based on your application elements. For example:

     'Set formula via Report object model 
    If sngTaxRate = 0 Then
    Report.DataDefinition.FormulaFields("Order + Tax").Text = _
    "{Orders.Order Amount}"
    Else
    Report.DataDefinition.FormulaFields("Order + Tax").Text = _
    "{Orders.Order Amount} + {Orders.Order Amount} * " & _
    Trim(CStr(sngTaxRate)) & "/ 100"
    End If 'sngTaxRate = 0

    You may navigate directly to the FormulaFields collection of the report s DataDefinition object. Notice that the particular collection member can be retrieved by name, in addition to numeric index (this is a refreshing change from many collections in the older Report Designer Component, which could only be accessed via numeric index). By setting the formula s Text property, you can change the formula contents at run time. In this example, a variable is examined indicating the tax rate supplied by the user. The formula that calculates the order amount plus tax is modified, depending on what the user supplies as the tax rate. Chapter 5 discusses report formulas in greater detail.

  • Supplying text object text While there are several ways to display a custom string or message on a report (perhaps you wish to display various run-time options chosen by the report viewer on the report itself), one way is to set the actual text displayed by a text object at run time. This capability is provided by the Report Engine only and cannot be accomplished by using any of the viewer object model calls. Here s an example:

     'Set text object via Report object model 
    Dim SelectionText As TextObject
    'CrystalDecisions.CrystalReports.Engine.TextObject if no Imports
    SelectionText = _ Report.ReportDefinition.ReportObjects("SelectionText")
    SelectionText.Text = strSelectionText

    Instantiate a TextObject object (supplied by the CrystalDecisions.CrystalReports .Engine namespace). Set it to the proper text object in the report by navigating through the report s ReportObjects collection from the ReportDefinition object. Then, set the text object s Text property to change the actual text contained in the text object on the report.

  • Controlling section formatting The Print Engine object model exposes all the report areas and sections within the source report. You may set formatting options for these sections and areas, such as page control, background color , section suppression and hiding, and so forth. Here s an example:

     If blnSummary Then 
    Report.ReportDefinition.Areas("Area4").AreaFormat._
    EnableHideForDrillDown = True
    Report.PHb.SectionFormat.EnableSuppress = True
    End If 'blnSummary

    A variable is tested to see if the user chose to see a summary report. If so, the Group Header 1 (the fourth report area ) is hidden for drill-down. And, the Page Header B section is suppressed. Note the difference between Area and Section objects ”an area refers to an entire series of related sections. For example, in the case of a report containing four details sections, the Report Engine will expose a single details area object, but individual details a, b, c, and d section objects. Some formatting is common to both areas and sections, while other formatting is specific to one or the other.

Printing Reports to a Printer

Windows applications often require that an integrated Crystal report be printed on a local or network printer. While the Windows Forms Viewer includes a print button that will print a report when clicked, you may wish to exert more control over printing from within your application code. Both the Windows Forms Viewer object model and the Report Engine object model expose methods to print a report to a printer. Depending on your application s requirements, you may make use of either.

The viewer object model exposes a simple PrintReport method that you may execute in code, as follows :

 'Print using Viewer Object Model 
CrystalReportViewer1.PrintReport()

This is functionally equivalent to the user clicking the Print button in the Windows Forms Viewer. It will launch a standard Windows Print dialog box, whereby the user can specify printing particulars, such as the page range. Note that you cannot change this behavior ”the print dialog box will always display and the user will need to specify any report printing particulars at run time.

If you want more granular control over report printing, or your particular application does not make use of the Windows Forms Viewer, use the Report Engine s PrintToPrinter method, as in the following sample:

 'Print using Report Engine 
Report.PrintToPrinter(1, False, 0, 0)

PrintToPrinter accepts four arguments: the number of copies to print, whether to print the report in collated form, the starting print page, and the ending print page (setting the print pages to zero will print the entire report).

Furthermore, you can access various properties within the Print Engine report object s PrintOptions class. Class members include such settings as page orientation, page size , margins, and so forth. If you want to gather some of these values from the user, you may design your own custom print options dialog box, or call a standard Windows print options dialog box, and pass resulting values to the report s PrintOptions class.

Exporting or E-Mailing Reports

While the Crystal Windows Forms Viewer includes an Export toolbar button that allows the viewer to export the viewed report to various file formats, you may wish to do this programmatically. For example, the only available destination for reports exported by clicking the export button is disk ”you may prefer to e-mail a report instead.

The simplest way to export a report is via the Report Viewer object model. Here s an example:

 'Export via viewer object model 
CrystalReportViewer1.ExportReport()

This is functionally equivalent to the user clicking the Export button on the Windows Forms Viewer. A dialog box will be presented to the user requiring them to choose a location and filename for the export, as well as the file format to export to. You cannot control any of these options programmatically.

For more controlled exporting, you ll need to use the Report Engine. Here s an example of more involved exporting that attaches a file to an e-mail message:

 Dim ExportOptions As New ExportOptions 
Dim EMailOptions As New MicrosoftMailDestinationOptions
ExportOptions.ExportFormatType = ExportFormatType.PortableDocFormat
ExportOptions.ExportDestinationType = ExportDestinationType.MicrosoftMail
EMailOptions.MailToList = strEMailAddress
EMailOptions.MailSubject = "XTEME Orders Report"
EMailOptions.MailMessage = _
"The XTREME Orders report is attached in PDF format"
ExportOptions.ExportDestinationOptions = EMailOptions
Report.Export(ExportOptions)

In this example, both ExportOptions and MicrosoftMailDestinationOptions objects are instantiated (both classes are exposed by the CrystalDecisions.Shared namespace). The ExportOptions export format type is set to Adobe Acrobat Portable Document Format (PDF), and the export destination type is set to Microsoft Mail. Various MicrosortMailDestinationOptions are used to set the e-mail s To address, subject, and message body text. The ExportOptions ExportDestinationOptions property is set to the MicrosoftMailDestinationOptions object. And, finally, the report object s Export method is executed, with the ExportOptions object being supplied as an argument.




Crystal Reports 10
Crystal Reports 10: The Complete Reference
ISBN: B005DI80VA
EAN: N/A
Year: 2004
Pages: 223
Authors: George Peck

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net