I made a code in C# to be used with Crystal Reports for Visual Studio, version 13.0.5.891, and Visual Studio 2010. It basically receives the name of a report file and a Dictionary with the parameters to pass to the .rpt file and shows the generated report on browser window. It's part of an ASP.NET MVC 3 application.
Here's the code:
/// <summary>
/// Shows the report
/// </summary>
/// <param name="reportName">Report name</param>
/// <param name="parameters">Dictionary containing the pairs "key/value" of each parameter.</param>
public static void ShowReport(string reportName, Dictionary<string, object> parameters)
{
if (!string.IsNullOrEmpty(reportName))
{
ReportDocument rd = new ReportDocument();
CrystalDecisions.Shared.ConnectionInfo connection = new CrystalDecisions.Shared.ConnectionInfo();
TableLogOnInfo tableLogin = new TableLogOnInfo();
reportName += "_o.rpt"; // all .rpt files we use here have names ending with "_o"
//Find and load the report.
string strRptPath = Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/"), "Reports", reportName);
rd.Load(strRptPath);
//Get the application connection string to build de connection info object
OracleConnectionStringBuilder builder = new OracleConnectionStringBuilder(ConnectionString.providerConnectionString());
CrystalDecisions.ReportAppServer.DataDefModel.Table boTable =
new CrystalDecisions.ReportAppServer.DataDefModel.Table();
//boMainPropertyBag: These hold the attributes of the tables ConnectionInfo object
PropertyBag boMainPropertyBag = new PropertyBag();
//boInnerPropertyBag: These hold the attributes for the QE_LogonProperties
//In the main property bag (boMainPropertyBag)
PropertyBag boInnerPropertyBag = new PropertyBag();
//Set the attributes for the boInnerPropertyBag
boInnerPropertyBag.Add("Server", builder.DataSource);
boInnerPropertyBag.Add("Trusted_Connection", "False");
//Set the attributes for the boMainPropertyBag
boMainPropertyBag.Add("Database DLL", "crdb_oracle.dll");
boMainPropertyBag.Add("QE_DatabaseName", "");
boMainPropertyBag.Add("QE_DatabaseType", "Oracle Server");
//Add the QE_LogonProperties we set in the boInnerPropertyBag Object
boMainPropertyBag.Add("QE_LogonProperties", boInnerPropertyBag);
boMainPropertyBag.Add("QE_ServerDescription", "XE");
boMainPropertyBag.Add("QE_SQLDB", "False");
boMainPropertyBag.Add("SSO Enabled", "False");
//Create a new ConnectionInfo object
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo boConnectionInfo =
new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
//Pass the database properties to a connection info object
boConnectionInfo.Attributes = boMainPropertyBag;
//Set the connection kind
boConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
//**EDIT** Set the User Name and Password if required.
boConnectionInfo.UserName = builder.UserID;
boConnectionInfo.Password = builder.Password;
//Pass the connection information to the table
boTable.ConnectionInfo = boConnectionInfo;
//Get the Database Tables Collection for your report
CrystalDecisions.ReportAppServer.DataDefModel.Tables boTables;
boTables = rd.ReportClientDocument.DatabaseController.Database.Tables;
//For each table in the report:
// - Set the Table Name properties.
// - Set the table location in the report to use the new modified table
int numtable = 0;
foreach (CrystalDecisions.ReportAppServer.DataDefModel.Table table in boTables)
{
boTable.Name = table.Name;
boTable.QualifiedName = builder.UserID + "." + table.Name;
boTable.Alias = table.Name;
rd.ReportClientDocument.DatabaseController.SetTableLocation(boTables[numtable], boTable);
numtable++;
}
//Code for subreports.
CrystalDecisions.ReportAppServer.Controllers.DatabaseController boDatabaseCtl = null;
CrystalDecisions.ReportAppServer.DataDefModel.Database boDatabase = null;
CrystalDecisions.ReportAppServer.ClientDoc.ISCDReportClientDocument boClientDoc = rd.ReportClientDocument;
Strings subreportNames=boClientDoc.SubreportController.GetSubreportNames();
for (int i = 0; i < subreportNames.Count; i++)
{
boDatabaseCtl = boClientDoc.SubreportController.GetSubreport(subreportNames[i]).DatabaseController;
boDatabase = boDatabaseCtl.Database;
boTables = boDatabase.Tables;
numtable = 0;
foreach (CrystalDecisions.ReportAppServer.DataDefModel.Table t in boTables)
{
boTable.Name = t.Name;
boTable.QualifiedName = builder.UserID + "." + t.Name;
boTable.Alias = t.Name;
boDatabaseCtl.SetTableLocation(boTables[numtable], boTable);
numtable++;
}
}
//Verify the database after adding substituting the new table.
//To ensure that the table updates properly when adding Command tables or Stored Procedures.
rd.VerifyDatabase();
//Set the parameters.
foreach (string key in parameters.Keys)
{
object value;
if (parameters.TryGetValue(key, out value))
rd.SetParameterValue(key, value);
}
//Export(show) the report.
rd.ExportToHttpResponse(ExportFormatType.PortableDocFormat, System.Web.HttpContext.Current.Response, false, "crReport");
rd.Close();
rd.Dispose();
}
else
{
// throws an exception saying the .rpt name was not informed
throw new Exception(Idiomas.Atual.NomeRelatórioNãoInformado);
}
}
It works fine when I use a report without subreports, or a report that has subreports which receive parameters from outside, but when I use subreports with subreport links it throws an exception with the message: Missing Parameter Values.
Any idea on what I'm missing here? Any help is greatly appreciated. Thanks!