Crystal Reports for Visual Studio引发具有子报表链接的“缺少参数值”异常

本文关键字:参数 异常 缺少参数值 链接 报表 Studio Visual for Reports Crystal | 更新日期: 2023-09-27 18:20:05

我用C#编写了一段代码,用于Visual Studio 13.0.5.891版和Visual Studio 2010的Crystal Reports。它基本上接收一个报告文件的名称和一个Dictionary,其中包含要传递到.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);   
        }
    }

当我使用不带子报表的报表,或具有从外部接收参数的子报表时,它可以正常工作,但当我使用带子报表链接的子报表,它会引发异常,并显示消息:缺少参数值。

知道我在这里遗漏了什么吗?非常感谢您的帮助。谢谢

Crystal Reports for Visual Studio引发具有子报表链接的“缺少参数值”异常

我的情况在更高级别的细节上与您不同,但我也一直在以编程方式分配参数。不过,我还没有使用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数组,但它无论如何都能工作。

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

希望这有帮助:)

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

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

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

希望帮助