4

大家下午好,

在过去 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不包含“克隆”的定义,也没有扩展方法“克隆”...

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

4

3 回答 3

0

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

于 2017-05-30T22:33:50.417 回答
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 之前再次添加数据。

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

于 2017-02-28T15:39:48.863 回答
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;
}

再一次,我可以提供更多,但对于这个问题来说就太多了,因为你可能会有/想要更多的来回问题。

于 2020-10-16T23:35:28.477 回答