mppeters
asked on
Dynamic crystal report from a datatable and export to PDF
All the samples I've seen use a pre-defined crystal report. How would I create a dynamic crystal report using a datatable (or dataset) as the datasource and export it to PDF, all from one button click?
So I have a query:
myQuery = "SELECT Users.UserKey, Rules.RuleDescr
FROM Users
INNER JOIN userRules ON Users.UserKey = userRules.UserKey
INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey"
And I fill a datatable with the results of that query.
How the heck do I create the Crystal Report to show the results grouped by UserKey and then export to PDF.
Here's the code I have so far:
Private Sub GenerateReportBTN_Click(By Val sender As System.Object, ByVal e As System.EventArgs) Handles GenerateReportBTN.Click
Dim CrystalReportDocument As ReportDocument
Dim CrystalExportOptions As ExportOptions
Dim CrystalDiskFileDestination Options As DiskFileDestinationOptions
Dim Filename As String = "C:\Report.pdf"
CrystalReportDocument = New ReportDocument
'TODO: Set the datasource, and define the report to show userkey and ruledescr, grouped by userkey
CrystalDiskFileDestination Options = New DiskFileDestinationOptions
CrystalDiskFileDestination Options.Di skFileName = Filename
CrystalExportOptions = CrystalReportDocument.Expo rtOptions
With CrystalExportOptions
.DestinationOptions = CrystalDiskFileDestination Options
.ExportDestinationType = ExportDestinationType.Disk File
.ExportFormatType = ExportFormatType.PortableD ocFormat
End With
CrystalReportDocument.Expo rt()
End Sub
So I have a query:
myQuery = "SELECT Users.UserKey, Rules.RuleDescr
FROM Users
INNER JOIN userRules ON Users.UserKey = userRules.UserKey
INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey"
And I fill a datatable with the results of that query.
How the heck do I create the Crystal Report to show the results grouped by UserKey and then export to PDF.
Here's the code I have so far:
Private Sub GenerateReportBTN_Click(By
Dim CrystalReportDocument As ReportDocument
Dim CrystalExportOptions As ExportOptions
Dim CrystalDiskFileDestination
Dim Filename As String = "C:\Report.pdf"
CrystalReportDocument = New ReportDocument
'TODO: Set the datasource, and define the report to show userkey and ruledescr, grouped by userkey
CrystalDiskFileDestination
CrystalDiskFileDestination
CrystalExportOptions = CrystalReportDocument.Expo
With CrystalExportOptions
.DestinationOptions = CrystalDiskFileDestination
.ExportDestinationType = ExportDestinationType.Disk
.ExportFormatType = ExportFormatType.PortableD
End With
CrystalReportDocument.Expo
End Sub
ASKER
Ok then. Forget the dynamic part of it.
How would I create the report from the results of a query like the following?
SELECT Users.UserKey, Rules.RuleDescr
FROM Users
INNER JOIN userRules ON Users.UserKey = userRules.UserKey
INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey
UNION
SELECT ur.UserKey, Rules.RuleDescr
FROM
(SELECT Users.UserKey, Roles.RoleKey, Roles.RoleDesc
FROM Roles
INNER JOIN UserRole ON Roles.RoleKey = UserRole.RoleKey
INNER JOIN Users ON UserRole.UserKey = Users.UserKey) ur
INNER JOIN rolerules ON ur.RoleKey = rolerules.RoleKey
INNER JOIN Rules ON rolerules.RuleKey = Rules.RuleKey
How would I create the report from the results of a query like the following?
SELECT Users.UserKey, Rules.RuleDescr
FROM Users
INNER JOIN userRules ON Users.UserKey = userRules.UserKey
INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey
UNION
SELECT ur.UserKey, Rules.RuleDescr
FROM
(SELECT Users.UserKey, Roles.RoleKey, Roles.RoleDesc
FROM Roles
INNER JOIN UserRole ON Roles.RoleKey = UserRole.RoleKey
INNER JOIN Users ON UserRole.UserKey = Users.UserKey) ur
INNER JOIN rolerules ON ur.RoleKey = rolerules.RoleKey
INNER JOIN Rules ON rolerules.RuleKey = Rules.RuleKey
First create the report "Strongly typed". From ur code, create and fill a dataset with the results and pass it to the report.
Get this free e-book on creating crystal reports:
http://www.crystalreportsbook.com/FreeEbook.asp
-Baan
Get this free e-book on creating crystal reports:
http://www.crystalreportsbook.com/FreeEbook.asp
-Baan
ASKER
Thanks DotNetLover.
I understand the concept, but what is the code?
I understand the concept, but what is the code?
If you've created the report as a rpt file in your vb project then the code looks like this:
Dim rpt As New myReport
Dim frm As New ReportViewer
'As a side note ... this allows you to pass a string into a text field on the report at runtime that is not a part of the recordset
Dim oText As CrystalDecisions.CrystalRe ports.Engi ne.TextObj ect
oText = rpt.Section2.ReportObjects .Item("txt Title")
oText.Text = "History Report For " & Name
'This passes records to the report object
rpt.SetDataSource(Table)
'This sets the report to a viewer, so instead you want to put your export code here
frm.crvViewer.ReportSource = rpt
frm.crvViewer.DisplayGroup Tree = False
frm.Show()
Dim rpt As New myReport
Dim frm As New ReportViewer
'As a side note ... this allows you to pass a string into a text field on the report at runtime that is not a part of the recordset
Dim oText As CrystalDecisions.CrystalRe
oText = rpt.Section2.ReportObjects
oText.Text = "History Report For " & Name
'This passes records to the report object
rpt.SetDataSource(Table)
'This sets the report to a viewer, so instead you want to put your export code here
frm.crvViewer.ReportSource
frm.crvViewer.DisplayGroup
frm.Show()
"Code" means.. your program code... I use this term a lot here. You see, just like.. Code behind. :))
ASKER
When I add the Crystal Report file to the solution, it wants me to add the tables and the fields directly, and define the links for those tables ahead of time. How can I represent the following query in the rpt file?
SELECT Users.UserKey, Rules.RuleDescr
FROM Users
INNER JOIN userRules ON Users.UserKey = userRules.UserKey
INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey
UNION
SELECT ur.UserKey, Rules.RuleDescr
FROM
(SELECT Users.UserKey, Roles.RoleKey, Roles.RoleDesc
FROM Roles
INNER JOIN UserRole ON Roles.RoleKey = UserRole.RoleKey
INNER JOIN Users ON UserRole.UserKey = Users.UserKey) ur
INNER JOIN rolerules ON ur.RoleKey = rolerules.RoleKey
INNER JOIN Rules ON rolerules.RuleKey = Rules.RuleKey
SELECT Users.UserKey, Rules.RuleDescr
FROM Users
INNER JOIN userRules ON Users.UserKey = userRules.UserKey
INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey
UNION
SELECT ur.UserKey, Rules.RuleDescr
FROM
(SELECT Users.UserKey, Roles.RoleKey, Roles.RoleDesc
FROM Roles
INNER JOIN UserRole ON Roles.RoleKey = UserRole.RoleKey
INNER JOIN Users ON UserRole.UserKey = Users.UserKey) ur
INNER JOIN rolerules ON ur.RoleKey = rolerules.RoleKey
INNER JOIN Rules ON rolerules.RuleKey = Rules.RuleKey
I use a xsd file to define the structure of the data first. Then you can browse for that "strongly-typed" dataset and use it as the source in design mode.
... nice definition DotNetLover ... lol
... nice definition DotNetLover ... lol
ASKER
Ok thanks RacinRan. So how would I represent the above query in the xsd file?
The complexity of query has nothing to with setting up the data structure in the report. The only thing it needs to know is what the data is that is being returned by the query. So, in your case, you will set up an element for UserKey and an element for RuleDescr because those are the only 2 fields being returned.
Here is the xml code for the xsd (which is a dataset):
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="Dataset1" targetNamespace="http://tempuri.org/Dataset1.xsd" elementFormDefault="qualif ied"
attributeFormDefault="qual ified" xmlns="http://tempuri.org/Dataset1.xsd" xmlns:mstns="http://tempuri.org/Dataset1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas- microsoft- com:xml-ms data">
<xs:element name="Dataset1" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="myDatatable">
<xs:complexType>
<xs:sequence>
<xs:element name="UserKey" type="xs:string" minOccurs="0" />
<xs:element name="UserDescr" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The dataset has two modes in design view one is a drag and drop type interface and a xml view. This is the xml view.
Here is the xml code for the xsd (which is a dataset):
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="Dataset1" targetNamespace="http://tempuri.org/Dataset1.xsd" elementFormDefault="qualif
attributeFormDefault="qual
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-
<xs:element name="Dataset1" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="myDatatable">
<xs:complexType>
<xs:sequence>
<xs:element name="UserKey" type="xs:string" minOccurs="0" />
<xs:element name="UserDescr" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The dataset has two modes in design view one is a drag and drop type interface and a xml view. This is the xml view.
btw...my code assumes the data type is string. If it's not then replace string with whatever in the <xs:Element name = "UserKey" type = "xs:<insert here>"
ASKER
I've tried several different ways and can't seem to get past the following error:
CrystalDecisions.CrystalRe ports.Engi ne.DataSou rceExcepti on: Query Engine Error: 'C:\DOCUME~1\MARK\ASPNET\L OCALS~1\Te mp\temp_c8 63172c-537 7-4256-82e d-1543fca7 634f.rpt'
XSD schema is:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="Dataset1" targetNamespace="http://tempuri.org/Dataset1.xsd" elementFormDefault="qualif ied"
attributeFormDefault="qual ified" xmlns="http://tempuri.org/Dataset1.xsd" xmlns:mstns="http://tempuri.org/Dataset1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas- microsoft- com:xml-ms data">
<xs:element name="Dataset1" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="UserRules">
<xs:complexType>
<xs:sequence>
<xs:element name="UserID" type="xs:string" />
<xs:element name="RuleDescr" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Button click code is:
Private Sub GenerateReportBTN_Click(By Val sender As System.Object, ByVal e As System.EventArgs) Handles GenerateReportBTN.Click
Dim rptReportDocument As CrystalReport1
Dim rptExportOptions As ExportOptions
Dim rptDiskFileDestinationOpti ons As DiskFileDestinationOptions
Dim PdfFilename As String
Dim dsUserRules As DataSet
Dim dt As DataTable
Dim sqlCmd As SqlCommand
Dim sqlString As String
PdfFilename = "C:\Report.pdf"
sqlString = "SELECT Users.UserID, Rules.RuleDescr" _
& " FROM Users" _
& " INNER JOIN userRules ON Users.UserKey = userRules.UserKey" _
& " INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey" _
& " UNION" _
& " SELECT ur.UserID, Rules.RuleDescr" _
& " FROM " _
& " (SELECT Users.UserID, Roles.RoleKey, Roles.RoleDesc" _
& " FROM Roles" _
& " INNER JOIN UserRole ON Roles.RoleKey = UserRole.RoleKey" _
& " INNER JOIN Users ON UserRole.UserKey = Users.UserKey) ur" _
& " INNER JOIN rolerules ON ur.RoleKey = rolerules.RoleKey" _
& " INNER JOIN Rules ON rolerules.RuleKey = Rules.RuleKey"
sqlCmd = New SqlCommand(sqlString)
sqlCmd.CommandType = CommandType.Text
Dim sda As SqlDataAdapter
sda = New SqlDataAdapter(sqlCmd)
sqlCmd.CommandTimeout = 90
sqlCmd.Connection = GetConnection()
sqlCmd.Connection.Open()
dsUserRules = New DataSet
sda.Fill(dsUserRules)
sqlCmd.Connection.Close()
rptReportDocument = New CrystalReport1
rptReportDocument.SetDataS ource(dsUs erRules)
rptDiskFileDestinationOpti ons = New DiskFileDestinationOptions
rptDiskFileDestinationOpti ons.DiskFi leName = PdfFilename
rptExportOptions = rptReportDocument.ExportOp tions
With rptExportOptions
.DestinationOptions = rptDiskFileDestinationOpti ons
.ExportDestinationType = ExportDestinationType.Disk File
.ExportFormatType = ExportFormatType.PortableD ocFormat
End With
rptReportDocument.Export()
End Sub
CrystalDecisions.CrystalRe
XSD schema is:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="Dataset1" targetNamespace="http://tempuri.org/Dataset1.xsd" elementFormDefault="qualif
attributeFormDefault="qual
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-
<xs:element name="Dataset1" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="UserRules">
<xs:complexType>
<xs:sequence>
<xs:element name="UserID" type="xs:string" />
<xs:element name="RuleDescr" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Button click code is:
Private Sub GenerateReportBTN_Click(By
Dim rptReportDocument As CrystalReport1
Dim rptExportOptions As ExportOptions
Dim rptDiskFileDestinationOpti
Dim PdfFilename As String
Dim dsUserRules As DataSet
Dim dt As DataTable
Dim sqlCmd As SqlCommand
Dim sqlString As String
PdfFilename = "C:\Report.pdf"
sqlString = "SELECT Users.UserID, Rules.RuleDescr" _
& " FROM Users" _
& " INNER JOIN userRules ON Users.UserKey = userRules.UserKey" _
& " INNER JOIN Rules ON userRules.RuleKey = Rules.RuleKey" _
& " UNION" _
& " SELECT ur.UserID, Rules.RuleDescr" _
& " FROM " _
& " (SELECT Users.UserID, Roles.RoleKey, Roles.RoleDesc" _
& " FROM Roles" _
& " INNER JOIN UserRole ON Roles.RoleKey = UserRole.RoleKey" _
& " INNER JOIN Users ON UserRole.UserKey = Users.UserKey) ur" _
& " INNER JOIN rolerules ON ur.RoleKey = rolerules.RoleKey" _
& " INNER JOIN Rules ON rolerules.RuleKey = Rules.RuleKey"
sqlCmd = New SqlCommand(sqlString)
sqlCmd.CommandType = CommandType.Text
Dim sda As SqlDataAdapter
sda = New SqlDataAdapter(sqlCmd)
sqlCmd.CommandTimeout = 90
sqlCmd.Connection = GetConnection()
sqlCmd.Connection.Open()
dsUserRules = New DataSet
sda.Fill(dsUserRules)
sqlCmd.Connection.Close()
rptReportDocument = New CrystalReport1
rptReportDocument.SetDataS
rptDiskFileDestinationOpti
rptDiskFileDestinationOpti
rptExportOptions = rptReportDocument.ExportOp
With rptExportOptions
.DestinationOptions = rptDiskFileDestinationOpti
.ExportDestinationType = ExportDestinationType.Disk
.ExportFormatType = ExportFormatType.PortableD
End With
rptReportDocument.Export()
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
'first add crystal reports and then put CrystalReportViewer into the form
Imports System.Data.SqlClient
'Declaration
Public cn As New SqlConnection
Public cmd1 As New SqlCommand
Public oda1 As New SqlDataAdapter
Public ods As New DataSet
'write the following code in button
cn.ConnectionString = "Server=eteam08;Database=d bTestGrid; user id=sa;password=imran"
cn.Open()
'MsgBox("Connection Established")
cmd1.Connection = cn
cmd1.CommandType = CommandType.Text
cmd1.CommandText = "select * from tblCustomer" 'write querry
oda1.SelectCommand = cmd1
oda1.Fill(ods, "Customer") 'you can write any name instead of Customer
Dim rpt As New CrystalReport1
rpt.SetDataSource(ods.Tabl es("Custom er"))
CrystalReportViewer1.Repor tSource = rpt
Imports System.Data.SqlClient
'Declaration
Public cn As New SqlConnection
Public cmd1 As New SqlCommand
Public oda1 As New SqlDataAdapter
Public ods As New DataSet
'write the following code in button
cn.ConnectionString = "Server=eteam08;Database=d
cn.Open()
'MsgBox("Connection Established")
cmd1.Connection = cn
cmd1.CommandType = CommandType.Text
cmd1.CommandText = "select * from tblCustomer" 'write querry
oda1.SelectCommand = cmd1
oda1.Fill(ods, "Customer") 'you can write any name instead of Customer
Dim rpt As New CrystalReport1
rpt.SetDataSource(ods.Tabl
CrystalReportViewer1.Repor
with the version of Crystal Reports that comes with VS.Net, you can NOT create repport dynamically. Go for stand alone version 10.
-Baan