在RDLC中动态生成列

时间:2015-03-06 11:44:21

标签: c# asp.net reporting-services rdlc dynamic-rdlc-generation

我正在尝试在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;
    }

enter image description here

enter image description here

但是,如果我对函数稍作修改以使我的数据表真正动态,通过从数据库中填充列,我的函数就不会显示在报表向导中。

这是我改变的功能

    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报告。

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

2 个答案:

答案 0 :(得分:3)

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

  1. 使用RDL代替RDLC
    因为RDLC不容易实现动态列。您可能只想更改为RDL。
  2. 列出所有列,然后隐藏那些您不需要的列
    当您的列具有最大限制并且通过设置"列可见性"非常容易实现时,此方法有效。表达。

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

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

  5. ProductName | Qty    | Date
    ----------- | ------ | ---------
    ProductA    | 1      | 2016-01-01
    ProductA    | 2      | 2016-01-15
    ProductA    | 3      | 2016-01-31
    ProductA    | 1      | 2016-02-01
    ProductA    | 2      | 2017-01-01
    ProductA    | 3      | 2017-01-15
    ProductA    | 1      | 2017-01-31
    ProductA    | 2      | 2017-02-01
    ProductA    | 3      | 2017-02-15
    ProductA    | 1      | 2017-02-28
    ProductB    | 2      | 2016-01-01
    ProductB    | 3      | 2016-01-15
    ProductB    | 1      | 2016-01-30
    ProductB    | 2      | 2016-02-01
    ProductB    | 3      | 2017-01-01
    

    我需要按月或年总数量,结果需要形成如

    ProductName | Jan    | Feb   
    ----------- | ------ | ------
    ProductA    | 12     | 7   
    ProductB    | 9      | 2     
    
    ProductName | 2016   | 2017   
    ----------- | ------ | ------
    ProductA    | 7      | 12   
    ProductB    | 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中添加一个表。删除除数据字段以外的所有内容 使用&#34;值&#34;设置数据。属性。 enter image description here

    然后通过&#34; ColumnName&#34;添加父组。属性(删除排序) enter image description here

    并在&#34; RowId&#34;上制作详细信息组。属性 enter image description here 现在,rdlc应该能够显示完全形成为DataTable的所有内容。

    为了更好地理解,我在my GitHub上制作了一个演示项目。

答案 1 :(得分: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()

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