向报表添加参数时Crystal Reports未选择任何记录

时间:2015-05-14 22:51:04

标签: c# asp.net crystal-reports

我在Visual Studio 2010中使用Crystal Reports与ASP.NET。

我有一个从数据库中提取数据的DataSet,它似乎很好地加载到报告中。当我在浏览器中查看报告时,所有记录都正确加载。

我必须添加一个参数供用户输入,以便过滤掉报表中的条目。问题是,当我添加任何类型的参数到报表时,查看器无法找到任何记录。这是之前我对选择向导做了任何事情。

我添加了一个下拉列表参数,其中只包含数字1,2和3.如果选择专家中没有任何内容,则不应影响任何内容。但无论出于何种原因,当报告中没有任何记录被选中时。一旦删除参数,它就会再次起作用。

如果这会产生影响,我会通过字段资源管理器添加参数及其值。

奇怪的是,当报表直接从数据库中提取数据时,实现是有效的,而不是先创建DataSet。我无法使用此实现的原因是它一直在询问数据库登录信息。即使我预先定义了信息。我切换到DataSet,所以我会避免登录提示。

我认为我的DataSet实现存在问题。相关代码在这里:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;


public partial class reportPage : System.Web.UI.Page
{

    private ReportDocument rpt;
    private string mapPath;

    protected void Page_Load(object sender, EventArgs e)
    {

        if (!Page.IsPostBack) // If the page is loaded for the first time
        {

            mapPath = "CrystalReport1.rpt";
            ConfigureCrystalReport();

        }

    }

    private void ConfigureCrystalReport() // Creates the instance of the report file and binds it to the viewer on the page
    {

        myDataSet ds = new myDataSet();

        myDataSetTableAdapters.myTableTableAdapter dsTA = new myDataSetTableAdapters.myTableTableAdapter();
        dsTA.Fill(ds.myTable);

        // Initializing the report file
        rpt = new ReportDocument();
        string reportPath = Server.MapPath(mapPath);
        rpt.Load(reportPath);

        DataTable dt = ds.myTable;
        Response.Write("<script>alert('Table has "+ dt.Rows.Count.ToString() +" rows');</script>");
        rpt.SetDataSource(dt); 

        // Binding the report file to the report viewer on the page
        CrystalReportViewer1.ReportSource = rpt;
        CrystalReportViewer1.ToolPanelView = CrystalDecisions.Web.ToolPanelViewType.ParameterPanel;
        CrystalReportViewer1.HasToggleGroupTreeButton = false;

    }

response.write会在页面上弹出一个警告,指出要发送到报表的表中有多少行。它正确计算,所以我知道数据被发送到报告,但它没有选择任何一个。

老实说,我不知道为什么它没有选择任何东西。

编辑:经过一些快速测试后,看起来我可以将参数添加到列表而不会破坏报告。当我将实际的参数元素放在页面上时,或当我将它作为选择专家的一部分使用时,报表无法加载行。

换句话说,只有在报告没有显示参数提示时,报告才有效。

编辑2 :我尝试更改我的DataSet代码,以使其实际连接到数据库。我以为我正在使用DataSet来避免这种情况......但我在教程视频中看到了它。

代码在这里:

        string sConnectionString;
        sConnectionString = "Password=mYp@ssw0rd*;User ID=sa;" + "Initial Catalog=databaseName;" + "Data Source=serverName";
        SqlConnection conn = new SqlConnection(sConnectionString);
        conn.Open();
        SqlDataAdapter sDA = new SqlDataAdapter("Select * from myTable", conn);
        conn.Close();

        myDataSet ds = new myDataSet();

        sDA.Fill(ds, "myTable");
        // Initializing the report file
        rpt = new ReportDocument();
        string reportPath = Server.MapPath(mapPath);
        rpt.Load(reportPath);

