Automagically Display Crystal Parameters: Part III
page 1 of 1
Published: 26 May 2004
Unedited - Community Contributed
Abstract
Final Part in Series on a sample application that Dynamically displays a reports parameters, then allows the user to view that report.
by Eric Landes
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 13124/ 20

[download sample app]

This series is about a sample application that can take a Crystal Report, display input parameters, then display that report.  In part 1 of this series, I went over the web page that shows the how to display a Crystal Report dynamically.  In part 2 we went over the class that actually performed the work of determining any parameters of the Crystal Report.  This final part of the series, shows how to take those two parts, and display the report.

I accomplish this by using methods on the default.aspx web page.  This part of the series starts after the user has input any parameters for the report and submitted it to be viewed.  The Report will be logged onto the reports datasource.  Then the report will be displayed in Adobe Acrobat format.

Allowing the user to view the report

When the _defaultCR CreatePage method created the parameters, it also added a submit button.

                _literalBr = Nothing
            End If
        Next
        Dim oSubmitButton As New System.Web.UI.WebControls.Button()
        oSubmitButton.Text = "View Report"
        oSubmitButton.ID = "ReportButton"
       AddHandler oSubmitButton.Click, AddressOf PCRMButtonClicked
        ' Add a control to pass the filename
        Dim oLiteral2 As New System.Web.UI.LiteralControl()
        oLiteral2.Text = "<input type=hidden name='FileID' value='" & Request.QueryString("FileID") & "'>"
        oLiteral2.ID = "HiddenFileID"
        Panel1.Controls.Add(oLiteral2)
        Panel1.Controls.Add(oSubmitButton)

The button oSubmitButton adds a handler for a click event to the method PCRMButtonClicked, which in turn calls the method CreateReportToView.  Now that the Parameters (if there are any) have been filled in, the user can click on the View Report button to see the report in an adobe acrobat format.  I chose displaying in that format to make for easy display and client side printing. 

Displaying the report

As mentioned earlier, when a user clicks on the button that says “View Report”, the method PCRMButtonClicked is called.  From that method CreateReportToView, the method with the muscle is called.  CreateReportToView is separated out from the actual click event code for cleaner code separation.  This method iterates through the values just entered for to the corresponding parameters in the report.

        Dim oReport As New CrystalDecisions.CrystalReports.Engine.ReportDocument()
        Dim oPCRMCRObject As New PCRMCreateCRObjects()
        Dim reportName As String = Server.MapPath("/CrystalParams") + "\customerOrders.rpt"
        Dim oCRParam As CrystalDecisions.CrystalReports.Engine.ParameterFieldDefinition
        Dim oDiscreteParam As New CrystalDecisions.Shared.ParameterDiscreteValue()
        Dim oDefaultValues As New CrystalDecisions.Shared.ParameterValues()

We start out by instantiating a ReportDocument object.  We also instatiate a PCRMCreateCRObjects class, to help us apply the appropriate parameters.  The report name variable contains a hard coded report in this sample.  Normally you would use a query string with some kind of report id that can be tied back to a report path and name through a database.  For sample purposes, I have kept it simply hard coded.

Finally we declare the Paramater objects.  First, a ParameterFieldDefinition to help in getting the name from the input form.  Second, a ParameterDiscreteValue object to use to apply the value entered back to the report.  Third, a ParameterValues collection object, to collect the discrete parameters to be applied to the report.

            If oPCRMCRObject.IsThisAValidCrystalFile(reportName) Then
                oReport.Load(reportName)
                For Each oCRParam In oReport.DataDefinition.ParameterFields
                    '                oDefaultValues = New CrystalDecisions.Shared.ParameterValues()
                    oDiscretePara[code language="VB.NET"]
            If oPCRMCRObject.IsThisAValidCrystalFile(reportName) Then
                oReport.Load(reportName)
                For Each oCRParam In oReport.DataDefinition.ParameterFields
                    '                oDefaultValues = New CrystalDecisions.Shared.ParameterValues()
                    oDiscreteParam.Value = GetRequest(oCRParam.ParameterFieldName & "1", oCRParam)

