C# Winform - 如何通过向 ReportViewer 传递 3 个变量(即 Reportname(RDL 文件)、SQLstring 和 Connectionstring)来显示实时报告

标签 c# sql winforms report rdl

将 RDL 文件、SQL 和连接字符串传递给 Winform C# 项目上的 ReportViewer 控件以在运行时显示报表的最优雅的方法是什么。

简介:

  • 我最近开始在 Windows 上创建报告。我发现 RDLC 文件充当静态文件,无需连接 字符串或SQL语句,所以我们需要将DataSource传递给它 命令在运行时用数据填充它。这不利于我们 目的。
  • RDL 文件可以采用 SQL 语句和连接字符串,其中 它们保存在 XML 标签中并用于生成动态报告。

既然我有

  1. RDL 报告模板
  2. SQL 语句
  3. 数据库连接字符串

将此信息传递给 C# Winform 中的 ReportViewer 以生成报告的最佳方法是什么?

1) 对于用于图书馆管理系统的 RDL。 (我们无法控制这些文件,这些文件由我们应用程序的用户使用)。

  <Query>
    <DataSourceName>DS1</DataSourceName>
    <CommandText>select bk_book_details.id, bk_book_details.book_id, bk_book_details.book_no, bk_book_details.book_name, bk_book_details.edition_id, bk_book_details.condition_id, bk_book_details.publication_year, bk_book_details.price, bk_book_details.purchase_price, bk_book_details.reference_no, bk_book_details.book_status, bk_book_details.purchase_id, bk_book_details.purchase_date from bk_book_details</CommandText>
  </Query>

2)这是SQL语句

select bk_book_details.id, bk_book_details.book_id, bk_book_details.book_no, bk_book_details.book_name, bk_book_details.edition_id, bk_book_details.condition_id, bk_book_details.publication_year, bk_book_details.price, bk_book_details.purchase_price, bk_book_details.reference_no, bk_book_details.book_status, bk_book_details.purchase_id, bk_book_details.purchase_date from bk_book_details

3) 这是连接字符串

server=localhost;User Id=root;password=root;Persist Security Info=True;database=lms

当前输出: 如 RDLReader.exe 应用程序中所示

enter image description here

用于获取此输出的代码

    private void btnReport_Click(object sender, EventArgs e) {
        string sql = "select bk_book_details.id, bk_book_details.book_id, bk_book_details.book_no, bk_book_details.book_name, bk_book_details.edition_id, bk_book_details.condition_id, bk_book_details.publication_year, bk_book_details.price, bk_book_details.purchase_price, bk_book_details.reference_no, bk_book_details.book_status, bk_book_details.purchase_id, bk_book_details.purchase_date from bk_book_details";
        string RDLReaderApplication = @"""""""" + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @""\ReaderPath\RDLReader.exe"" + @"""""""";
        string reportFile = @"""""""" + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @""\Reports\ReportFile.RDL"" + @"""""""";
        string connectionString = @"""""""" + "server=localhost;User Id=root;password=root;Persist Security Info=True;database=lms" + @"""""""";
        Process.Start(RDLReaderApplication, reportFile + "" "" + @"""""""" + sql + @"""""""" + "" "" + connectionString);
    }

预期输出:

enter image description here

到目前为止的工作:

表单ReportForm 包含停靠在表单上的ReportViewer 控件。

其他信息:

1) 我希望将 3 个数据发送到 ReportViewer 控件,该控件以不同的形式停靠并在 ReportViewer 上加载报表。

2) 我们的用户不与我们共享连接,因此我们无法将其硬编码到 RDL 文件中。 SQL 通常是一个常量,RDL 文件通常根据特定形式的需要设计一次。

3)我们现在使用MySQL数据库。但任何流行的 RDBMS 中的解决方案都会有很大帮助。我希望上面的查询能够很好地描述正在访问的表的架构(查询包含表中的所有列)。

注意:请在 RDL 文件中包含答案,而不是在 RDLC 文件中包含答案。

除了@Reza Aghaei给出的答案之外,最终为我解决问题的是什么

报告文件具有数据源和数据集的标签,位于 RDL 文件的开头,如下所示

  <DataSets>
    <DataSet Name="Data">
      <Query>
        <DataSourceName>DS1</DataSourceName>

来自 @Reza Aghaei 的行,询问 DataSet (Data) 的名称,而不是 DataSourceName (DS1)。做出这种区分对于使报告文件正常工作至关重要。

var rds = new Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", this.ReportData);

将其更改为:

