【问题标题】:Create Report in VS2013 Report Viewer with Multiple Report Tables that use the same Dataset在 VS2013 报表查看器中使用使用相同数据集的多个报表表创建报表
【发布时间】:2015-10-08 16:19:14
【问题描述】:

我需要在 VS2013 Report Viewer (.net 4.5 C#) winforms 应用程序中创建一个显示多个报表表的报表。报告表需要使用相同的 SQL 存储过程(以填充名为“DataSet”的 dt),只需根据从前一屏幕的列表框提示中选择的项目来改变返回的数据。我正在尝试使用本地报告模式(我的 winforms 应用程序中引用了 .net 程序集)。下面是单个报告应该如何显示的示例以及我尝试用来生成报告的代码。我有两个 rdlc 文件,包含页眉和页脚的初始文件是 ItemsSoldMonthlyReport_Load 方法中链接的文件。另一个 rdlc 作为子报表嵌入在第一个报表文件(在报表设计器中)的详细信息行中。 ItemsSoldMonthlyReport_Load 方法将 itemTypepFromDatepThruDate 参数正确地传递给子报表方法。 subreport 方法是根据应用于 “SoldList” 数据集的项目数启动的,这是正确的。对itemType 参数中的每个项目使用CC_SubreportProcessingEventHandler 中的GetData 方法,成功返回每个表的数据。每个报告表的"DataSet" DataTable 都设置了正确的数据。但是,似乎 "DataSet" DataTable 只能设置一次作为 ReportDataSource。当我尝试将加载了第二组数据的"DataSet"设置为ReportDataSource但第二个表(即:服装)的数据没有显示在最终报告中时,不会出现错误。相反,第一个数据表(即:玩具)在最终报告显示中显示两次。是否可以做我正在尝试的事情,如果可以,我应该采取什么方法?我已经尝试了很多东西并对此进行了很多研究,但我自己找不到答案。如果报表查看器绝对无法生成这样的报表,任何人都可以建议一个不太昂贵的替代方案吗?在此先感谢...

报告应该是什么样子...

我最近(也是最接近的尝试)创建此类报告的代码...

namespace StoreProject_Forms
{
    public partial class rptItemsSoldReport : Form
    {
        int x = 0;
        public rptItemsSoldReport()
        {
            InitializeComponent();
        }

        public void CC_SubreportProcessingEventHandler(object sender, SubreportProcessingEventArgs e)
        {
            DataTable dt = new DataTable();
            var mainSource = ((LocalReport)sender).DataSources["SoldList"];
            var itemTypes = e.Parameters["itemType"].Values;
            DateTime sdate = e.Parameters["pFromDate"].Values;
            DateTime edate = e.Parameters["pThruDate"].Values;
            StoreProject1.StoreDataSetTableAdapters.spGetItemsSoldReportTableAdapter commDt = new StoreProject1.StoreDataSetTableAdapters.spGetItemsSoldReportTableAdapter();
            dt.Clear();
            dt = commDt.GetData(sdate, edate, itemTypes[x]);
            e.DataSources.Add(new ReportDataSource("DataSet1", dt));
            x++;
        }


        public void ItemsSoldMonthlyReport_Load(DateTime startDate, DateTime endDate, ListBox.SelectedObjectCollection itemTypesTxt)
        {
            startDate = new DateTime(startDate.Year, startDate.Month, 1);
            endDate = new DateTime(endDate.Year, endDate.Month, 1);
            System.Collections.Generic.List<ReportParameter> paramList = new System.Collections.Generic.List<ReportParameter>();
            string itemTypes = null;
            reportViewer1.LocalReport.DataSources.Clear();
            StoreProject1.StoreDataSetTableAdapters.spGetItemsSoldReportTableAdapter commDt = new StoreProject1.StoreDataSetTableAdapters.spGetItemsSoldReportTableAdapter();
            List<string> itemsA = new List<string>();
            Dictionary<string, int> allItemTypes = new Dictionary<string, int>();
            DataTable ct = new DataTable();
            foreach (KeyValuePair<string, int> item in itemTypesTxt)
            {
                itemsA.Add(item.Key);
                allItemTypes.Add(item.Key, item.Value);
            }
            this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(CC_SubreportProcessingEventHandler);
            ReportParameter itemParam = new ReportParameter("itemType");
            ct = StoreProject1.ItemList.ConvertToDatatable(allItemTypes);
            string[] itemsArray = itemsA.ToArray();
            ReportDataSource _rsource = new ReportDataSource("SoldList", ct);
            reportViewer1.LocalReport.DataSources.Add(_rsource);

            itemParam.Values.AddRange(itemsArray);
            paramList.Add(itemParam);

            string sfdate = startDate.ToString("MM/yyyy");
            paramList.Add(new ReportParameter("pFromDate", sfdate, false));

            string stdate = endDate.ToString("MM/yyyy");
            paramList.Add(new ReportParameter("pThruDate", stdate, false));

            reportViewer1.LocalReport.ReportPath = @"C:/StoreProject1/ItemsSoldReport.rdlc";
            reportViewer1.LocalReport.SetParameters(paramList);
            this.reportViewer1.SetDisplayMode(DisplayMode.PrintLayout);
            this.reportViewer1.LocalReport.Refresh();
        }
    }
}

【问题讨论】:

  • 我对你上面提到的DataSet和DataTable感到困惑,但是对于这个简单的报告,为什么不使用列表而不是SubReport?
  • 我不确定您是否理解...报告不会总是有两个报告表。报告需要能够创建从 1 到 x 数量(可能多达 100 个)的此类报告表。创建的表的数量取决于用户从他们之前看到的屏幕中的列表框提示中选择了多少对象。报告需要动态生成空白数据集报告表(按所选项目的数量),然后在运行时由上面的代码填充。列表项会完成此操作吗?

标签: c# winforms reporting-services report-viewer2012


【解决方案1】:

抱歉,有点长。对于每个Report,我们有多种方法。如评论部分所述,我生成了相同(不完全但结果相同)的报告,其中包含以下逐步列表:

  1. 创建一个DataSet,一个表有7个Columns。

  1. 开始一个新的Report,在里面添加一个List的完整空间,然后在List里面添加7个TextBoxes(数据从Col1到Col 7)。

  1. 将那些TextBoxes 中的Visibility 设置为Show or hide based on an expression,以便在我们传递空字符串数据时隐藏它们:

文本框1:=IIF(Fields!Col1.Value="",TRUE,FALSE)

文本框2:=IIF(Fields!Col2.Value="",TRUE,FALSE)

TextBox3 到 7:=IIF(Fields!Col3.Value &amp; Fields!Col4.Value &amp; Fields!Col5.Value &amp; Fields!Col6.Value &amp; Fields!Col7.Value = "",TRUE,FALSE)

  1. 示例数据结构:

简单的:

class clsDataStruct
{
    public class ItemType
    {
        public string Name { get; set; }
    }

    public class Item
    {
        public string Name { get; set; }
        public ItemType Type { get; set; }
        public int Cost { get; set; }
        public int Prize { get; set; }
    }

    public class BillByItem
    {
        public DateTime DateSold { get; set; }
        public Item Item { get; set; }
    }
}
  1. Form 查看结果:

添加一个Form,一个ReportViewer 到那个Form,设置我们之前创建的Report 到那个ReportViewer。然后在FormLoad 事件中,添加一些代码来生成一些随机数据(这是你获取数据的地方)然后生成我们的Report

    //for data generation
    static Random rdn = new Random();

    //some list to hold data
    List<clsDataStruct.ItemType> lstItemType = new List<clsDataStruct.ItemType>();
    List<clsDataStruct.Item> lstItem = new List<clsDataStruct.Item>();
    List<clsDataStruct.BillByItem> lstBill = new List<clsDataStruct.BillByItem>();

    //this is what user choose to filter the report
    //user choose to report which item type
    List<clsDataStruct.ItemType> lstItemTypeByUser = new List<clsDataStruct.ItemType>();
    //date begin and end of report
    DateTime dteStart;
    DateTime dteEnd;

    private void Form1_Load(object sender, EventArgs e)
    {
        //create 3 ItemType
        for (int i = 1; i < 4; i++)
        {
            clsDataStruct.ItemType itt = new clsDataStruct.ItemType();
            itt.Name = "Item Type " + i.ToString();
            lstItemType.Add(itt);
        }

        //create 12 Item
        for (int i = 1; i < 13; i++)
        {
            clsDataStruct.Item item = new clsDataStruct.Item();
            item.Name = "Item " + i.ToString();
            item.Type = lstItemType[i % 3];
            item.Cost = rdn.Next(10);
            item.Prize = item.Cost + rdn.Next(5);
            lstItem.Add(item);
        }

        //create 30 BillByItem in next 3 month
        for (int i = 1; i < 31; i++)
        {
            clsDataStruct.BillByItem bill = new clsDataStruct.BillByItem();
            bill.DateSold = DateTime.Now.AddDays(rdn.Next(90));
            bill.Item = lstItem[rdn.Next(12)];
            lstBill.Add(bill);
        }
        //set the filters
        //add 2 random type to the filter
        lstItemTypeByUser.Add(lstItemType.Where(s => !lstItemTypeByUser.Contains(s)).ToList()[rdn.Next(lstItemType.Where(s => !lstItemTypeByUser.Contains(s)).ToList().Count)]);
        lstItemTypeByUser.Add(lstItemType.Where(s => !lstItemTypeByUser.Contains(s)).ToList()[rdn.Next(lstItemType.Where(s => !lstItemTypeByUser.Contains(s)).ToList().Count)]);
        //date start and end is one month from date we have data
        dteStart = DateTime.Now.AddDays(rdn.Next(60) - 30);
        dteEnd = DateTime.Now.AddMonths(3).AddDays(rdn.Next(60) - 30);

        this.reportViewer1.LocalReport.DataSources.Clear();
        dsReports.dtLyLichTrichNgangDataTable dtLyLichTrichNgang = new dsReports.dtLyLichTrichNgangDataTable();

        //Simple title, replace with yours
        dtLyLichTrichNgang.Rows.Add("ITEM INVENTORY SOLD " + dteStart.ToShortDateString() + " - " + dteEnd.ToShortDateString(), "", "", "", "", "", "");
        //empty row
        dtLyLichTrichNgang.Rows.Add(" ", "", "", "", "", "", "");

        DateTime dteFirstOfCycle;
        DateTime dteLastOfCycle;
        //cycle through months and fill data to datatable, maybe week or quarter
        for (dteFirstOfCycle = new DateTime(dteStart.Year, dteStart.Month, 1); dteFirstOfCycle < dteEnd; dteFirstOfCycle = dteFirstOfCycle.AddMonths(1))
        {
            dteLastOfCycle = dteFirstOfCycle.AddMonths(1).AddDays(-1);

            //take BillByItem in each month
            var billMonth = lstBill.Where(s => s.DateSold >= dteFirstOfCycle && s.DateSold <= dteLastOfCycle).OrderBy(s => s.DateSold);

            dtLyLichTrichNgang.Rows.Add("FROM " + dteFirstOfCycle.ToShortDateString() + " TO " + dteLastOfCycle.ToShortDateString(), "", "", "", "", "", "");
            //empty row
            dtLyLichTrichNgang.Rows.Add(" ", "", "", "", "", "", "");

            //cycle through each item type
            foreach (clsDataStruct.ItemType itt in lstItemTypeByUser)
                //have sold something
                if (billMonth.Where(s => s.Item.Type == itt).Count() != 0)
                {
                    //itemtype
                    dtLyLichTrichNgang.Rows.Add(itt.Name.ToUpper(), "", "", "", "", "", "");
                    //detail header
                    dtLyLichTrichNgang.Rows.Add("", "", "Name", "Cost", "Prize", "Profit", "Date Sold");
                    //cycle through each bill
                    foreach (clsDataStruct.BillByItem bill in billMonth)
                        dtLyLichTrichNgang.Rows.Add("", "", bill.Item.Name, bill.Item.Cost, bill.Item.Prize, bill.Item.Prize - bill.Item.Cost, bill.DateSold.ToShortDateString());
                    //total row
                    dtLyLichTrichNgang.Rows.Add("", "", "TOTAL", billMonth.Sum(s => s.Item.Cost), billMonth.Sum(s => s.Item.Prize), billMonth.Sum(s => s.Item.Prize - s.Item.Cost), "");
                }
                //sold nothing
                else
                {
                    dtLyLichTrichNgang.Rows.Add(itt.Name.ToUpper(), "", "", "", "", "", "");
                    dtLyLichTrichNgang.Rows.Add("Nothing sold", "", "", "", "", "", "");
                    //empty row
                    dtLyLichTrichNgang.Rows.Add(" ", "", "", "", "", "", "");
                }
            //empty row
            dtLyLichTrichNgang.Rows.Add(" ", "", "", "", "", "", "");
        }

        this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("dsLyLichTrichNgang", (DataTable)dtLyLichTrichNgang));
        this.reportViewer1.RefreshReport();
    }
  1. 结果:

通过对TextBoxBorderStyle 进行一些调整,您可以获得您想要的Report

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多