【问题标题】:Dynamically render a DataTable into a Winform using the SSRS ReportViewer Control使用 SSRS ReportViewer 控件将 DataTable 动态呈现到 Winform
【发布时间】:2010-12-16 00:30:34
【问题描述】:

背景

  • 我正在编写一个方法,该方法(最终)将 System.Data.DataTable 作为输入,并使用 Microsoft 的 ReportViewer 控件 (http://www.gotreportviewer.com/) 将其作为(简单的、表格的)SSRS 报告呈现到 Winform 中李>
  • 为此,我需要 (1) 基于 DataTable 动态创建 RDL 文件 (2) 将 RDL 加载到 ReportViewerControl (3) 将 ReportViewerControl 绑定到该 DataTable

问题

  • 理想情况下,我只需要一个链接,指向完成上述所有操作的示例 - 我已经搜索过,但找不到。
  • 否则,我需要一些关于上述 #1 和 #3 的帮助。
  • 对于 #1 - 是否有一种简单的方法可以在运行时动态生成 RDL 文件? (我已经开始编写代码来发出正确的 XML,但重用某些东西会让我有一段时间)
  • 对于#3 - 我不清楚如何将 ReportViewerControl 绑定到我在本地拥有的 DataTable。我发现的大多数示例都假设 ReportViewer 控件将获取远程 SQL 服务器上的数据(这是意料之中的),而不是从本地 DataTable 中获取数据。

上下文

  • 我最近才开始使用 ReportViewer 控件 - 我在谷歌上找到了示例 - 但似乎没有一个涵盖完整的场景
  • 我不提前知道 DataTable 的架构。在调用将呈现它的方法时,DataTable 的架构甚至不会保持不变。
  • 我不能使用不同的报告控件 - 我必须使用 ReportViewer 控件。如果您知道其他可以简化此任务的报告控件,请告诉我。即使它不能解决我当前的问题,但它对以后很有用。
  • 查看此报告的人是最终用户,无权将 RDL 发布到 SSRS 服务器
  • DataTable 已经进行了排序、过滤等操作。类型都是字符串、整数、双精度和日期的简单值。 DataTable 将具有合理的大小 - 1-30 列并具有 100 到 5000 行。 DataTable 也在本地构建(有时通过代码手动构建)并且没有从某个远程数据源检索数据。
  • 数据将始终呈现为简单的表格(无图表等)。稍后我可能需要添加分组
  • 我无法切换到使用 HTML、XAML 等来显示报告 - ReportViewer 中的某些功能我最终会利用 HTML、XAML 等所没有的功能。

2010 年 1 月 15 日更新

从下面乔恩的回答开始,我能够实现我所需要的。正如他所提到的,困难的部分是学习 RDL XML 模式并知道要编写哪些 RDL 元素来实现所需的报告类型。

【问题讨论】:

    标签: winforms reporting-services datatable reporting


    【解决方案1】:

    我在 4 个月的时间里确实做到了这一点。我的代码在 VB.NET 中,而且很长。我从 GotReportViewer 中列出的代码开始,并在它之上构建。简而言之,这就是您需要做的事情:

    • 在内存中渲染和 RDLC 文件 - 使用 DataTable(或数据集,用于 多表报告)作为输入

    为此,我创建了一个名为 ReportEngine 的类。它基本上只是一堆创建 RDLC 文件的函数。这是整个操作的胆量,代码比较长。以下是我正在使用的一些主要功能。最好将我的课程通过电子邮件发送给您 - 因为它们很长:

      'Data Building variables
      Private _reportDataset As DataSet             'Data displayed in report
      Private _AllFields As List(Of String)         'All column field names
      Private _AllCaptions As List(Of String)       'All column names to display in report (needed for french translation)
      Private _reportRDL As MemoryStream            'Report definition file
      Private _reportControl As ReportControl       'Control that displays the report
    
        Public Sub LoadReport(ByVal reportDataset As DataSet)
        Try
          _reportDataset = reportDataset
    
          'check if the datatable contains data
          _hasNoData = False
          If _reportDataset.Tables(0).Rows.Count = 0 Then
            _hasNoData = True
          End If
    
          'Get table column fieldnames, captions and widths
          _AllFields = GetTableFields(0)
          _AllCaptions = GetTableCaptions(0)
    
          'reset RDL file if already existing
          If Not (_reportRDL Is Nothing) Then
            _reportRDL.Dispose()
          End If
    
          GenerateRdl()                   'Create the RDLC file
          ShowReport()                    'Load it into the ReportViewer Control
          RaiseEvent ReportLoaded(Me)     'Indicate via event that report is loaded and ready to be displayed
    
        Catch ex As Exception
             'Handle error
        End Try
      End Sub
    
    
    
         'returns a list of fields from a datatable used for the report
      Public Function GetTableFields(ByVal tableIndex As Integer) As List(Of String)
        Dim dataTable As DataTable = _reportDataset.Tables(tableIndex)
        Dim availableFields As New List(Of String)
        Dim i As Integer
        For i = 0 To dataTable.Columns.Count - 1
          availableFields.Add(dataTable.Columns(i).ColumnName)
        Next i
        Return availableFields
      End Function
    
      'returns a list of captions from a datatable
      Public Function GetTableCaptions(ByVal tableIndex As Integer) As List(Of String)
        Dim dataTable As DataTable = _reportDataset.Tables(tableIndex)
        Dim captions As New List(Of String)
        Dim i As Integer
        For i = 0 To dataTable.Columns.Count - 1
          captions.Add(dataTable.Columns(i).Caption)
        Next i
        Return captions
      End Function
    
    • 将 RDLC 文件从内存加载到 reportViewer 中
    • 使用在 RDLC 文件中指定的相同名称将数据源添加到 ReportViewer 控件。如果名称不匹配,则会出现错误。

    [代码从这里开始 - 代码块搞砸了,无法修复。]

    Public Sub DisplayReport(ByVal ms As MemoryStream, ByVal ds As DataSet)
    

    Dim RowCount As Integer = 0

    ReportViewer1.Reset()
    ReportViewer1.LocalReport.DataSources.Clear()
    ReportViewer1.LocalReport.LoadReportDefinition(ms)
    
    For I As Integer = 0 To Me.ReportEngine.ReportDataSet.Tables.Count - 1
      'Bind dataTables to the report viewer control - matches the datasources contained in the RDLC files
      ReportViewer1.LocalReport.DataSources.Add(New ReportDataSource("MyData" + I.ToString, ds.Tables(I)))
    
      'Calc total rows returned
      RowCount += ds.Tables(I).Rows.Count
    Next
    
    SetupReport()
    ReportViewer1.RefreshReport()
    
    End Sub
    

    无论如何,如果您还有更多问题,我可以继续讨论几天。要让它运行起来,还有很多工作要做。

    【讨论】:

      【解决方案2】:
          public static DataTable GetDataTabletFromCSVFile(string filePath, bool isHeadings)
          {
              DataTable MethodResult = null;
              try
              {
                  using (TextFieldParser TextFieldParser = new TextFieldParser(filePath))
                  {
                      if (isHeadings)
                      {
                          MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
      
                      }
                      else
                      {
                          MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
      
                      }
      
                  }
      
              }
              catch (Exception ex)
              {
                  ex.HandleException();
              }
              return MethodResult;
          }
      
          public static DataTable GetDataTableFromCsvString(string csvBody, bool isHeadings)
          {
              DataTable MethodResult = null;
              try
              {
                  MemoryStream MemoryStream = new MemoryStream();
      
      
                  StreamWriter StreamWriter = new StreamWriter(MemoryStream);
      
                  StreamWriter.Write(csvBody);
      
                  StreamWriter.Flush();
      
      
                  MemoryStream.Position = 0;
      
      
                  using (TextFieldParser TextFieldParser = new TextFieldParser(MemoryStream))
                  {
                      if (isHeadings)
                      {
                          MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
      
                      }
                      else
                      {
                          MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
      
                      }
      
                  }
      
              }
              catch (Exception ex)
              {
                  ex.HandleException();
              }
              return MethodResult;
          }
      
          public static DataTable GetDataTableFromRemoteCsv(string url, bool isHeadings)
          {
              DataTable MethodResult = null;
              try
              {
                  HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
                  HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
      
                  StreamReader StreamReader = new StreamReader(httpWebResponse.GetResponseStream());
      
                  using (TextFieldParser TextFieldParser = new TextFieldParser(StreamReader))
                  {
                      if (isHeadings)
                      {
                          MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
      
                      }
                      else
                      {
                          MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
      
                      }
      
                  }
      
              }
              catch (Exception ex)
              {
                  ex.HandleException();
              }
              return MethodResult;
          }
      
      
          private static DataTable GetDataTableFromTextFieldParser(TextFieldParser textFieldParser)
          {
              DataTable MethodResult = null;
              try
              {
                  textFieldParser.SetDelimiters(new string[] { "," });
      
                  textFieldParser.HasFieldsEnclosedInQuotes = true;
      
      
                  string[] ColumnFields = textFieldParser.ReadFields();
      
                  DataTable dt = new DataTable();
      
                  foreach (string ColumnField in ColumnFields)
                  {
                      DataColumn DataColumn = new DataColumn(ColumnField);
      
                      DataColumn.AllowDBNull = true;
      
                      dt.Columns.Add(DataColumn);
      
                  }
      
      
                  while (!textFieldParser.EndOfData)
                  {
                      string[] Fields = textFieldParser.ReadFields();
      
      
                      for (int i = 0; i < Fields.Length; i++)
                      {
                          if (Fields[i] == "")
                          {
                              Fields[i] = null;
      
                          }
      
                      }
      
                      dt.Rows.Add(Fields);
      
                  }
      
                  MethodResult = dt;
      
              }
              catch (Exception ex)
              {
                  ex.HandleException();
              }
              return MethodResult;
          }
      
          private static DataTable GetDataTableFromTextFieldParserNoHeadings(TextFieldParser textFieldParser)
          {
              DataTable MethodResult = null;
              try
              {
                  textFieldParser.SetDelimiters(new string[] { "," });
      
                  textFieldParser.HasFieldsEnclosedInQuotes = true;
      
                  bool FirstPass = true;
      
                  DataTable dt = new DataTable();
      
                  while (!textFieldParser.EndOfData)
                  {
                      string[] Fields = textFieldParser.ReadFields();
      
                      if(FirstPass)
                      {
                          for (int i = 0; i < Fields.Length; i++)
                          {
                              DataColumn DataColumn = new DataColumn("Column " + i);
      
                              DataColumn.AllowDBNull = true;
      
                              dt.Columns.Add(DataColumn);
      
                          }
      
                          FirstPass = false;
      
                      }
      
                      for (int i = 0; i < Fields.Length; i++)
                      {
                          if (Fields[i] == "")
                          {
                              Fields[i] = null;
      
                          }
      
                      }
      
                      dt.Rows.Add(Fields);
      
                  }
      
                  MethodResult = dt;
      
              }
              catch (Exception ex)
              {
                  ex.HandleException();
              }
              return MethodResult;
          }
      

      【讨论】:

        猜你喜欢
        • 2012-04-29
        • 1970-01-01
        • 1970-01-01
        • 2015-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-07
        相关资源
        最近更新 更多