var rds = new Microsoft.Reporting.WinForms.ReportDataSource("Data", this.ReportData);

最佳答案

您可以使用如下所示的单个 ReportForm 并将数据和报告名称传递给它。报告表单应包含一个 ReportViewer 控件和这样的代码:

public partial class ReportForm : Form
{
    public ReportForm()
    {
        InitializeComponent();
        this.Load+=new EventHandler(ReportForm_Load);
    }

    public Object ReportData { get; set; }
    public string ReportName { get; set; }        

    private void ReportForm_Load(object sender, EventArgs e)
    {
        var rds = new Microsoft.Reporting.WinForms.ReportDataSource("DataSet1",
            this.ReportData);
        this.reportViewer1.LocalReport.DataSources.Clear();
        this.reportViewer1.LocalReport.DataSources.Add(rds);         
        var path = System.IO.Path.Combine(Application.StartupPath, 
            "Reports", this.ReportName);
        reportViewer1.LocalReport.ReportPath = path;
        this.reportViewer1.RefreshReport();
    }
}

使用

您可以这样使用ReportForm:

var f = new ReportForm();
DataTable table = new DataTable(); 
var command = Properties.Settings.Default.Command;        /*SELECT Statement*/
var connection = Properties.Settings.Default.Connection;  /*Connection String*/
using (var adapter = new SqlDataAdapter(command, connection))
    adapter.Fill(table)
f.ReportName = "Report1.rdlc" /*Or any other name*/
f.ReportData = table;
f.ShowDialog();

注意

  1. ReportViewer 控件显示 RDLC 报告。 RDL 报告应托管在 SQL Server 报告服务上。您似乎想要在客户端计算机上而不是 SSRS 上获得报告。如果是这种情况,您需要 RDLC 报告。虽然 RDL 和 RDLC 具有相同的 XML 架构,但从技术上讲,您似乎需要 RDLC。

  2. 您说RDL文件通常设计一次因此客户可以在他们的机器上拥有报告文件,您可以简单地通过地址将报告加载到报告 View 中,甚至您可以拥有这些报告在解决方案中并将其作为资源嵌入。当您将其设置为嵌入资源时,您可以通过其名称加载报告:

    reportViewer1.LocalReport.ReportEmbeddedResource = "Sample.Reports.Report1.rdlc";
    

    或按路径加载报告:

    var path = System.IO.Path.Combine(Application.StartupPath, "Reports", "Report1.rdlc");
    reportViewer1.LocalReport.ReportPath = path;
    
  3. 您说SQL通常是一个常量。并且我们的用户不与我们共享连接因此您可以使用Settings.settings 并添加 2 个属性,Command 具有应用程序范围,Connection 具有用户范围。因此,您可以让用户在运行时更改连接字符串,然后以这种方式加载数据并将数据传递到您的 ReportForm:

    DataTable table = new DataTable(); 
    var command = Properties.Settings.Default.Command;
    var connection = Properties.Settings.Default.Connection;
    using (var adapter = new SqlDataAdapter(command, connection))
        adapter.Fill(table)
    //Pass table to ReportForm
    
  4. 事实上sql命令可以是动态的,但它应该保持恒定的结果模式。不应更改结果列名称,因为报表引擎使用查询列名称来显示报表字段中的数据。因此,您也可以将 Command 属性创建为 User 设置。

  5. 关于但是任何流行的 RDBMS 中的解决方案,最好使用依赖项注入(inject)来注入(inject)为您加载数据的库。这样您就可以为不同的 DBMS 提供不同的 dll,并在需要时注入(inject)合适的 dll。

关于C# Winform - 如何通过向 ReportViewer 传递 3 个变量(即 Reportname(RDL 文件)、SQLstring 和 Connectionstring)来显示实时报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40395159/

相关文章:

c# - 如何调整 c# 标记图像的大小?

.net - Windows 窗体 .NET 中的热键(非全局)

winforms - 当我使用 Application.Exit() 或 Form.Close() 时,为什么我的通知图标应用程序没有退出?

c# - ASP.NET Core - 将 IEnumerable<T> 绑定(bind)到 POST 上的 ViewModel 字段

c# - 由同一台本地计算机上的多个应用程序并发访问轻量级/(嵌入式?)SQL 数据库?

c# - 以编程方式确定项目解决方案中的索引 - C#

mysql - 如何在创建表命令中指定日期格式

sql - 如何在 Golang 中正确扫描 array_agg 函数的结果?

c# - 如何在调用 SmtpClient.Send() 之前知道域是错误的?

c# - 如何更改附加控制台的窗口大小?