1

我在 C# 中编写了一个代码,用于 Visual Studio 版本 13.0.5.891 和 Visual Studio 2010 的 Crystal Reports。它基本上接收报告文件的名称和带有要传递给 .rpt 文件的参数的字典并显示在浏览器窗口上生成的报告。它是 ASP.NET MVC 3 应用程序的一部分。

这是代码:

    /// <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);   
        }
    }

当我使用没有子报表的报表或具有从外部接收参数的子报表的报表时,它可以正常工作,但是当我使用带有子报表链接的子报表时,它会抛出异常消息:缺少参数值。

知道我在这里缺少什么吗?任何帮助是极大的赞赏。谢谢!

4

2 回答 2

0

如果您想继续使用 SetParameterValue ,只需使用它

reportDocument.SetParameterValue(string name,object value,string subreportname)

将值传递给子报表中的指定参数。

希望帮助

于 2013-07-17T22:45:35.423 回答
0

在更高级别的细节上,我的情况与您不同,但我也一直在以编程方式分配参数。不过,我没有使用过 SetParameterValue 方法。

相反,我遍历数据定义中的参数集合:

int intNumParameters = reportDoc.ParameterFields.Count;

for(int i = 0; i < intNumParameters; i++)
{
    if(!reportDoc.DataDefinition.ParameterFields[i].IsLinked())
    {
        ParameterValues pVals = new ParameterValues();
        ParameterDiscreteValue pdv = new ParameterDiscreteValue();
        pdv.Value = objValue;
        pVals.Add(pdv);
        reportDoc.DataDefinition.ParameterFields[i].ApplyCurrentValues(pVals);
    }
}

reportDoc.Export(expOpts);

我想你可能可以做很多内联,但这只是我为自己使用的一个小工具的一部分。我可能应该得到 DataDefinition.ParameterFields 数组而不是 ReportDocument.ParameterFields 数组的长度,但无论如何它都有效。

我不知道这是否会对您有所帮助,因为我有意跳过似乎是您问题根源的链接参数。但我至少可以提供另一种分配参数的方式。我会注意到,我的大多数报告中也有子报告,并且没有注意到处理带有子报告和不处理子报告之间的任何区别。

希望这可以帮助 :)

于 2013-06-28T07:42:06.153 回答