Good Afternoon All,
我花了大量时间在过去两周内寻找有关我使用C#WinForm应用程序的问题的帮助。
我有一个表单,其中有一个DataGridView显示从数据库中提取的详细信息。当用户双击此网格中的一行时,代码会从CustomerID列中获取值,将其放入静态公共字符串,然后打开另一个具有reportviewer的表单。
我尝试做的是让报表查看器使用CustomerID作为参数来运行报表。
到目前为止,我所做的就是让它说明尚未指定报告定义。
我的SQL服务器是一台没有SSRS的旧服务器,由于更改请求问题,我无法安装它,因此我不得不使用本地报告,而不是服务器报告。< / p>
我创建报告的方式是在Visual Studio中转到我的解决方案资源管理器,然后转到添加 - 新项目 - 报告,然后我给出了数据集和参数。我将报告放在一个名为Reports的子文件夹中,该子文件夹位于我所有表单旁边的解决方案中。
我的reportviewer表单的代码如下。不要笑太多,我100%自学。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.Data.SqlClient;
namespace FormsApp
{
public partial class ReportGenerator : Form
{
public ReportGenerator()
{
InitializeComponent();
this.reportViewer1.RefreshReport();
}
private void ReportGenerator_Load(object sender, EventArgs e)
{
if (CustomerList.CustomerID!= "")
{
this.reportViewer1.ProcessingMode = ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = "\\Reports\\CustomerDetails.rdlc";
this.reportViewer1.ShowParameterPrompts = true;
ReportParameter CustID = new ReportParameter("CustomerID",CustomerList.CustomerID);
this.reportViewer1.LocalReport.SetParameters(CustID);
}
else
{}
}
}
}
我是否正确使用LocalReport?我真的很难过,这是我需要工作的最后一点,然后我的申请就完成了。
非常感谢任何帮助。
非常感谢
更新
我的代码现在显示如下来自各种来源的建议。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.Data.SqlClient;
namespace FormsApp
{
public partial class ReportGenerator : Form
{
public ReportGenerator()
{
InitializeComponent();
this.reportViewer1.RefreshReport();
}
private DataTable getCustomerData()
{
SqlConnection con = new SqlConnection(Home.ConString);
DataSet ds = new DataSet();
ds.DataSetName = "CustomerListRetrieve";
string sql = "SELECT * FROM Customers";
SqlDataAdapter da = new SqlDataAdapter(sql, con);
da.Fill(ds);
DataTable dt = ds.Tables[0];
return dt;
}
private void ReportGenerator_Load(object sender, EventArgs e)
{
if (CustomerList.CustomerID != "")
{
this.reportViewer1.Reset();
this.reportViewer1.LocalReport.ReportEmbeddedResource = "FormsApp.Reports.CustomerDetails.rdlc";
ReportDataSource rds = new ReportDataSource("CustomerListRetrieve", getCustomerData());
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(rds);
ReportParameter CustID= new ReportParameter("CustomerID", CustomerList.CustomerID);
this.reportViewer1.LocalReport.SetParameters(CustID);
this.reportViewer1.LocalReport.Refresh();
ViewButtonClicked();
}
else
{
}
}
private void ViewButtonClicked(object sender, ReportParametersEventArgs e)
{
var SubmittedParameters = e.Parameters.Clone();
e.Parameters.Clear();
SubmittedParameters.Where(x => x.Name == "Parametername").FirstOrDefault().Values[0] = "YourValue";
SubmittedParameters.ToList().ForEach(x => e.Parameters.Add(x));
}
private void OnReportChosenFromList()
{
reportViewer1.SubmittingParameterValues -= ViewButtonClicked;
reportViewer1.SubmittingParameterValues += ViewButtonClicked;
}
}
}
我在codingbiz的回复后添加的数据源代码。添加此内容后,我不再收到报表定义错误,只是在加载reportviewer时出现空白窗口。
根据伯纳德沃尔特斯的建议,最后两个方法 - ViewButtonClicked和OnReportChosenFromList被添加。添加后我得到2个错误说明:
现在真的很难过。可能错误地实施了这些建议。
答案 0 :(得分:0)
我遇到了同样的问题,这是修复:
private void ViewButtonClicked(object sender, ReportParametersEventArgs e)
{
var SubmittedParameters = e.Parameters.Clone();
e.Parameters.Clear();
SubmittedParameters.Where(x => x.Name == "Parametername").FirstOrDefault().Values[0] = "YourValue";
SubmittedParameters.ToList().ForEach(x => e.Parameters.Add(x));
}
private void OnReportChosenFromList()
{
reportViewer.SubmittingParameterValues -= ViewButtonClicked;
reportViewer.SubmittingParameterValues += ViewButtonClicked;
}
这一行:
reportViewer.SubmittingParameterValues += ViewButtonClicked;
在报表查看器上设置一个侦听器,在触发事件时执行ViewButtonClicked
。
ViewButtonClicked
然后拦截包含发送到SSRS的所有参数数据的消息,这允许您复制其数据,编辑它,然后在将消息发送到SSRS之前再次添加数据。 / p>
注意:已对此进行了一些编辑,但大部分都是直接从我的代码中复制的
答案 1 :(得分:0)
在您拥有reportViewer1.RefreshReport()之前,reportViewer不会执行操作;这是它在本地或远程运行报告的命令。 每次您要报告刷新或最初加载时,您都需要此命令。
答案 2 :(得分:0)
我已经编写了整个包装类用于报告,可以帮助/提供其中的一部分,但是可以稍后再使用/聊天/发送电子邮件。
对于此问题,您没有在报表实际运行的任何地方提供报表数据源。您有一个针对数据库的查询,该查询返回的数据集很好,但是没有明确地与报表绑定。所以,让我开始这样。
进行查询并调用FILL()时,可以填充单个DataTable而不是DataSet。 DataSet的优点是您可以将多个表传递给报表,并具有更多的父/子报表...,甚至可以有一个附加表仅包含一条记录而没有标题,标题,消息等内容希望报表中的其他位置与在每个表的每一行进行复制始终是一回事。现在,让我们只使用一个DataTable
private void generateReport()
{
var rptDT = getCustomerData();
// dont know how you are preparing the load of your report...
var yourRpt = YourReportViewer.LocalReport.LoadReportDefinition( whateverYourReport );
// Now, add the data source to it. THIS is what populates the report with the data
// as a result of your query, pull down, assign table name for context in the report.
// You are telling the local report, here is the datasource, and by the way, the named
// reference of the table is whatever you set for the table name... and finally, this
// datatable object IS the content for the report.
YourReportViewer.LocalReport.DataSources.Add(
new ReportDataSource( rptDT.TableName, rptDT ) );
}
private DataTable getCustomerData()
{
SqlConnection con = new SqlConnection(Home.ConString);
// slightly altered using just a datatable
DataTable dt = new DataTable();
string sql = "SELECT * FROM Customers";
SqlDataAdapter da = new SqlDataAdapter(sql, con);
da.Fill(dt);
dt.TableName = "CustomerList";
return dt;
}
同样,我可以提供更多,但仅此一个问题可能就太多了,因为您可能会有/想要更多的来回问题。