【问题标题】:Create RDLC report dynamically at run-time from a DataGridView在运行时从 DataGridView 动态创建 RDLC 报告
【发布时间】:2016-11-01 15:15:20
【问题描述】:

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

带有 DataGridView 和按钮的表单

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

我的 DatagridView (dgrData) 控件与

  1. SQL
“Select Id, c_Name from Country”
  1. 连接字符串
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. 点击按钮后,目标表单上的报表查看器应获得
    与数据源中的值相关联 数据网格视图。因此,ReportViewer 控件在用户点击报告之前对报告中的数据一无所知 运行时的按钮。
  2. 我希望该解决方案不需要创建单独的 RDLC 文件,因为它导致外部依赖,停止当前流 并在报表文件设计器中创建一个报表文件,它可以是 让用户不知所措。
  3. 我对 RDLC 设计器和关联数据源一无所知(我是 愿意学习(^_^),但我不能强求这个学习要求 在我的团队中)并将数据绑定到报告中。我将不胜感激 工作编码示例,如果您的帮助包含理论。
  4. 我知道 ReportViewer 已经存在了很长时间。希望 数据网格和数据网格之间的 1-1 数据映射的示例解决方案 将来在 SO 上更容易找到 ReportViewer。

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

【问题讨论】:

  • 让我试试c#中的解决方案,然后回到这个链。
  • 我希望该解决方案不需要创建单独的 RDLC。 我发布的解决方案基于现有报告。它不会在运行时创建列。如果需要在运行时创建报表,可以使用this ideathis one
  • 谢谢@rezaAghaei。我想知道您是否可以帮助我在运行时创建一个 rdlc 文件,而不是像您在另一个链中显示的那样创建 HTML。我已经看到您在上面提供的解决方案,但不知何故,我认为它们很复杂,我觉得事情不必那么复杂。
  • 如果有办法完全避免 RDLC 或 HTML 文件,那就更好了:)

标签: c# winforms datagridview rdlc reportviewer


【解决方案1】:

作为在运行时动态创建RDLC 报告的选项,您可以使用Run-Time Text Templates

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

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

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

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

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();

解决方法

ReportColumnDynamicReport.ttReportForm 添加到您的应用程序或什至在可重用库中一次就足够了,然后像上面的示例一样简单地使用。按照以下步骤创建动态报告模板。

报表列模型

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

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

举报表格

在项目中添加Form,在窗体中添加ReportViewer控件,并将这段代码放在类中:

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

注意

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

示例

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

【讨论】:

  • 谢谢,这似乎完全模仿了 DataGrid 并暂时解决了问题。我想知道预处理器模板是否具有灵活性,可以使其以更自定义的格式显示。特别是在我们需要根据报告需要合并行和列的情况下。
  • 我们可以在这种类型的预处理器模板中为网格上的数据设置不同的网格宽度吗?
  • 上面显示的 .tt 文件似乎是 XML,您能否展示一个相同的 HTML 实现。 . .
  • 我需要以下几行的帮助
    f.ReportColumns = this.dgrData.Columns.Cast() .Select(x => new ReportColumn(x.DataPropertyName) { Title = x.HeaderText, 宽度 = x.Width }).ToList();
  • 在运行时创建动态报告并不容易,在现实世界的环境/项目中,我相信我的回答只是一个起点。但是一个非常优雅和有用的解决方案。如果您明白这一点,它将在您需要创建模板的许多情况下对您有用,例如包含客户购买的产品的电子邮件模板。这个想法很棒 IMO!
猜你喜欢
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2013-04-22
相关资源
最近更新 更多