Once again I use the method IsThisAValidCrystalFile to verify that the report name and path passed are valid.  When that test is passed, the report gets loaded into oReport.  Then using the ParameterValues collection oCRParam, I iterate through oReports Parameter fields.  oDiscreteParam gets the value applied using the GetRequest method.

    Public Function GetRequest(ByVal _paramName As String, _
        ByVal _paramField As CrystalDecisions.CrystalReports.Engine.ParameterFieldDefinition) As String
        Dim _returnValue As String
        Select Case _paramField.ParameterValueKind
            Case CrystalDecisions.[Shared].ParameterValueKind.DateParameter
                Dim _thisCal As System.Web.UI.WebControls.Calendar
                _thisCal = Panel1.FindControl(_paramName)
                _returnValue = CStr(_thisCal.SelectedDate)
            Case CrystalDecisions.[Shared].ParameterValueKind.DateTimeParameter
                Dim _thisCal As System.Web.UI.WebControls.Calendar
                _thisCal = Panel1.FindControl(_paramName)
                _returnValue = CStr(_thisCal.SelectedDate)
            Case CrystalDecisions.[Shared].ParameterValueKind.NumberParameter
                _returnValue = Request.Form(_paramName)
            Case CrystalDecisions.[Shared].ParameterValueKind.StringParameter
                _returnValue = Request.Form(_paramName)
        End Select
        Return _returnValue
    End Function

GetRequest uses _paramName to help find the forms input control to use.  Then, depending on what the ParamterVAlueKind is, the value is returned.  If it’s a datetime parameter, then I need to instantiate a WebControls Calendar class to get the value.  I utilize findcontrol to get the correct object from the form.  Then I convert the selected Date to a string to pass back to the calling method.

Back to the CreateReportView method.

                    oDefaultValues.Add(oDiscreteParam)
                    oCRParam.ApplyCurrentValues(oDefaultValues)
                Next
            End If
            oPCRMCRObject.Close()
            oPCRMCRObject = Nothing
            DoCRLogin(oReport)
            ExportData(oReport)

Now that there is a value put into the oDiscreteParam, we can add it to the oDefault collection.  Now we use the ApplyCurrntValues method of the oCRParam object from the reports ParameterFields.  The iteration continues until all the Parameterfields have been touched.

After closing the custom object oPCRMCRObject, we use the DoCRLogin method to logon to the report.

   Public Sub DoCRLogin(ByRef oRpt As CrystalDecisions.CrystalReports.Engine.ReportDocument)
        Dim _applyLogin As New ApplyCRLogin
        ' use ApplyLogin object to apply login info to all tables in CR object
        _applyLogin._dbName = "Northwind"
        _applyLogin._passWord = "CrystalUser"
        _applyLogin._serverName = "(local)"
        _applyLogin._userID = "CrystalUser"
        _applyLogin.ApplyInfo(oRpt)
        ' clean up
        _applyLogin = Nothing
    End Sub

DoCRLogin should be reusable among other applications.  I would separate that into a new project, or perhaps into the PCRMCRObjects project.  For now, it’s on the web page.  Taking the reportDocument in by reference, I also instantiate a new class called ApplyCRLogin.  This class has the properties for database name, userid, server name, and password.  Once those are set, the ApplyInfo method is called using the referenced reportdocument.

    Public Sub ApplyInfo(ByRef _oRpt As CrystalDecisions.CrystalReports.Engine.ReportDocument)
        Dim oCRDb As CrystalDecisions.CrystalReports.Engine.Database = _oRpt.Database
        Dim oCRTables As CrystalDecisions.CrystalReports.Engine.Tables = oCRDb.Tables
        Dim oCRTable As CrystalDecisions.CrystalReports.Engine.Table
        Dim oCRTableLogonInfo As CrystalDecisions.Shared.TableLogOnInfo
        Dim oCRConnectionInfo As New CrystalDecisions.Shared.ConnectionInfo()
        '        Dim oCRBeginDateParam As CrystalDecisions.Shared.ParameterField
        oCRConnectionInfo.DatabaseName = _dbName
        oCRConnectionInfo.ServerName = _serverName
        oCRConnectionInfo.UserID = _userID
        oCRConnectionInfo.Password = _passWord
        ' TODO: Need to change this to allow multiple logins for multiple sources.
        For Each oCRTable In oCRTables
            oCRTableLogonInfo = oCRTable.LogOnInfo
            oCRTableLogonInfo.ConnectionInfo = oCRConnectionInfo
            oCRTable.ApplyLogOnInfo(oCRTableLogonInfo)
        Next
    End Sub

