I have a VS2008 project in which I generate a Crystal report and use it to create an output file. The report is never displayed onscreen, so I don't use any report viewer controls. This is my current VB Code:
Now, this all works swimmingly apart from one thing: I've recently discovered that the value required by crConnectionInfo.ServerName is actually a DSN name, not the server name. However, I use my ConnectionDetails elsewhere in the code, and its Server property does need to be the server name for everything except these reports.Code:Imports CrystalDecisions.CrystalReports.Engine Imports CrystalDecisions.Shared Public Shared Function GenerateReport(ByVal databaseConnectionDetails As ConnectionDetails, ByVal reportTemplate As String, ByVal reportArchive As String, ByVal parameters As IDictionary(Of String, Object)) As Boolean Try Dim crTableLogonInfo As TableLogOnInfo = New TableLogOnInfo Dim crConnectionInfo As ConnectionInfo = New ConnectionInfo Dim crReportDocument As ReportDocument = New ReportDocument Dim crParameterDiscreteValue As ParameterDiscreteValue Dim crParameterFieldDefinitions As ParameterFieldDefinitions Dim crParameterFieldLocation As ParameterFieldDefinition Dim crParameterValues As ParameterValues '# Use the report template. crReportDocument.Load(reportTemplate) '# Create a Crystal connection object and give it the database details and credentials With crConnectionInfo .ServerName = databaseConnectionDetails.Server .DatabaseName = databaseConnectionDetails.Database .UserID = databaseConnectionDetails.UserID .Password = databaseConnectionDetails.Password End With '# For each table in the report, apply the same database settings. For Each CrTable As CrystalDecisions.CrystalReports.Engine.Table In crReportDocument.Database.Tables crTableLogonInfo = CrTable.LogOnInfo crTableLogonInfo.ConnectionInfo = crConnectionInfo CrTable.ApplyLogOnInfo(crTableLogonInfo) Next '# If the report has any parameters defined, loop through them. crParameterFieldDefinitions = crReportDocument.DataDefinition.ParameterFields For Counter As Integer = 0 To crParameterFieldDefinitions.Count - 1 Dim FoundIt As Boolean = False Dim CrystalParameterName As String = crParameterFieldDefinitions.Item(Counter).Name crParameterFieldLocation = crParameterFieldDefinitions.Item(CrystalParameterName) crParameterValues = crParameterFieldLocation.CurrentValues crParameterDiscreteValue = New CrystalDecisions.Shared.ParameterDiscreteValue '# For each parameter in the report, check the parameters we passed in to see if there's a matching one. If Not parameters Is Nothing Then For Each ParameterName As String In parameters.Keys '# If there is a matching one, apply it and note that we've found it. If ParameterName = CrystalParameterName Then FoundIt = True If crParameterFieldLocation.ValueType = FieldValueType.StringField AndAlso IsDate(parameters(ParameterName)) Then crParameterDiscreteValue.Value = CType(parameters(ParameterName), Date).ToString("dd-MMMM-yyyy HH:mm:ss") Else crParameterDiscreteValue.Value = parameters(ParameterName) End If End If Next ParameterName End If '# If we haven't found it, it must be optional. Cystal will still require a value, so give a dummy one. If Not FoundIt Then Select Case crParameterFieldLocation.ValueType '# Only tested on string fields (even though it's supposed to be a date), so can't guarantee '# that the DBNull will work for other data types. Case FieldValueType.StringField crParameterDiscreteValue.Value = "" Case Else crParameterDiscreteValue.Value = DBNull.Value End Select End If '# Add the value we chose into the parameter. crParameterValues.Add(crParameterDiscreteValue) crParameterFieldLocation.ApplyCurrentValues(crParameterValues) Next Counter '# Run the report and export it to the specified location in the required format. Dim Extension As String If Not reportArchive.LastIndexOf(".") = -1 Then Extension = reportArchive.Substring(reportArchive.LastIndexOf("."), reportArchive.Length - reportArchive.LastIndexOf(".")) Else Extension = ".PDF" End If Select Case Extension.ToUpper Case ".XLS", ".XLSX" crReportDocument.ExportToDisk(ExportFormatType.Excel, reportArchive) Case ".RTF" crReportDocument.ExportToDisk(ExportFormatType.RichText, reportArchive) Case ".DOC", ".DOCX" crReportDocument.ExportToDisk(ExportFormatType.WordForWindows, reportArchive) Case ".RPT" crReportDocument.ExportToDisk(ExportFormatType.WordForWindows, reportArchive) Case ".PDF" crReportDocument.ExportToDisk(ExportFormatType.PortableDocFormat, reportArchive) Case Else crReportDocument.ExportToDisk(ExportFormatType.PortableDocFormat, reportArchive) End Select crReportDocument = Nothing Return True Catch ex As Exception WriteLog(ex) Return False End Try End Function
Obviously I could rewrite it to add an extra property for the DSN, but I'd rather not have to create a DSN for each data connection if it's not required. So, I figured I might go completely overboard and rewrite the entire thing in VS2010 (which I'll need to do in the near future anyway) and use the reporting tools from that. I know that the connection string for that doesn't require a DSN, but does anyone know if I can do a similar thing to what I've done here: create the report without a viewer or Dataset object, and just export it, having passed in the connection info and entered it manually.
Any advice would be gratefully received.![]()


Reply With Quote