从DataGridView在运行时动态创建RDLC报告 [英] Create RDLC report dynamically at run-time from a DataGridView

查看:361
本文介绍了从DataGridView在运行时动态创建RDLC报告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



使用DataGridView和按钮的表单





输出预期点击按钮报告:





我的 DatagridView dgrData )控件与


  1. SQL


$ b $相关联b


 从国家选择ID,c_Name





  1. C onnectionString




  server = localhost;用户ID = root;密码= root; Persist Security Info = True; database = country_state 


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

  DataAdapter dataAdapter = DataAdapter。当前; 
//我将SQL语句和表名传递给我的数据库,该数据库知道LoadData函数中的ConnectionString

DataTable dt0 = dataAdapter.LoadData(select id,c_Name from`country ,国);
if(dt0!= null){
dgrData.DataSource = dt0;
}

是否可以调用包含默认 reportviewer 控件,它显示一个包含与datagridview相对应的列的报表( dgrData )以及运行时动态的数据



详细输出期望




  1. 点击按钮,目标表单上的报表查看器应该从
    DataGridView 中的值获取与dataSource相关联的

    。因此,只有在用户在运行时点击报告
    按钮之后,报表查看器
    控件就不了解报表中的数据。

  2. 我希望该解决方案不需要创建单独的RDLC
    文件,因为它导致外部依赖关系,以阻止当前流
    并在报告文件设计器中创建一个可以为
    的报告文件

  3. 我对RDLC设计师和关联数据源一无所知(我是
    愿意学习(^ _ ^),但我不能强制这个学习要求
    在我的团队),并将数据绑定到报告。我会感谢
    的工作代码示例,如果您的帮助包含理论。

  4. 我知道ReportViewer已经存在了很长时间了。祝愿
    ,数据网格和
    之间的1-1数据映射的示例解决方案ReportViewer在将来更容易找到。

注意:如有需要在评论中需要附加资料,请通知我。为了显示当前的解决方案,我必须创建和RDLC文件,我必须在设计时把两个连接字符串和SQL都放在我想要解决的解决方案中。我想找到一个解决方案,RDLC文件是通过一些可以在其他解决方案中使用的模块化代码生成的,而不是为每个具有DataGrids的表单设计它。

解决方案

作为在运行时动态创建 RDLC 的选项,您可以使用



解决路径



添加 ReportColumn DynamicReport已经足够了.tt ReportForm 到您的应用程序,甚至在一个可重用的库中,然后只需使用上面的例子。按照以下步骤创建动态报告模板。



报表列模型



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

  using System; 
使用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;组; }
public string标题{get;组; }
public Type Type {get;组; }
public int Width {get;组; }
public float WidthInInch
{
get {return GetInchFromPixel(Width); }
}
public string Expression {get;组; }
public Color HeaderBackColor {get;组; }
public string HeaderBackColorInHtml
{
get {return ColorTranslator.ToHtml(HeaderBackColor);
}
private int GetPixelFromInch(float inch)
{
using(var g = Graphics.FromHwnd(IntPtr.Zero))
return(int)(g .DpiY *英寸);
}
private float GetInchFromPixel(int pixel)
{
using(var g = Graphics.FromHwnd(IntPtr.Zero))
return(float)pixel / g piㄧ;
}
}

报告模板 p>

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

 <#@ template language =C##> 
<#@ import namespace =System.Linq#>
<#@ import namespace =System.Collections.Generic#>
<#@ parameter name =Modeltype =System.Collections.Generic.List< ReportColumn>#>
<?xml version =1.0encoding =utf-8?>
< Report xmlns:rd =http://schemas.microsoft.com/SQLServer/reporting/reportdesignerxmlns =http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition >
< DataSources>
< DataSource Name =DataSource1>
< ConnectionProperties>
< DataProvider> System.Data.DataSet< / DataProvider>
< ConnectString> / *本地连接* /< / ConnectString>
< / ConnectionProperties>
< rd:DataSourceID> e9784bb0-a630-49cc-b7f9-8495aca23a6c< / rd:DataSourceID>
< / DataSource>
< / DataSources>
< DataSet>
< DataSet Name =DataSet1>
< Fields>
<#foreach(Model中的ReportColumn列){#>
< Field Name =<#= column.Name#>>
< DataField><#= column.Name#>< / DataField>
< rd:TypeName><#= column.Type.Name#>< / rd:TypeName>
< / Field>
<#}#>
< / Fields>
<查询>
< DataSourceName> DataSource1< / DataSourceName>
< CommandText> / *本地查询* /< / CommandText>
< / Query>
< rd:DataSetInfo>
< rd:DataSetName />
< rd:TableName />
< rd:ObjectDataSourceType />
< / rd:DataSetInfo>
< / DataSet>
< / DataSets>
< Body>
< ReportItems>
< Tablix Name =Tablix1>
< TablixBody>
< TablixColumns>
<#foreach(Model中的ReportColumn列){#>
< TablixColumn>
< Width><#= column.WidthInInch#> in< / Width>
< / TablixColumn>
<#}#>
< / TablixColumns>
< TablixRows>
< TablixRow>
< Height> 0.25in< / Height>
< TablixCells>
<#foreach(Model中的ReportColumn列){#>
< TablixCell>
< CellContents>
< Textbox Name =<#= column.Name#> TextBox>
< CanGrow> true< / CanGrow>
< KeepTogether> true< / KeepTogether>
<段落>
< Paragraph>
< TextRuns>
< TextRun>
< Value><#= column.Title#>< / Value>
< Style />
< / TextRun>
< / TextRuns>
< Style />
< / Paragraph>
< / Paragraphs>
< rd:DefaultName><#= column.Name#> TextBox< / rd:DefaultName>
< Style>
< Border>
<颜色> LightGrey< / Color>
< Style> Solid< / Style>
< / Border>
< BackgroundColor><#= column.HeaderBackColorInHtml#>< / BackgroundColor>
< PaddingLeft> 2pt< / PaddingLeft>
< PaddingRight> 2pt< / PaddingRight>
< PaddingTop> 2pt< / PaddingTop>
< PaddingBottom> 2pt< / PaddingBottom>
< / Style>
< / Textbox>
< / CellContents>
< / TablixCell>
<#}#>
< / TablixCells>
< / TablixRow>
< TablixRow>
< Height> 0.25in< / Height>
< TablixCells>
<#foreach(Model中的ReportColumn列){#>
< TablixCell>
< CellContents>
< Textbox Name =<#= column.Name#>>
< CanGrow> true< / CanGrow>
< KeepTogether> true< / KeepTogether>
<段落>
< Paragraph>
< TextRuns>
< TextRun>
< Value><#= column.Expression#>< / Value>
< Style />
< / TextRun>
< / TextRuns>
< Style />
< / Paragraph>
< / Paragraphs>
< rd:DefaultName><#= column.Name#>< / rd:DefaultName>
< Style>
< Border>
<颜色> LightGrey< / Color>
< Style> Solid< / Style>
< / Border>
< PaddingLeft> 2pt< / PaddingLeft>
< PaddingRight> 2pt< / PaddingRight>
< PaddingTop> 2pt< / PaddingTop>
< PaddingBottom> 2pt< / PaddingBottom>
< / Style>
< / Textbox>
< / CellContents>
< / TablixCell>
<#}#>
< / TablixCells>
< / TablixRow>
< / TablixRows>
< / TablixBody>
< TablixColumnHierarchy>
< TablixMembers>
<#foreach(Model中的ReportColumn列){#>
< TablixMember />
<#}#>
< / TablixMembers>
< / TablixColumnHierarchy>
< TablixRowHierarchy>
< TablixMembers>
< TablixMember>
< KeepWithGroup>之后< / KeepWithGroup>
< / TablixMember>
< TablixMember>
< Group Name =Details/>
< / TablixMember>
< / TablixMembers>
< / TablixRowHierarchy>
< DataSetName> DataSet1< / DataSetName>
< Top> 0.15625in< / Top>
< Left> 0.125in< / Left>
< Height> 0.5in< / Height>
< Width> 2in< / Width>
< Style>
< Border>
< Style> None< / / Style>
< / Border>
< / Style>
< / Tablix>
< / ReportItems>
< Height> 0.82292in< / Height>
< Style />
< / Body>
< Width> 6.5in< / Width>
< Page>
< LeftMargin> 1in< / LeftMargin>
&RightMargin> 1in< / RightMargin>
< TopMargin> 1in< / TopMargin>
< BottomMargin> 1in< / BottomMargin>
< Style />
< / Page>
< rd:ReportID> 60987c40-62b1-463b-b670-f3fa81914e33< / rd:ReportID>
< rd:ReportUnitType> Inch< / rd:ReportUnitType>
< / Report>

报告表



添加一个表单来投射并将一个 ReportViewer 控件添加到表单中,并将此代码放在类中:

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

public List< ReportColumn> ReportColumns {get组; }
public Object ReportData {get;组;

private void ReportForm_Load(object sender,EventArgs e)
{
var report = new DynamicReport();
report.Session = new Dictionary< string,object>();
report.Session [Model] = this.ReportColumns;
report.Initialize();
var rds = new Microsoft.Reporting.WinForms.ReportDataSource(DataSet1,this.ReportData);
this.reportViewer1.LocalReport.DataSources.Clear();
这个.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代码标签来使其生效。


I have a form AdvancedSearchForm with a DataGridView control dgrData and a button Report in C# Winform. On click of the button Report, I wish that a form with a ReportView control be shown with the same columns as in the DataGridView with the same column Headers.

Form with DataGridView and Button

Output expected on clicking Button "Report":

My DatagridView (dgrData) Control is associated with

  1. SQL

"Select Id, c_Name from Country"

  1. ConnectionString

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

To load data to the grid at runtime, I prepare the following 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;
}

Is it possible to call a child Form containing default reportviewer control, which shows report with a table containing columns corresponding to the datagridview (dgrData) along with data dynamically at runtime?

Output expectation in detail:

  1. On click of button, the reportviewer on the target form should get
    associated with the dataSource from the values in the DataGridView. So, the ReportViewer control does not know anything about the data in the report till user clicks on the Report Button at run-time.
  2. I wish the the solution does not require creation of a separate RDLC file, because It causes external dependency, to stop the current flow and create a report file in a report file designer which can be over-whelming to users.
  3. I know nothing about RDLC designer and associating data source (I am willing to learn (^_^), but I cannot force this learning requirement on my team) and binding the data to the report. I would appreciate working coding examples, if your help contains theory.
  4. I know ReportViewer has been around for quite a long time now. Wish that an example solution for 1-1 data mapping between data-grid and ReportViewer was easier to find for someone in the future on SO.

Note: Please let me know if any additional data is required from my side in the comments. To show the current solution, I had to create and RDLC file where I had to put both the connection string and SQL at design time which I wish to avoid in the solution I am looking for. I wish to find a solution where the RDLC file is generated through some modular code that can be used on other solutions as well, rather than having to design it for each form where I have DataGrids.

解决方案

As an option to create RDLC report dynamically at at run-time, you can use Run-Time Text Templates.

In the below example, I've created a simple grid report that can be used to create report dynamically at run-time. You can dynamically add columns to report and set title, width, header back color for column.

In the example, I've filled the template using a DataGridView. But you can use this technique dependent from any kind of contrlol or even use it in web forms.

Sample Usage - Create and Show Dynamic Report

To create and show dynamic report it's enough to add some columns to the ReportForm and then set data and show the form.

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

Path to solution

It's enough to add ReportColumn and DynamicReport.tt and ReportForm to your application or even in a reusable library once and then simply use like above example. Follow below steps to create a dynamic report template.

Report Column Model

Create a report column model that contains properties for title, expression, color and so on. We will use this to add columns to report.

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;
    }
}

Report Template

Add a Run-time Template (Also known as Preprocessed template) to the project and name it DynamicReport.tt and copy this content to the file:

<#@ template language="C#" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ parameter name="Model" type="System.Collections.Generic.List<ReportColumn>"#>
<?xml version="1.0" encoding="utf-8"?>
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition">
  <DataSources>
    <DataSource Name="DataSource1">
      <ConnectionProperties>
        <DataProvider>System.Data.DataSet</DataProvider>
        <ConnectString>/* Local Connection */</ConnectString>
      </ConnectionProperties>
      <rd:DataSourceID>e9784bb0-a630-49cc-b7f9-8495aca23a6c</rd:DataSourceID>
    </DataSource>
  </DataSources>
  <DataSets>
    <DataSet Name="DataSet1">
      <Fields>
<#    foreach(ReportColumn column in Model){#>
        <Field Name="<#=column.Name#>">
          <DataField><#=column.Name#></DataField>
          <rd:TypeName><#=column.Type.Name#></rd:TypeName>
        </Field>
<#    }#>
      </Fields>
      <Query>
        <DataSourceName>DataSource1</DataSourceName>
        <CommandText>/* Local Query */</CommandText>
      </Query>
      <rd:DataSetInfo>
        <rd:DataSetName />
        <rd:TableName />
        <rd:ObjectDataSourceType />
      </rd:DataSetInfo>
    </DataSet>
  </DataSets>
  <Body>
    <ReportItems>
      <Tablix Name="Tablix1">
        <TablixBody>
          <TablixColumns>
<#    foreach(ReportColumn column in Model){#>
            <TablixColumn>
              <Width><#=column.WidthInInch#>in</Width>
            </TablixColumn>
<#    }#>
          </TablixColumns>
          <TablixRows>
            <TablixRow>
              <Height>0.25in</Height>
              <TablixCells>
<#    foreach(ReportColumn column in Model){#>
                <TablixCell>
                  <CellContents>
                    <Textbox Name="<#=column.Name#>TextBox">
                      <CanGrow>true</CanGrow>
                      <KeepTogether>true</KeepTogether>
                      <Paragraphs>
                        <Paragraph>
                          <TextRuns>
                            <TextRun>
                              <Value><#=column.Title#></Value>
                              <Style />
                            </TextRun>
                          </TextRuns>
                          <Style />
                        </Paragraph>
                      </Paragraphs>
                      <rd:DefaultName><#=column.Name#>TextBox</rd:DefaultName>
                      <Style>
                        <Border>
                          <Color>LightGrey</Color>
                          <Style>Solid</Style>
                        </Border>
                        <BackgroundColor><#=column.HeaderBackColorInHtml#></BackgroundColor>
                        <PaddingLeft>2pt</PaddingLeft>
                        <PaddingRight>2pt</PaddingRight>
                        <PaddingTop>2pt</PaddingTop>
                        <PaddingBottom>2pt</PaddingBottom>
                      </Style>
                    </Textbox>
                  </CellContents>
                </TablixCell>
<#    }#>
              </TablixCells>
            </TablixRow>
            <TablixRow>
              <Height>0.25in</Height>
              <TablixCells>
<#    foreach(ReportColumn column in Model){#>
                <TablixCell>
                  <CellContents>
                    <Textbox Name="<#=column.Name#>">
                      <CanGrow>true</CanGrow>
                      <KeepTogether>true</KeepTogether>
                      <Paragraphs>
                        <Paragraph>
                          <TextRuns>
                            <TextRun>
                              <Value><#=column.Expression#></Value>
                              <Style />
                            </TextRun>
                          </TextRuns>
                          <Style />
                        </Paragraph>
                      </Paragraphs>
                      <rd:DefaultName><#=column.Name#></rd:DefaultName>
                      <Style>
                        <Border>
                          <Color>LightGrey</Color>
                          <Style>Solid</Style>
                        </Border>
                        <PaddingLeft>2pt</PaddingLeft>
                        <PaddingRight>2pt</PaddingRight>
                        <PaddingTop>2pt</PaddingTop>
                        <PaddingBottom>2pt</PaddingBottom>
                      </Style>
                    </Textbox>
                  </CellContents>
                </TablixCell>
<#    }#>
              </TablixCells>
            </TablixRow>
          </TablixRows>
        </TablixBody>
        <TablixColumnHierarchy>
          <TablixMembers>
<#    foreach(ReportColumn column in Model){#>
            <TablixMember />
<#    }#>
          </TablixMembers>
        </TablixColumnHierarchy>
        <TablixRowHierarchy>
          <TablixMembers>
            <TablixMember>
              <KeepWithGroup>After</KeepWithGroup>
            </TablixMember>
            <TablixMember>
              <Group Name="Details" />
            </TablixMember>
          </TablixMembers>
        </TablixRowHierarchy>
        <DataSetName>DataSet1</DataSetName>
        <Top>0.15625in</Top>
        <Left>0.125in</Left>
        <Height>0.5in</Height>
        <Width>2in</Width>
        <Style>
          <Border>
            <Style>None</Style>
          </Border>
        </Style>
      </Tablix>
    </ReportItems>
    <Height>0.82292in</Height>
    <Style />
  </Body>
  <Width>6.5in</Width>
  <Page>
    <LeftMargin>1in</LeftMargin>
    <RightMargin>1in</RightMargin>
    <TopMargin>1in</TopMargin>
    <BottomMargin>1in</BottomMargin>
    <Style />
  </Page>
  <rd:ReportID>60987c40-62b1-463b-b670-f3fa81914e33</rd:ReportID>
  <rd:ReportUnitType>Inch</rd:ReportUnitType>
</Report>

Report Form

Add a Form to project and add a ReportViewer control to the form and put this code in the class:

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

    public List<ReportColumn> ReportColumns { get; set; }
    public Object ReportData { get; set; }

    private void ReportForm_Load(object sender, EventArgs e)
    {
        var report = new DynamicReport();
        report.Session = new Dictionary<string, object>();
        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();
    }
}

Note

You can simply extend the ReportColumn model and also DynamicReport.tt. I've created the template using an exiting report, I just used some t4 code tags to make it dynamic.

这篇关于从DataGridView在运行时动态创建RDLC报告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