Crystal 当我向报表添加参数时,报表没有选择任何记录
Crystal Reports not selecting any records when I add a parameter to the report
我在 Visual Studio 2010 年内使用 Crystal 报告 ASP.NET。
我有一个从数据库中提取数据的数据集,它似乎可以很好地加载到报表中。当我在浏览器中查看报告时,所有记录都正确加载。
我必须添加一个参数供用户输入,以便过滤掉报告中的条目。问题是,当我 添加 任何类型的参数到报表时,查看器找不到任何记录。这是 BEFORE 我使用选择向导做任何事情。
我添加了一个仅包含数字 1、2 和 3 的下拉列表参数。如果选择专家中没有任何内容,这应该不会有任何影响。但无论出于何种原因,当它出现在报告中时,不会选择任何记录。一旦我删除参数,它就会再次起作用。
我正在通过字段资源管理器添加参数及其值(如果有影响的话)。
奇怪的是,当我让报表直接从数据库中提取数据而不是先创建数据集时,实现工作正常。我不能使用这个实现的原因是它一直在询问数据库登录信息。即使我预先定义了信息。我切换到数据集,这样我就可以避免登录提示。
我认为我的 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 会在页面上弹出一个警告,说明 table 中有多少行被发送到报告。它计数正确,所以我知道数据正在发送到报告,但它没有选择任何数据。
老实说,我不知道为什么它没有选择任何东西。
编辑:经过一些快速测试后,我似乎可以在不破坏报告的情况下将参数添加到列表中。当我将实参元素放在页面上,或者当我将它用作选择专家的一部分时,报告无法加载行。
换句话说,报表只有在不弹出参数提示时才有效。
编辑 2:我尝试更改我的 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);
毕竟:什么都没有。如果没有参数在工作,它仍然会从 table 加载所有数据。只要我添加一个参数(到页面,或作为选择专家的一部分),就没有记录加载。
编辑 3:我试过以编程方式传递参数:
rpt.SetParameterValue("par1", 1);
有趣的是,它确实 加载了DataSet 中的所有数据...直到我向它传递了一个新参数。然后没有记录加载,即使在我将参数设置回 1 之后也是如此。似乎一旦查看器必须处理一个参数,它就会删除所有记录。
我现在真的不知道去哪里看。据我所知,这是 rpt.SetDataSource() 或 CrystalReportsViewer1.ReportSource = rpt.
的问题
编辑 4:正如 user4663200 所指出的,当页面被 post 回退时,mapPath 为空存在一个问题。我尝试修复它,但 运行 变成了一个新错误,弹出窗口显示 'Please wait while the document is being processed.' 永远。我调查了这个错误,多个消息来源告诉我 t运行 将加载代码从 Page_Load().
转移到 Page_Init()
重要的是,当页面 post 在用户输入参数 后返回 时,此错误不知何故会导致。显然,如果没有 post 返回,该页面会正常加载。
我尝试在 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;
}
}
问题是其他解决方案要求将报告保存在 session 中,但要实现这一点,需要将 Sessionstate 设置为 "InProc" 模式。我无法让这个网站脱离 "StateServer" 模式。我尝试了一种变通方法,将 DataSet 保存在 session 中,然后每次都将其绑定到新报告。但这也没有用。
EDIT 4.5 我刚刚尝试将 sessionState 更改为 InProc,但这仍然不起作用。即使我做到了,所以报告就是保存在 session.
中的内容
编辑 4.75 我尝试在 Page_Init() 中放置一个断点,它揭示了一些有趣的事情。
我可以看到 Session["Report"];在初始 运行 期间通过代码正确保存。
但是在输入参数后,我再次观察了 Page_Init(),当它尝试执行 rpt = (ReportDocument)Session["Report"]; Session["Report"] 中的所有内容均为空。它抛出了很多空异常,但这些只在断点调试器中可见,它们似乎从未在正常 运行 期间出现。我很确定这就是为什么它在 post 返回后一直加载的原因
所以现在的问题是post输入参数后返回导致session里面的数据全部丢失
EDIT 4.825:您可以忽略之前的编辑。我注释掉了这段代码:
protected void Page_UnLoad(object sender, EventArgs e)
{
try
{
rpt.Close();
rpt.Dispose();
}
catch { }
}
摆脱这段代码后,我再次查看了 Session["Report"] 变量,它不再为空。
有趣的是,Page_UnLoad 在到达参数条目之前就被调用了。如果rpt.Close();正在转储对 rpt 的所有引用,那么 Session 变量就像一个指针,而不是存储实际的 rpt object。所以当 rpt 是 Disposed() 时,Session["Report"] 看起来只是一个空指针。
所以现在它传递了正确的东西...它仍然有无限 'document processing' 屏幕。
编辑 5:我终于让它工作了。
事实证明 sessions 是解决方案,但我找不到它的任何好的实现。
我的大部分相关代码都来自 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();
在我将整个数据集传递给 rpt 之前。我不确定为什么,但是使用 GetData() 的结果创建一个新的 DataTable 让报告保留在 session.
现在我的报告保存在 session 中,即使有所有 post 支持。我遇到并解决了其他一些问题,例如 session 在用户离开页面并返回时未重置。
您的 SQL 查询缺少 where 子句,因此无论您为参数输入什么,它总是 return 所有记录。后续调用失败的可能原因是您的 mapPath 为空,您在每个 Page_Load 上创建它,但仅在它不是回发时才设置它。这意味着在初始页面加载后,mapPath 为空,因此没有要拉取的报告。
已解决。有关解释,请参阅编辑 5。
我在 Visual Studio 2010 年内使用 Crystal 报告 ASP.NET。
我有一个从数据库中提取数据的数据集,它似乎可以很好地加载到报表中。当我在浏览器中查看报告时,所有记录都正确加载。
我必须添加一个参数供用户输入,以便过滤掉报告中的条目。问题是,当我 添加 任何类型的参数到报表时,查看器找不到任何记录。这是 BEFORE 我使用选择向导做任何事情。
我添加了一个仅包含数字 1、2 和 3 的下拉列表参数。如果选择专家中没有任何内容,这应该不会有任何影响。但无论出于何种原因,当它出现在报告中时,不会选择任何记录。一旦我删除参数,它就会再次起作用。
我正在通过字段资源管理器添加参数及其值(如果有影响的话)。
奇怪的是,当我让报表直接从数据库中提取数据而不是先创建数据集时,实现工作正常。我不能使用这个实现的原因是它一直在询问数据库登录信息。即使我预先定义了信息。我切换到数据集,这样我就可以避免登录提示。
我认为我的 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 会在页面上弹出一个警告,说明 table 中有多少行被发送到报告。它计数正确,所以我知道数据正在发送到报告,但它没有选择任何数据。
老实说,我不知道为什么它没有选择任何东西。
编辑:经过一些快速测试后,我似乎可以在不破坏报告的情况下将参数添加到列表中。当我将实参元素放在页面上,或者当我将它用作选择专家的一部分时,报告无法加载行。
换句话说,报表只有在不弹出参数提示时才有效。
编辑 2:我尝试更改我的 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);
毕竟:什么都没有。如果没有参数在工作,它仍然会从 table 加载所有数据。只要我添加一个参数(到页面,或作为选择专家的一部分),就没有记录加载。
编辑 3:我试过以编程方式传递参数:
rpt.SetParameterValue("par1", 1);
有趣的是,它确实 加载了DataSet 中的所有数据...直到我向它传递了一个新参数。然后没有记录加载,即使在我将参数设置回 1 之后也是如此。似乎一旦查看器必须处理一个参数,它就会删除所有记录。
我现在真的不知道去哪里看。据我所知,这是 rpt.SetDataSource() 或 CrystalReportsViewer1.ReportSource = rpt.
的问题编辑 4:正如 user4663200 所指出的,当页面被 post 回退时,mapPath 为空存在一个问题。我尝试修复它,但 运行 变成了一个新错误,弹出窗口显示 'Please wait while the document is being processed.' 永远。我调查了这个错误,多个消息来源告诉我 t运行 将加载代码从 Page_Load().
转移到 Page_Init()重要的是,当页面 post 在用户输入参数 后返回 时,此错误不知何故会导致。显然,如果没有 post 返回,该页面会正常加载。
我尝试在 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;
}
}
问题是其他解决方案要求将报告保存在 session 中,但要实现这一点,需要将 Sessionstate 设置为 "InProc" 模式。我无法让这个网站脱离 "StateServer" 模式。我尝试了一种变通方法,将 DataSet 保存在 session 中,然后每次都将其绑定到新报告。但这也没有用。
EDIT 4.5 我刚刚尝试将 sessionState 更改为 InProc,但这仍然不起作用。即使我做到了,所以报告就是保存在 session.
中的内容编辑 4.75 我尝试在 Page_Init() 中放置一个断点,它揭示了一些有趣的事情。
我可以看到 Session["Report"];在初始 运行 期间通过代码正确保存。
但是在输入参数后,我再次观察了 Page_Init(),当它尝试执行 rpt = (ReportDocument)Session["Report"]; Session["Report"] 中的所有内容均为空。它抛出了很多空异常,但这些只在断点调试器中可见,它们似乎从未在正常 运行 期间出现。我很确定这就是为什么它在 post 返回后一直加载的原因
所以现在的问题是post输入参数后返回导致session里面的数据全部丢失
EDIT 4.825:您可以忽略之前的编辑。我注释掉了这段代码:
protected void Page_UnLoad(object sender, EventArgs e)
{
try
{
rpt.Close();
rpt.Dispose();
}
catch { }
}
摆脱这段代码后,我再次查看了 Session["Report"] 变量,它不再为空。
有趣的是,Page_UnLoad 在到达参数条目之前就被调用了。如果rpt.Close();正在转储对 rpt 的所有引用,那么 Session 变量就像一个指针,而不是存储实际的 rpt object。所以当 rpt 是 Disposed() 时,Session["Report"] 看起来只是一个空指针。
所以现在它传递了正确的东西...它仍然有无限 'document processing' 屏幕。
编辑 5:我终于让它工作了。
事实证明 sessions 是解决方案,但我找不到它的任何好的实现。
我的大部分相关代码都来自 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(); 在我将整个数据集传递给 rpt 之前。我不确定为什么,但是使用 GetData() 的结果创建一个新的 DataTable 让报告保留在 session.
现在我的报告保存在 session 中,即使有所有 post 支持。我遇到并解决了其他一些问题,例如 session 在用户离开页面并返回时未重置。
您的 SQL 查询缺少 where 子句,因此无论您为参数输入什么,它总是 return 所有记录。后续调用失败的可能原因是您的 mapPath 为空,您在每个 Page_Load 上创建它,但仅在它不是回发时才设置它。这意味着在初始页面加载后,mapPath 为空,因此没有要拉取的报告。
已解决。有关解释,请参阅编辑 5。