Programmatically Change a Crystal Reports datasource location
I used crystal to do the heavy lifting of geneating the pdf for me.
But as I needed to deploy it to multiple databases/clients I needed a way of programmatically changing the datasource location of the report. So with a bit of help from the crystal knowledgebase here is the code I use.
There is a lot of debugging information in here and trust me when it fails you need it.
The .dbo of the location reference obviously means I was working with sql server.
1 2 ' -------------------------------------------------------------------------- 3 ' SetupReport 4 ' 5 ' Description: 6 ' sets up the crystal report 7 ' 8 ' Arguments: 9 ' objCrystalReportDocument - crystal report document object 10 ' 11 ' Dependencies: 12 ' GetConnnectionInfo 13 ' CrystalDescisions 14 ' 15 ' History: 16 ' 03/17/2006 - WSR : created 17 ' 18 Private Function SetupReport(ByRef objCrystalReportDocument As CrystalDecisions.CrystalReports.Engine.ReportDocument) As System.Boolean 19 20 ' a heck of a lot of objects used 21 Dim crParameterDiscreteValue As CrystalDecisions.Shared.ParameterDiscreteValue 22 Dim crParameterFieldDefinitions As CrystalDecisions.CrystalReports.Engine.ParameterFieldDefinitions 23 Dim crParameterFieldLocation As CrystalDecisions.CrystalReports.Engine.ParameterFieldDefinition 24 Dim crParameterValues As CrystalDecisions.Shared.ParameterValues 25 Dim crSections As CrystalDecisions.CrystalReports.Engine.Sections 26 Dim crSection As CrystalDecisions.CrystalReports.Engine.Section 27 Dim crReportObjects As CrystalDecisions.CrystalReports.Engine.ReportObjects 28 Dim crReportObject As CrystalDecisions.CrystalReports.Engine.ReportObject 29 Dim crSubreportDocument As CrystalDecisions.CrystalReports.Engine.ReportDocument 30 Dim crSubreportObject As CrystalDecisions.CrystalReports.Engine.SubreportObject 31 Dim crConnectionInfo As CrystalDecisions.Shared.ConnectionInfo 32 Dim crDatabase As CrystalDecisions.CrystalReports.Engine.Database 33 Dim crTables As CrystalDecisions.CrystalReports.Engine.Tables 34 Dim aTable As CrystalDecisions.CrystalReports.Engine.Table 35 Dim bTable As CrystalDecisions.CrystalReports.Engine.Table 36 Dim crTableLogOnInfo As CrystalDecisions.Shared.TableLogOnInfo 37 Dim blnTest As System.Boolean 38 Dim strLocation As System.String 39 Dim blnErrors As System.Boolean 40 41 ' instantiate the debug page 42 m_strDebugPage = New System.Text.StringBuilder(4096) 43 blnErrors = False 44 45 crConnectionInfo = GetConnectionInfo() 46 47 crDatabase = objCrystalReportDocument.Database 48 49 crTables = crDatabase.Tables 50 51 'For intCounter = 0 To objCrystalReportDocument.Database.Tables.Count - 1 52 For Each aTable In crTables 53 54 crTableLogOnInfo = aTable.LogOnInfo 55 56 OutputDebugLine("BEFORE") 57 OutputDebugLine("TABLE NAME: " & aTable.Name) 58 OutputDebugLine("TABLE LOC: " & aTable.Location) 59 OutputDebugLine("SERVER: " & crTableLogOnInfo.ConnectionInfo.ServerName) 60 OutputDebugLine("DB: " & crTableLogOnInfo.ConnectionInfo.DatabaseName) 61 OutputDebugLine("UID: " & crTableLogOnInfo.ConnectionInfo.UserID) 62 OutputDebugLine("PWD: " & crTableLogOnInfo.ConnectionInfo.Password) 63 OutputDebugLine("RN: " & crTableLogOnInfo.ReportName) 64 OutputDebugLine("TN: " & crTableLogOnInfo.TableName) 65 66 crTableLogOnInfo.ConnectionInfo = crConnectionInfo 67 aTable.ApplyLogOnInfo(crTableLogOnInfo) 68 strLocation = crConnectionInfo.DatabaseName & ".dbo." & aTable.Location.Substring(aTable.Location.LastIndexOf(".") + 1) 69 OutputDebugLine("New Location: " & strLocation) 70 Try 71 aTable.Location = strLocation 72 Catch ex As Exception 73 OutputDebugLine("Set Location Error: " & ex.ToString) 74 blnErrors = True 75 End Try 76 77 OutputDebugLine("AFTER") 78 OutputDebugLine("TABLE NAME: " & aTable.Name) 79 OutputDebugLine("TABLE LOC: " & aTable.Location) 80 OutputDebugLine("SERVER: " & crTableLogOnInfo.ConnectionInfo.ServerName) 81 OutputDebugLine("DB: " & crTableLogOnInfo.ConnectionInfo.DatabaseName) 82 OutputDebugLine("UID: " & crTableLogOnInfo.ConnectionInfo.UserID) 83 OutputDebugLine("PWD: " & crTableLogOnInfo.ConnectionInfo.Password) 84 OutputDebugLine("RN: " & crTableLogOnInfo.ReportName) 85 OutputDebugLine("TN: " & crTableLogOnInfo.TableName) 86 Try 87 blnTest = aTable.TestConnectivity() 88 OutputDebugLine("CONNECTED? " & blnTest.ToString()) 89 Catch ex As Exception 90 OutputDebugLine("CONNECTED? NO") 91 OutputDebugLine(ex.ToString) 92 blnErrors = True 93 End Try 94 95 '// THIS STUFF HERE IS FOR REPORTS HAVING SUBREPORTS 96 '// set the sections object to the current report's section 97 crSections = objCrystalReportDocument.ReportDefinition.Sections 98 99 '// loop through all the sections to find all the report objects 100 For Each crSection In crSections 101 102 crReportObjects = crSection.ReportObjects 103 104 '//loop through all the report objects in there to find all subreports 105 For Each crReportObject In crReportObjects 106 107 If crReportObject.Kind = ReportObjectKind.SubreportObject Then 108 109 crSubreportObject = CType(crReportObject, CrystalDecisions.CrystalReports.Engine.SubreportObject) 110 '//open the subreport object and logon as for the general report 111 crSubreportDocument = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName) 112 crDatabase = crSubreportDocument.Database 113 crTables = crDatabase.Tables 114 115 For Each bTable In crTables 116 117 crTableLogOnInfo = bTable.LogOnInfo 118 119 OutputDebugLine("BEFORE") 120 OutputDebugLine("TABLE NAME: " & bTable.Name) 121 OutputDebugLine("TABLE LOC: " & bTable.Location) 122 OutputDebugLine("SERVER: " & crTableLogOnInfo.ConnectionInfo.ServerName) 123 OutputDebugLine("DB: " & crTableLogOnInfo.ConnectionInfo.DatabaseName) 124 OutputDebugLine("UID: " & crTableLogOnInfo.ConnectionInfo.UserID) 125 OutputDebugLine("PWD: " & crTableLogOnInfo.ConnectionInfo.Password) 126 OutputDebugLine("RN: " & crTableLogOnInfo.ReportName) 127 OutputDebugLine("TN: " & crTableLogOnInfo.TableName) 128 129 crTableLogOnInfo.ConnectionInfo = crConnectionInfo 130 bTable.ApplyLogOnInfo(crTableLogOnInfo) 131 strLocation = crConnectionInfo.DatabaseName & ".dbo." & bTable.Location.Substring(bTable.Location.LastIndexOf(".") + 1) 132 OutputDebugLine("New Location: " & strLocation) 133 Try 134 bTable.Location = strLocation 135 Catch ex As Exception 136 OutputDebugLine("Set Location Error: " & ex.ToString) 137 blnErrors = True 138 End Try 139 140 OutputDebugLine("AFTER") 141 OutputDebugLine("TABLE NAME: " & bTable.Name) 142 OutputDebugLine("TABLE LOC: " & bTable.Location) 143 OutputDebugLine("SERVER: " & crTableLogOnInfo.ConnectionInfo.ServerName) 144 OutputDebugLine("DB: " & crTableLogOnInfo.ConnectionInfo.DatabaseName) 145 OutputDebugLine("UID: " & crTableLogOnInfo.ConnectionInfo.UserID) 146 OutputDebugLine("PWD: " & crTableLogOnInfo.ConnectionInfo.Password) 147 OutputDebugLine("RN: " & crTableLogOnInfo.ReportName) 148 OutputDebugLine("TN: " & crTableLogOnInfo.TableName) 149 Try 150 blnTest = bTable.TestConnectivity() 151 OutputDebugLine("CONNECTED? " & blnTest.ToString()) 152 Catch ex As Exception 153 OutputDebugLine("CONNECTED? NO") 154 OutputDebugLine(ex.ToString) 155 blnErrors = True 156 End Try 157 158 Next bTable 159 160 End If 161 162 Next crReportObject 163 164 Next crSection 165 166 Next aTable 167 168 ' get parameter fields from report 169 crParameterFieldDefinitions = objCrystalReportDocument.DataDefinition.ParameterFields 170 171 ' ' Set the first parameter 172 ' ' - Get the parameter, tell it to use the current values vs default value. 173 ' ' - Tell it the parameter contains 1 discrete value vs multiple values. 174 ' ' - Set the parameter's value. 175 ' ' - Add it and apply it. 176 ' ' - Repeat these statements for each parameter. 177 ' ' 178 crParameterFieldLocation = crParameterFieldDefinitions.Item("@psindex") 179 crParameterValues = crParameterFieldLocation.CurrentValues 180 crParameterDiscreteValue = New CrystalDecisions.Shared.ParameterDiscreteValue 181 crParameterDiscreteValue.Value = m_intReportID 182 crParameterValues.Add(crParameterDiscreteValue) 183 crParameterFieldLocation.ApplyCurrentValues(crParameterValues) 184 185 ' if there were errors 186 If blnErrors Then 187 188 ' display debug page 189 OutputDebugPage() 190 191 End If 192 193 End Function 194 ' -------------------------------------------------------------------------- 195 196 197 ' -------------------------------------------------------------------------- 198 ' GetConnectionInfo 199 ' 200 ' Description: 201 ' retrieves the connection information from the data layer object 202 ' 203 ' Arguments: none 204 ' 205 ' Dependencies: 206 ' DataLayer.GetConnectInfo 207 ' 208 ' History: 209 ' 03/17/2006 - WSR : created 210 ' 211 Private Function GetConnectionInfo() As CrystalDecisions.Shared.ConnectionInfo 212 213 Dim objConnectionInfo As CrystalDecisions.Shared.ConnectionInfo 214 Dim strDSN As System.String 215 Dim strDB As System.String 216 Dim strUID As System.String 217 Dim strPWD As System.String 218 Dim blnTrust As System.Boolean 219 220 ' get connection information from data layer 221 m_objDataLayer.GetConnectInfo(strDSN, strDB, strUID, strPWD, blnTrust) 222 223 ' create new crystal connection info object 224 objConnectionInfo = New CrystalDecisions.Shared.ConnectionInfo 225 226 ' populate it 227 objConnectionInfo.IntegratedSecurity = False 228 objConnectionInfo.ServerName = strDSN 229 objConnectionInfo.UserID = strUID 230 objConnectionInfo.Password = strPWD 231 objConnectionInfo.DatabaseName = strDB 232 233 ' return object 234 GetConnectionInfo = objConnectionInfo 235 236 End Function 237 ' -------------------------------------------------------------------------- 238 239 ' -------------------------------------------------------------------------- 240 ' OutputDebugLine 241 ' 242 ' Description: appends a line to the debug string builder 243 ' 244 ' Arguments: text to add 245 ' 246 ' Dependencies: 247 ' m_strDebugPage 248 ' 249 ' History: 250 ' 03/17/2006 - WSR : created 251 ' 2007.04.25 - WSR : revised to use string builder 252 ' 253 Function OutputDebugLine(ByVal strLine As System.String) As System.Boolean 254 255 m_strDebugPage.Append("<div>" & Server.HtmlEncode(strLine) & "</div>") 256 257 End Function 258 ' -------------------------------------------------------------------------- 259 260 261 ' -------------------------------------------------------------------------- 262 ' OutputDebugPage 263 ' 264 ' Description: sends debug string builder to response 265 ' 266 ' Arguments: none 267 ' 268 ' Dependencies: 269 ' m_strDebugPage 270 ' 271 ' History: 272 ' 2007.04.25 - WSR : created 273 ' 274 Function OutputDebugPage() As System.Boolean 275 276 With Response 277 .ClearHeaders() 278 .ClearContent() 279 .ContentType = "text/html" 280 End With 281 282 Response.Write("<html><head><title>Debug Page</title></head><body>") 283 Response.Write(m_strDebugPage.ToString()) 284 Response.Write("</body></html>") 285 286 Response.Flush() 287 Response.End() 288 289 End Function 290 ' -------------------------------------------------------------------------- 291 292