        rpt.SetDataSource(ds);

毕竟:没有。如果没有参数可用,它仍会加载表中的所有数据。只要我添加一个参数(到页面,或作为选择专家的一部分),就不会加载任何记录。

编辑3 :我已尝试以编程方式传递参数:

rpt.SetParameterValue("par1", 1);

有趣的是,确实加载了DataSet中的所有数据......直到我向它传递了一个新参数。然后,即使我将参数设置回1,也没有加载任何记录。看起来,一旦查看者必须处理参数,它就会删除所有记录。

我真的不知道现在在哪里看。据我所知,这是rpt.SetDataSource()或CrystalReportsViewer1.ReportSource = rpt的问题。

编辑4 :正如user4663200所指出的那样,当页面被回发时,mapPath为空。我尝试修复它,但遇到了一个新的错误,弹出窗口出现并说“请等待文档处理。”#39;永远。我查看了这个错误,多个消息来源告诉我将加载代码从Page_Load()转移到Page_Init()。

重要的一点是,当用户输入参数后>页面回发时,会以某种方式导致此错误。显然,如果页面没有回发,页面就会很好。

我尝试在Page_Init中实现我的代码的更简单版本,但它不起作用,仍有无限的加载弹出窗口。

这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;  



private ReportDocument rpt;
private myDataSet ds;

protected void Page_Init(object sender, EventArgs e)
    {

        if (!Page.IsPostBack)
        {

            ds = new myDataSet();


            myDataSetTableAdapters.myTableTableAdapter dsTA = new myDataSetTableAdapters.myTableTableAdapter();

            dsTA.Fill(ds.myTable);
            // Initializing the report file
            rpt = new ReportDocument();
            string reportPath = Server.MapPath("myReport.rpt");
            rpt.Load(reportPath);
            Session.Add("dataSet", ds);
            Session["dataSet"] = ds;

            rpt.SetDataSource(ds);

            CrystalReportViewer1.ReportSource = rpt;

        }
        else
        {

            ds = (myDataSet)Session["Report"];
            rpt = new ReportDocument();
            string reportPath = Server.MapPath("myReport.rpt");
            rpt.Load(reportPath);
            rpt.SetDataSource(ds);
            CrystalReportViewer1.ReportSource = rpt;

        }

    }

问题在于其他解决方案要求将REPORT保存在会话中,但为了实现这一点,需要将Sessionstate设置为&#34; InProc&#34;模式。我不能把这个网站从&#34; StateServer&#34;模式。我尝试通过在会话中保存DataSet,然后每次将其绑定到新报表来解决方法。但这也没有用。

编辑4.5 我刚尝试将sessionState更改为InProc,但这仍然无法正常工作。即使我这样做,报告也会在会话中被保存。

编辑4.75 我尝试在Page_Init()中添加一个断点,它揭示了一些有趣的东西。

我可以看到会话[&#34;报告&#34;];在初始运行代码时正确保存。

但是在输入参数后我再次看了Page_Init(),当它尝试做rpt =(ReportDocument)Session [&#34; Report&#34;];会话[&#34;报告&#34;]中的所有内容均为空。它抛出了许多空异常,但这些仅在断点调试器中可见,它们似乎在正常运行期间似乎没有出现。我很确定这就是为什么它会在回帖后永远加载。

现在的问题是,输入参数后回发会导致会话中的所有数据丢失。

编辑4.825 :您可以忽略之前的修改。我注释掉了这段代码:

    protected void Page_UnLoad(object sender, EventArgs e)
    {
        try
        {
            rpt.Close();
            rpt.Dispose();
        }
        catch { }
    }

在删除此代码后,我再次查看了Session [&#34; Report&#34;]变量,它不再为null。

有趣的是,即使进入参数条目,也会调用Page_UnLoad BEFORE。如果是rpt.Close();正在转储对rpt的所有引用,然后就好像Session变量就像一个指针一样,而不是存储一个实际的rpt对象。因此,当rpt为Disposed()时,Session [&#34; Report&#34;]似乎只是一个空指针。

所以现在它正确的东西被传递......它仍然有无限的文件处理&#39;屏幕。

编辑5 :我终于开始工作了。

事实证明会话是解决方案,但我找不到任何好的实现。

我从here获得了大部分相关代码。但你不能只复制并粘贴它。

这是我的实施

    private ReportDocument rpt;
    private myDataSet ds;

    protected void Page_Init(object sender, EventArgs e)
    {

        if (!IsPostBack)
        {

            Session["Report"] = null;

        }

        if (Session["Report"] == null)
        {

            ds = new myDataSet();
            myDataSetTableAdapters.myTableTableAdapter dsTA = new myDataSetTableAdapters.myTableTableAdapter();
            DataTable dt = dsTA.GetData();

            rpt = new ReportDocument();
            rpt.Load(Server.MapPath("myReport.rpt"));
            rpt.SetDataSource(dt);
            Session.Add("Report", rpt);
            CrystalReportViewer1.ReportSource = rpt;
            CrystalReportViewer1.ToolPanelView = CrystalDecisions.Web.ToolPanelViewType.ParameterPanel;
            CrystalReportViewer1.HasToggleGroupTreeButton = false;

        }

    }

    protected void Page_Load(object sender, EventArgs e)
    {

        if (Page.IsPostBack)

        {

            rpt = (ReportDocument)Session["Report"];
            CrystalReportViewer1.ReportSource = rpt;
            CrystalReportViewer1.ToolPanelView = CrystalDecisions.Web.ToolPanelViewType.ParameterPanel;
            CrystalReportViewer1.HasToggleGroupTreeButton = false;

        }

    }

    protected void butReport_Click(object sender, EventArgs e)
    {

        if (Session["Report"] == null) // Report is not in session (previously loaded) so load report, set params, view and place in session
        {

            ds = new myDataSet();
            myDataSetTableAdapters.myTableTableAdapter dsTA = new myDataSetTableAdapters.myTableTableAdapter();
            DataTable dt = dsTA.GetData();

            rpt = new ReportDocument();
            rpt.Load(Server.MapPath("myReport.rpt"));
            rpt.SetDataSource(dt);
            Session.Add("Report", rpt);
            CrystalReportViewer1.ReportSource = rpt;
            CrystalReportViewer1.ToolPanelView = CrystalDecisions.Web.ToolPanelViewType.ParameterPanel;
            CrystalReportViewer1.HasToggleGroupTreeButton = false;

        }
        else
        {

            rpt = (ReportDocument)Session["Report"];
            CrystalReportViewer1.ReportSource = rpt;
            CrystalReportViewer1.ToolPanelView = CrystalDecisions.Web.ToolPanelViewType.ParameterPanel;
            CrystalReportViewer1.HasToggleGroupTreeButton = false;

        }

    }

最重要的区别是这一行:DataTable dt = dsTA.GetData(); 在我将整个DataSet传递给rpt之前。我不确定原因,但使用GetData()结果创建新的DataTable可让报告保持在会话中。

现在我的报告即使在所有回发中都会保持在会话中。我遇到并解决了一些其他问题,例如当用户离开页面并返回时会话未重置。

2 个答案:

答案 0 :(得分:0)

您的SQL查询缺少where子句,因此无论您为参数添加什么内容,它都将始终返回所有记录。可能后续调用失败的原因是你的mapPath是空白的,你在每个Page_Load上创建它,但只有在它不是回发时才设置它。这意味着在初始页面加载后,mapPath为null,因此没有报告可以提取。

答案 1 :(得分:0)

解决。有关说明,请参见第5步。