【问题标题】:C# ReportViewer Local Report with ParameterC# ReportViewer 带参数的本地报表
【发布时间】:2017-07-19 14:23:51
【问题描述】:

大家下午好,

在过去 2 周的大部分时间里,我一直在寻找有关我在使用 C# WinForm 应用程序时遇到的问题的帮助。

我有一个表单,它有一个显示从数据库中提取的详细信息的 DataGridView。当用户双击此网格中的一行时,代码会从 CustomerID 列中获取值,将其放入静态公共字符串中,然后打开另一个具有报表查看器的表单。

然后我要做的是让reportviewer 使用CustomerID 作为参数来运行报告。

到目前为止,我所做的只是让它声明尚未指定报告定义。

我的 SQL 服务器是一个没有 SSRS 的旧服务器,由于更改请求问题我无法安装它,所以我不得不使用本地报告,而不是服务器报告。

我创建报告的方式是转到 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时出现一个空白窗口。

根据 Bernard Walters 的建议,添加了底部的两个方法 - ViewButtonClicked 和 OnReportChosenFromList。添加此内容后,我收到 2 个错误说明:

  1. 错误 1 ​​只有赋值、调用、递增、递减、等待和新对象表达式可以用作语句。
  2. Microsoft.Reporting.WinForms.ReportParameterCollection 不包含“克隆”的定义,也没有扩展方法“克隆”...

现在真的很难过。可能是错误地执行了建议。

【问题讨论】:

  • 我认为报表查看器缺少数据源
  • 您好,感谢您的回复。即使报表本身有数据源和数据集,报表是否需要它自己的数据源?
  • 是的,根据我的经验。您在报告中指定的那个用作预期的模板。您需要提供的实际数据
  • @TomCamish 你搞定了吗?

标签: c# winforms parameters reportviewer localreport


【解决方案1】:

我也遇到了同样的问题,解决方法如下:

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 的reportviewer 上设置一个侦听器。

ViewButtonClicked 然后截获包含正在发送到 SSRS 的所有参数数据的消息,这允许您复制其数据,编辑它,然后在消息发送到 SSRS 之前再次添加数据。

注意:这已经被编辑了一点,但大部分是直接从我的代码中复制出来的

【讨论】:

  • reportviewer 的工作方式几乎不可能更改您看到的值,但您肯定可以更改 SSRS 看到的值 ;)
  • 感谢您的回复。我不确定如何将您的代码添加到我的代码中。 ViewButtonClicked 方法中的代码可以添加到我的 ReportGenerator_Load 方法中吗?谢谢,
  • @TomCamish 是的,我会将其添加到您更改/查看报告时实例化的方法中。请注意,您必须同时保留 -= 和 +=...如果没有它们,您将创建多个事件处理程序,并且每次查看新报告时都会导致 int then 方法执行 +1 次。
  • 我尝试添加它并收到错误“System.EventArgs 不包含参数的定义”。很抱歉这有点慢(自学) - 我怎样才能在我的代码中实现它?
  • 你在使用事件 ReportParametersEventArgs 吗?
【解决方案2】:

reportViewer 在你有 reportViewer1.RefreshReport() 之前不会行动;这是它在本地或远程运行报告的命令。 每次您希望报表刷新或初始加载时,您都需要此命令。

【讨论】:

    【解决方案3】:

    我已经为报告编写了一个完整的包装类,可以帮助/提供部分内容,但可以稍后/聊天/发送电子邮件。

    至于问题,您没有在报告实际运行的任何地方提供报告数据源。您有一个针对您的数据库的查询,它返回一个很好的数据集,但它没有明确地与报告相关联。所以,让我这样开始吧。

    在执行查询并调用 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;
    }
    

    同样,我可以提供更多,但仅此一个问题就太过分了,因为您可能会有/想要更多的前后问题。

    【讨论】:

      猜你喜欢
      • 2013-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多