4

我正在尝试在 ASP.NET 中生成 RDLC 报告,其中我的数据集的列将是动态的并且仅在运行时确定。

我做了一个返回DataTable的函数,通过在RDLC报告向导中选择这个函数,我可以成功生成我的报告。

    public DataTable GetTable()
    {
        // Here we create a DataTable with four columns.
        DataTable table = new DataTable();
        table.Columns.Add("Dosage", typeof(int));
        table.Columns.Add("Drug", typeof(string));
        table.Columns.Add("Patient", typeof(string));
        table.Columns.Add("Date", typeof(DateTime));
        table.Columns.Add("testColumn", typeof(DateTime));

        // Here we add five DataRows.
        table.Rows.Add(25, "Indocin", "David", DateTime.Now);
        table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
        table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
        table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
        table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);
        return table;
    }

在此处输入图像描述

在此处输入图像描述

但是,如果我通过填充数据库中的列对函数进行轻微更改以使我的数据表真正动态化,那么我的函数将不会显示在报表向导中。

这是我改变的功能

    public DataTable GetTable2()
    {
        // Here we create a DataTable with four columns.
        DataTable table = new DataTable();
        table.Columns.Add("Dosage", typeof(int));
        table.Columns.Add("Drug", typeof(string));
        table.Columns.Add("Patient", typeof(string));
        table.Columns.Add("Date", typeof(DateTime));
        table.Columns.Add("testColumn", typeof(DateTime));


        SqlConnection connection = new SqlConnection();
        connection = Connection.getConnection();
        connection.Open();


        string tableName = "";

        tableName += "Subject";


        string Query = "select * from " + tableName + " where Status = 0;";


        SqlDataAdapter da = new SqlDataAdapter(Query, connection);
        DataSet ds = new DataSet();
        da.Fill(ds);
        DataRowCollection collection = ds.Tables[0].Rows;
        foreach (DataRow row in collection)
        {

            // Here we add five DataRows.
            table.Rows.Add(25, "Indocin", "David", DateTime.Now);
            table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
            table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
            table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
            table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);

        }


        connection.Close();

        return table;
    }

您会看到,我对该函数所做的唯一更改是从数据库中查询并在循环中生成报表数据集列,该循环遍历数据库数据。但是由于这种变化,我的功能没有出现在报告向导中。如果我省略代码,它会再次出现。

我可以使用此函数很好地生成 GridView,但问题在于 RDLC 报告。

我的目标是使用数据库结果生成报告数据表。请帮我。

4

2 回答 2

4

我有同样的需求,并对解决方案做了一些调查。
我没有尝试所有这些,但仍然列出了我认为有意义的那些。

  1. 使用 RDL 而不是 RDLC
    因为 RDLC 不容易实现动态列。您可能只想更改为 RDL。
  2. 列出所有列,然后隐藏不需要
    的列 当您的列具有最大限制并且通过使用表达式设置“列可见性”很容易实现时,这很有效。

  3. 在运行时创建 RDLC
    RDLC 基于 XML,因此在运行时生成适合您的数据结构的 RDLC 是有意义的。
    好吧,我没有选择这个,因为我认为 RDLC 的架构有点复杂,而且我的表实际上很简单,即使它需要动态列。
    如果您真的需要使用这个终极解决方案,您可能需要搜索是否有某种库可以帮助您进行构建。

  4. 将表格划分为单元格列表并按组行和列标识重新组装它们
    这是我的同事吉米建议的。有点 hacky 但我发现如果您的表没有像 ColumnSpan 或其他东西这样的复杂结构,它非常有用。详情如下例

产品名称 | 数量 | 日期
------------ | ------ | ---------
产品A | 1 | 2016-01-01
产品A | 2 | 2016-01-15
产品A | 3 | 2016-01-31
产品A | 1 | 2016-02-01
产品A | 2 | 2017-01-01
产品A | 3 | 2017-01-15
产品A | 1 | 2017-01-31
产品A | 2 | 2017-02-01
产品A | 3 | 2017-02-15
产品A | 1 | 2017-02-28
产品B | 2 | 2016-01-01
产品B | 3 | 2016-01-15
产品B | 1 | 2016-01-30
产品B | 2 | 2016-02-01
产品B | 3 | 2017-01-01

我需要按月或按年计算总量,结果需要形成

产品名称 | 一月 | 二月   
------------ | ------ | ------
产品A | 12 | 7   
产品B | 9 | 2     
产品名称 | 2016 | 2017   
------------ | ------ | ------
产品A | 7 | 12   
产品B | 8 | 3     

按月分组时,我可以列出所有 12 个月并隐藏那些我不需要的。
但是,按年分组时不起作用。

实施解决方案4。
首先,准备您需要的DataTable。

其次,将 DataTable 划分为List<ReportCell>.

public class ReportCell
{
    public int RowId { get; set; }
    public string ColumnName { get; set; }
    public string Value { get; set; }

    public static List<ReportCell> ConvertTableToCells(DataTable table)
    {
        List<ReportCell> cells = new List<ReportCell>();

        foreach (DataRow row in table.Rows)
        {
            foreach (DataColumn col in table.Columns)
            {
                ReportCell cell = new ReportCell
                {
                    ColumnName = col.Caption,
                    RowId = table.Rows.IndexOf(row),
                    Value = row[col.ColumnName].ToString()
                };

                cells.Add(cell);
            }
        }

        return cells;
    }
}

第三,将此列表用作 ReportViewer 的来源。

// in DAO
public List<ReportCell> GetReportCells(DataTable table)
{
    return ReportCell.ConvertTableToCells(table);
}    

// in aspx.cs
ReportViewer_main.LocalReport.ReportPath = Server.MapPath("~/RDLC/Report_main.rdlc");
ReportViewer_main.LocalReport.DataSources.Add(
    new ReportDataSource("DataSet1", dao.GetReportCells(tableGroupByMonth)));
ReportViewer_main.LocalReport.Refresh();

最后,在 RDLC 中添加一个表。删除除数据字段之外的所有内容。
使用“值”属性设置数据。 在此处输入图像描述

然后通过“ColumnName”属性添加父组(删除排序) 在此处输入图像描述

并在“RowId”属性上创建详细信息组 在此处输入图像描述 现在 rdlc 应该能够显示与 DataTable 完全相同的所有内容。

为了更好地理解,我在我的 GitHub 上做了一个演示项目。

于 2017-03-14T09:10:05.590 回答
1

我不确定你的问题是否过于优雅。不可能创建真正的临时报告。解决方法是这样的。- 创建 rdlc 文件 - 以您从中获取数据的格式创建一个数据集 xsd 文件。您必须手动执行此操作,并且每一列都应与您的最终输出匹配 - 将 rdlc 文件绑定到此数据集数据源 - 设计您的报告

现在在查询生成部分,您必须像这样将动态数据绑定到 rdlc

                Dim repDS As New Microsoft.Reporting.WebForms.ReportDataSource
                repDS.Value = dT
                repDS.Name = "dsConsolReq_dt1" 'hard coded here, but you should get it dynamically perhaps from the querystring or the db

                RV1.LocalReport.DataSources.Clear()
                RV1.LocalReport.DataSources.Add(repDS)
                RV1.LocalReport.ReportPath = "Reports\rep_itemr1.rdlc" 'same again, use dynamic values
                RV1.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local
                RV1.LocalReport.Refresh()

这里的关键是报表数据源的名称。它应该与您为设计报告而创建的虚拟数据集/数据表完全匹配

于 2015-03-31T09:14:35.153 回答