Создание отчета RDLC динамически во время выполнения из DataGridView



У меня есть форма AdvancedSearchForm с DataGridView control dgrData и кнопка Report В C# Winform. При нажатии на кнопку Report, я хочу, чтобы форма с ReportView управления будет отображаться с теми же столбцами, как в DataGridView с теми же заголовками столбцов.



Форма с DataGridView и кнопкой



Введите описание изображения здесь



Ожидаемый результат при нажатии кнопки "отчет":



Введите описание изображения здесь



Мой DatagridView (dgrData) контроль связан с




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


Можно ли вызвать дочернюю форму, содержащую элемент управления default reportviewer , который показывает отчет с таблицей, содержащей столбцы, соответствующие datagridview (dgrData) вместе с данными динамически во время выполнения?



Ожидание выхода подробно:




  1. по нажатию кнопки, reportviewer на целевой форме должен получить

    связанный с источником данных из значений в
    DataGridView . Таким образом, элемент управления ReportViewer ничего не знает о данных в отчете, пока пользователь не нажмет на отчет
    Кнопка во время выполнения.

  2. я желаю, чтобы решение не требовало создания отдельного RDLC
    файл, потому что это вызывает внешнюю зависимость, чтобы остановить текущий поток
    и создайте файл отчета в конструкторе файлов отчетов, который может быть
    чрезмерное внимание к пользователям.

  3. я ничего не знаю о конструкторе RDLC и ассоциирующем источнике данных (я
    готов учиться ( ^ _ ^ ), но я не могу навязать это требование обучения
    в моей команде) и привязка данных к отчету. Я был бы признателен
    рабочие примеры кодирования, если ваша помощь содержит теорию.

  4. я знаю, что элемент был вокруг в течение довольно долгое время сейчас. Желание
    тот пример решения для 1-1 сопоставления данных между data-grid и
    Элемент был легче найти кого-то в будущем так.


Примечание: пожалуйста, дайте мне знать, если какие-либо дополнительные данные требуются с моей стороны в комментариях. Чтобы показать текущее решение, мне пришлось создать файл RDLC, в который я должен был поместить строку подключения и SQL во время разработки, чего я хочу избежать в решении, которое я ищу. Я хочу найти решение, где создается файл RDLC через некоторый модульный код, который можно использовать и на других решениях, а не разрабатывать его для каждой формы, где у меня есть DataGrids.

818   1  

1 ответ:

В качестве опции для динамического создания отчета RDLC во время выполнения можно использовать текстовые Шаблоны во время выполнения.

В приведенном ниже примере я создал простой сеточный отчет, который можно использовать для динамического создания отчета во время выполнения. Вы можете динамически добавлять столбцы в отчет и задавать заголовок, ширину, цвет заголовка для столбца.

В примере я заполнил шаблон, используя DataGridView. Но вы можете использовать эту технику в зависимости от любого вида контралола или даже использовать ее в веб-форма.

Пример использования-создание и отображение динамического отчета

Для создания и отображения динамического отчета достаточно добавить несколько столбцов в 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();

Введите описание изображения здесь

Путь к решению

Достаточно добавить ReportColumn и DynamicReport.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<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, чтобы сделать его динамичным.

Пример

Вы можете клонировать или загрузить рабочий пример:

Comments

    Ничего не найдено.