C# 使用使用相同数据集的多个报表表在VS2013报表查看器中创建报表
我需要在VS2013 report Viewer.net 4.5 C winforms应用程序中创建一个报告,该应用程序显示多个报告表。报表表需要使用相同的SQL存储过程来填充dt命名的数据集,只需改变返回的数据,根据这些数据从前面屏幕中的列表框提示符中选择项目。我正在尝试使用winforms应用程序中引用的本地报告模式.net程序集。下面是一个示例,说明了单个报告应该如何显示,以及我试图使用的代码来生成报告。我有两个rdlc文件,包含页眉和页脚的初始文件是ItemsSoldMonthlyReport_加载方法中链接的文件。另一个rdlc作为子报表嵌入在报表设计器中第一个报表文件的详细信息行中。ItemsSoldMonthlyReport_Load方法将itemType、pFromDate和pThruDate参数正确地传递给subreport方法。subreport方法是根据应用于“SoldList”数据集的项数启动的,这是正确的。使用CC_SubreportProcessingEventHandler中的GetData方法,为itemType参数中的每个项成功返回每个表的数据。为每个报表表的DataSet DataTable设置了正确的数据。但是,似乎DataSet DataTable只能作为ReportDataSource设置一次。当我尝试将加载了第二组数据的数据集设置为ReportDataSource时,不会发生错误,但第二个表(即:Cloth)的数据不会显示在最终报告中。相反,第一个数据表即:Toys在最终报告显示中显示两次。有可能做到我正在尝试的事情吗?如果有,我应该采取什么方法?我做了很多尝试,做了很多研究,但我自己却找不到答案。如果报表查看器完全无法生成这样的报表,有人能推荐一个成本不太高的替代方案吗?先谢谢你 报告应该是什么样子 我最近和最近尝试创建这样一个报告的代码C# 使用使用相同数据集的多个报表表在VS2013报表查看器中创建报表,c#,winforms,reporting-services,report-viewer2012,C#,Winforms,Reporting Services,Report Viewer2012,我需要在VS2013 report Viewer.net 4.5 C winforms应用程序中创建一个报告,该应用程序显示多个报告表。报表表需要使用相同的SQL存储过程来填充dt命名的数据集,只需改变返回的数据,根据这些数据从前面屏幕中的列表框提示符中选择项目。我正在尝试使用winforms应用程序中引用的本地报告模式.net程序集。下面是一个示例,说明了单个报告应该如何显示,以及我试图使用的代码来生成报告。我有两个rdlc文件,包含页眉和页脚的初始文件是ItemsSoldMonthlyRep
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();
}
}
}
对不起,有点长。对于每个报告,我们有多种方法。如评论部分所述,我生成的报告并不完全相同,但结果是相同的报告,列表如下: 创建一个数据集,其中一个表有7列。 开始一个新的报告,在其中添加一个完整的列表空间,然后在该列表中添加7个文本框,其中包含从Col1到col7的数据。 根据表达式将这些文本框的可见性设置为显示或隐藏,以便在传递emty字符串数据时隐藏它们: TextBox1:=iifields!Col1.Value=,TRUE,FALSE TextBox2:=iifields!Col2.Value=,TRUE,FALSE TextBox3到7:=iifields!Col3.值和字段!Col4.值和字段!Col5.值和字段!Col6.值和字段!Col7.Value=,TRUE,FALSE 示例数据结构: 简单一点:
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; }
}
}
查看结果的表单:
添加一个表单,一个ReportViewer到该表单,将我们以前创建的报表设置到该ReportViewer。然后在表单的加载事件中,添加一些代码以生成一些随机数据这是您获取数据的地方,然后生成我们的报告:
结果:
对TextBox的BorderStyle进行一些调整,您就可以得到所需的报告。我对上面提到的DataSet和DataTable感到困惑,但对于这个简单的报告,为什么不使用list而不是SubReport?我不确定您是否理解……报告并不总是有两个报告表。该报告需要能够创建从1到x的数量,可能多达100个这样的报告表。创建的表的数量取决于用户在之前看到的屏幕中从列表框提示符中选择的对象数量。报告需要根据所选项目的数量动态生成空白数据集报告表,然后在运行时由上述代码填充。列表项是否可以实现这一点?
//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();
}