Logging Onto Sub Reports
Here is the email from Wolfgang on the now defunct ngfx-crystal mailing list from aspfriends, where he explained how he accomplished logging into multiple sub reports. The code for this is as an example only. Please use this as a starting point, not as a solution.
From: Wolfgang Baeck
Sent: Wednesday, November 06, 2002 8:21 AM
To: ngfx-crystal
Subject: [ngfx-crystal] Discoveries on Logging on for Crystal
Report Hi Guys, Well, I finally managed to get my report which includes 4 subreports going. I never thought that CR would embedd so much information at design time into the report.
1. If you create your report and use at design time an ODBC (RDO) connection, you MUST use the same connection at runtime.
2. If you decide that at design time you are using the ODBC connection with a trusted connection, you MUST use a trusted connection at runtime too. You can not supply userid and password for that connection once it was built with the trusted connection option.
3. If you use an ODBC connection, then you MUST specify as the server name in the section:
1:
2: crConnectionInfo = new ConnectionInfo();
3: crConnectionInfo.ServerName = "DSN Name of ODBC Connection";
4: crConnectionInfo.DatabaseName = "HopeAndHome";
5: crConnectionInfo.UserID = "sa";
6: crConnectionInfo.Password = "password";
the name of the Data Set Name, not the server name.
4. If you want to use a simpler logon (not the new SetDatabaseLogon()) but the logon where all reports use the same connection info, you MUST create all reports and subreports with the same connection info.
5. If you use an OLEDB Connection (ADO), then use the server name in the connection info.
6. If you have logon problems on a report with subreports, I suggest using the method that I provide later on to run each individual subreport by itself trying to figure out which of them creates the logon problem since the logon exception can not be intercepted. The message: "Unhandled exception..." is useless since one can't handle it, at least I didn't find how to. I wished CR would at least give you the name of the report that failed to logon in case you have more than one subreport.
7. If you are still not tired of the CR issues, here is the code that I use for reports with subreports:
1:
2: override protected void OnInit(EventArgs e) {
3:
4: InitializeComponent();
5: CrystalReportViewer1.ReportSource = this.prepareReport();
6: base.OnInit(e); }
7:
8: private ReportDocument prepareReport() {
9: Sections crSections;
10: ReportDocument crReportDocument, crSubreportDocument;
11: SubreportObject crSubreportObject;
12: ReportObjects crReportObjects;
13: ConnectionInfo crConnectionInfo;
14: Database crDatabase;
15: Tables crTables;
16: TableLogOnInfo crTableLogOnInfo;
17: crReportDocument = new ReportDocument();
18: crReportDocument.Load("c:\\reports\\Homes.rpt",CrystalDecisions.Shared.OpenReportMethod.OpenReportByTempCopy);
19: crDatabase = crReportDocument.Database;
20: crTables = crDatabase.Tables;
21: crConnectionInfo = new ConnectionInfo();
22: crConnectionInfo.ServerName = "DSNName Or Server Name";
23: crConnectionInfo.DatabaseName = "HopeAndHome";
24: crConnectionInfo.UserID = "sa";
25: crConnectionInfo.Password = "password";
26: foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables) {
27: crTableLogOnInfo = aTable.LogOnInfo;
28: crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
29: aTable.ApplyLogOnInfo(crTableLogOnInfo); }
30:
31:
32: crSections = crReportDocument.ReportDefinition.Sections;
33:
34: foreach (Section crSection in crSections) {
35: crReportObjects = crSection.ReportObjects;
36:
37: foreach (ReportObject crReportObject in crReportObjects) {
38: if (crReportObject.Kind == ReportObjectKind.SubreportObject) {
39: crSubreportObject = (SubreportObject) crReportObject;
40:
41: crSubreportDocument = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName);
42: crDatabase = crSubreportDocument.Database;
43: crTables = crDatabase.Tables;
44: foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables) {
45: crTableLogOnInfo = aTable.LogOnInfo;
46: crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
47: aTable.ApplyLogOnInfo(crTableLogOnInfo);
48: }
49: }
50: }
51: }
52: return crReportDocument;
53: }
This section is simpler if you don't have subreports, but again, in my opinion you should not care whether the report has subreports or not because you may change that one day, so I suggest the involved logon for all reports because your report writer which may not be you may change the composition of a report one day.
1: private ReportDocument prepareReport() {
2: ReportDocument crReportDocument;
3: ConnectionInfo crConnectionInfo;
4: Database crDatabase;
5: Tables crTables;
6: TableLogOnInfo crTableLogOnInfo;
7: crReportDocument = new ReportDocument();
8: crReportDocument.Load("c:\\reports\\SomeReport.rpt",CrystalDecisions.Shared.OpenReportMethod.OpenReportByTempCopy);
9: crDatabase = crReportDocument.Database;
10: crTables = crDatabase.Tables;
11: crConnectionInfo = new ConnectionInfo();
12: crConnectionInfo.ServerName = "DSN Or Server";
13: crConnectionInfo.DatabaseName = "HopeAndHome";
14: crConnectionInfo.UserID = "sa";
15: crConnectionInfo.Password = "password";
16: foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables) {
17: crTableLogOnInfo = aTable.LogOnInfo;
18: crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
19: aTable.ApplyLogOnInfo(crTableLogOnInfo);
20: }
21: return
22: crReportDocument;
23: }
Crystal Resources
Crystal Alliance