从DataGridView在运行时动态创建RDLC报告

我有一个表单AdvancedSearchFormDataGridView控件dgrData和一个按钮Report在C#Winform。 单击按钮Report ,我希望带有ReportView控件的表单显示与DataGridView中具有相同列标题的列相同的列。

使用DataGridView和Button进行表单

在此处输入图像描述

单击按钮“报告”时预期的输出:

在此处输入图像描述

我的DatagridViewdgrData )控件与

  1. SQL
 “Select Id, c_Name from Country” 
  1. 的ConnectionString
 server=localhost;User Id=root;password=root;Persist Security Info=True;database=country_state 

要在运行时将数据加载到网格,我准备以下DataAdapter

 DataAdapter dataAdapter = DataAdapter.Current; // I am passing the SQL statement and the table name to my database which knows the ConnectionString within the LoadData function DataTable dt0 = dataAdapter.LoadData("select Id, c_Name from `country`", "country"); if (dt0 != null) { dgrData.DataSource = dt0; } 

是否可以调用包含默认reportviewer控件的子窗体,该窗口显示带有包含与datagridview( dgrData )对应的列的表的报告以及在运行时动态生成的数据?

输出预期详情:

  1. 单击按钮,目标表单上的报表查看器应该获得
    DataGridView中的值与dataSource相关联。 因此,在用户在运行时单击“报告”按钮之前, ReportViewer控件对报告中的数据一无所知。
  2. 我希望该解决方案不需要创建单独的RDLC文件,因为它会导致外部依赖,停止当前流并在报表文件设计器中创建一个报表文件,这可能会对用户产生影响。
  3. 我对RDLC设计器和关联数据源一无所知(我愿意学习(^ _ ^),但我不能强迫我的团队学习这个学习要求)并将数据绑定到报告中。 如果您的帮助包含理论,我将非常感谢编写代码示例。
  4. 我知道ReportViewer已经存在了很长时间了。 希望将来更容易找到数据网格和ReportViewer之间1-1数据映射的示例解决方案。

注意:如果我在评论中需要任何其他数据,请告知我们。 为了显示当前的解决方案,我必须创建和RDLC文件,我必须在设计时放置连接字符串和SQL,我希望在我正在寻找的解决方案中避免。 我希望找到一个解决方案,其中RDLC文件是通过一些模块化代码生成的,这些代码也可以用在其他解决方案上,而不必为我拥有DataGrids的每个表单设计它。

作为在运行时动态创建RDLC报告的选项,您可以使用运行时文本模板 。

在下面的示例中,我创建了一个简单的网格报告,可用于在运行时动态创建报告。 您可以动态添加列以进行报告,并为列设置标题,宽度,标题返回颜色。

在示例中,我使用DataGridView填充了模板。 但您可以使用此技术依赖于任何类型的控制,甚至可以在Web表单中使用它。

示例用法 – 创建和显示动态报告

要创建和显示动态报告,只需向ReportForm添加一些列,然后设置数据并显示表单即可。

 var f = new ReportForm(); f.ReportColumns = this.dataGridView1.Columns.Cast() .Select(x => new ReportColumn(x.DataPropertyName) { Title = x.HeaderText, Width = x.Width }).ToList(); f.ReportData = this.dataGridView1.DataSource; f.ShowDialog(); 

在此处输入图像描述

解决方案的途径

ReportColumnDynamicReport.tt以及ReportForm添加到您的应用程序甚至可重用的库中就足够了,然后只需使用上面的示例。 按照以下步骤创建动态报告模板。

报告列模型

创建包含标题,表达式,颜色等属性的报表列模型。 我们将使用它来添加要报告的列。

 using System; using System.Drawing; public class ReportColumn { public ReportColumn(string name) { Name = name; Title = name; Type = typeof(System.String); Width = GetPixelFromInch(1); Expression = string.Format("=Fields!{0}.Value", name); HeaderBackColor = Color.LightGray; } public string Name { get; set; } public string Title { get; set; } public Type Type { get; set; } public int Width { get; set; } public float WidthInInch { get { return GetInchFromPixel(Width); } } public string Expression { get; set; } public Color HeaderBackColor { get; set; } public string HeaderBackColorInHtml { get { return ColorTranslator.ToHtml(HeaderBackColor); } } private int GetPixelFromInch(float inch) { using (var g = Graphics.FromHwnd(IntPtr.Zero)) return (int)(g.DpiY * inch); } private float GetInchFromPixel(int pixel) { using (var g = Graphics.FromHwnd(IntPtr.Zero)) return (float)pixel / g.DpiY; } } 

报告模板

将一个运行时模板(也称为预处理模板)添加到项目中,并将其命名为DynamicReport.tt并将此内容复制到该文件中:

 <#@ template language="C#" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections.Generic" #> <#@ parameter name="Model" type="System.Collections.Generic.List"#>      System.Data.DataSet /* Local Connection */  e9784bb0-a630-49cc-b7f9-8495aca23a6c      <# foreach(ReportColumn column in Model){#>  <#=column.Name#> <#=column.Type.Name#>  <# }#>   DataSource1 /* Local Query */              <# foreach(ReportColumn column in Model){#>  <#=column.WidthInInch#>in  <# }#>    0.25in  <# foreach(ReportColumn column in Model){#>    true true     <#=column.Title#>       <#=column.Name#>TextBox   <#=column.HeaderBackColorInHtml#> 2pt 2pt 2pt 2pt     <# }#>    0.25in  <# foreach(ReportColumn column in Model){#>    true true     <#=column.Expression#>       <#=column.Name#>   2pt 2pt 2pt 2pt     <# }#>       <# foreach(ReportColumn column in Model){#>  <# }#>      After       DataSet1 0.15625in 0.125in 0.5in 2in      0.82292in   6.5in  1in 1in 1in 1in   60987c40-62b1-463b-b670-f3fa81914e33 Inch  

报表

添加一个Form到项目并将ReportViewer控件添加到表单并将此代码放在类中:

 public partial class ReportForm : Form { public ReportForm() { InitializeComponent(); ReportColumns = new List(); this.Load+=new EventHandler(ReportForm_Load); } public List ReportColumns { get; set; } public Object ReportData { get; set; } private void ReportForm_Load(object sender, EventArgs e) { var report = new DynamicReport(); report.Session = new Dictionary(); report.Session["Model"] = this.ReportColumns; report.Initialize(); var rds = new Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", this.ReportData); this.reportViewer1.LocalReport.DataSources.Clear(); this.reportViewer1.LocalReport.DataSources.Add(rds); var reportContent = System.Text.Encoding.UTF8.GetBytes(report.TransformText()); using (var stream = new System.IO.MemoryStream(reportContent)) { this.reportViewer1.LocalReport.LoadReportDefinition(stream); } this.reportViewer1.RefreshReport(); } } 

注意

您可以简单地扩展ReportColumn模型和DynamicReport.tt 。 我使用现有报告创建了模板,我只使用了一些t4代码标记使其动态化。

您可以克隆或下载一个工作示例:

  • R-aghaei / DynamicRdlcReport
  • 下载Zip