ApplyInfo uses those properties set to apply them to the reports different tables by iterating through the tables within the reports database.  oCRTables is a collection of the reports tables.  This method owes to Wolfgang Baecks method he discovered when logging on to sub reports.  Currently this method applies the same login information to all the tables in the collection.  If your reports mix databases or tables, you might need to modify this.

Once we are finished using Applyinfo, on to the exporting the report.  Using the method ExportData, the report is output to a pdf file into the browser.  This gives the user a pretty seamless experience, with the advantages of client side printing.

   Public Sub ExportData(ByRef oRpt As Object)
        Dim fs As IO.FileStream
        Dim FileSize As Long
        Dim oDest As New CrystalDecisions.Shared.DiskFileDestinationOptions
        Dim ExportFileName As String = Server.MapPath("/") & ConfigurationSettings.AppSettings("ExportDir") & Session.SessionID & ".pdf"
        Try
            'Dim oExport As New CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportOptions()
            oRpt.ExportOptions.ExportDestinationType = CrystalDecisions.[Shared].ExportDestinationType.DiskFile
            oRpt.ExportOptions.ExportFormatType = CrystalDecisions.[Shared].ExportFormatType.PortableDocFormat
            oDest.DiskFileName = ExportFileName
            oRpt.ExportOptions.DestinationOptions = oDest
            oRpt.Export()
            'Build Target Filename
            'Send the file to the user that made the request
            Response.Clear()
            Response.Buffer = True
            Response.AddHeader("Content-Type", "application/pdf")
            '        Response.AddHeader("Content-Disposition", "attachment;filename=" & Session.SessionID & ".pdf;")
            fs = New IO.FileStream(ExportFileName, IO.FileMode.Open)
            FileSize = fs.Length
            Dim bBuffer(CInt(FileSize)) As Byte
            fs.Read(bBuffer, 0, CInt(FileSize))
            fs.Close()
            Response.BinaryWrite(bBuffer)
            Response.Flush()
            Response.Close()
        Catch e As Exception
        End Try
    End Sub

I start out setting the oRpt ExportOptions Destination to a DiskFile.  Then we set ExportFormatType to the pdf type (PortableDocFormat).  Next, we set the file name to the variable ExportFileName.  This is created using the SessionID in the name to create a pretty random file name.  This is a temporary file anyways, so for the current user, it shouldn’t matter if it overwrites another file.

Once I’ve set the Destination Options, and called the reports export method, I’m ready to write this back out to the browser. 

To write it out to the browser, I clear the response object, and add a pdf header to it.    Next I open the file I just created using FileStream class.  The variable bBuffer is used to store the data in byte format to be written back to the browser.  Once that is filled, then using Response.BinaryWrite the Response.Flush to output the pdf file to the browser.

In the End!

That’s how I dynamically create the parameters for a Crystal Report, then display that report in a pdf document using ASP.NET.  This sample application is intended to allow you to create your own inexpensive Report manager.  It’s a starting point not a complete solution.  You might want to compare the ability to do this with using Crystal Enterprise.  Enjoy, and keep the ASP.NET faith!

 



User Comments

Title: You Saved Me from MSDN HELL   
Name: Eclipse
Date: 2005-10-26 5:54:46 PM
Comment:
Great sample guys or gals!! I really appreciate you taking the time to place this information on the web. You're my hero!

Product Spotlight
Product Spotlight 



Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-29 6:40:50 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search