报表模块几乎是各种大小管理系统都是必不可少的一个模块,而往往报表都需要有数据查看、打印、导出、数据汇总等方面,原本我在准备做酒店管理系统的时候,曾经考虑过试用ActiveReport报表控件的,因为我以前的送水管理系统就是采用这个来做报表的,因此曾经写过一篇文章《ActiveReport报表开发---谈谈ActiveReport的中文化问题 》,提前为做中文报表做准备。
做ActiveReport的报表,大致需要下面几个步骤,设计好报表表现内容的文件,设计一个通用的窗体用来实现Preview功能的报表查看窗体,再设计一个通用的报表函数进行统一调用,如下所示:
/// 提供通用的打印函数
/// </summary>
/// <param name="rpt1"></param>
/// <param name="ds"></param>
public void PrintPreview(ActiveReport3 rpt1, ref DataSet ds)
{
try
{
FrmPrintPreview frm = new FrmPrintPreview();
frm.StartPosition = FormStartPosition.CenterScreen;
// frm.Dock = DockStyle.Fill;
// frm.WindowState = FormWindowState.Maximized;
frm.Show();
rpt1.DataSource = ds.Tables[0];
// rpt1.DataMember = cmbQuery.Text;
rpt1.Run();
frm.arvMain.Document = rpt1.Document;
}
catch (Exception ex)
{
MessageUtil.ShowError(ex.Message);
}
}
这样通过报表文件和界面的数据源,就可以实现报表的显示了。
不过由于这种方式,必须为每个报表都设计一个报表文件,如下所示。
最后得到的报表界面大致如下所示。
使用这个ActiveReport来实现我的报表功能的话,这样如果我的报表非常多,那么这个工作量就比较吓人了,最后还是放弃了这种方式,采用了改造我的分页控件的方式来实现,既可以方便数据的展示,有可以继承了报表预览打印、导出等功能,而且这样做的好处就是,我省却了不用设计那么多报表格式文件的时间,并且总体效果也非常不错。
在我前面的文章有介绍过Winform分页控件的内容《WinForm界面开发之“分页控件” 》,该控件集成了分页、导出Excel、打印、右键菜单等操作,我唯一需要改造的主要就是不用分页功能,然后在增加一些细微的修改就可以了。先看看我的酒店管理系统中的一些报表界面吧。
总体上就是我们一般报表所需要的功能。其中报表打印预览可以设置报表标题,打印的列也可以设定,有一些字段的汇总功能,而且这样的报表基本上不需要额外的代码就能实现(相对分页控件来说)。
下面我们来看看我这个控件大致的代码实现。
首先在Form窗体初始化的时候,指定该控件所需要的一些载体,如空的菜单控件、空的Progressbar进度条控件。
{
InitDictItem();
this.winGridView1.ProgressBar = this.toolStripProgressBar1.ProgressBar;
this.winGridView1.AppendedMenu = this.contextMenuStrip1;
this.dtStart.Value = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00"));
this.dtEnd.Value = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59"));
}
然后在所需要的地方,如按钮、更新操作,调用下面的函数就可以了。
{
#region 添加别名解析
this.winGridView1.AddColumnAlias("Rank", "名次");
this.winGridView1.AddColumnAlias("ItemName", "项目名称");
this.winGridView1.AddColumnAlias("Price", "商品单价");
this.winGridView1.AddColumnAlias("Quantity", "销售数量");
this.winGridView1.AddColumnAlias("OriginalAmount", "销售总额");
this.winGridView1.AddColumnAlias("OfferMoney", "优惠金额");
this.winGridView1.AddColumnAlias("Amount", "折后金额");
#endregion
#region 条件检索
SearchCondition condition = new SearchCondition();
condition.AddCondition("ItemType", this.txtStatisticItem.Text, SqlOperator.Like)
.AddCondition("BeginTime", this.dtStart.Value.ToString(), SqlOperator.MoreThanOrEqual)
.AddCondition("BeginTime", this.dtEnd.Value.ToString(), SqlOperator.LessThanOrEqual);
string filter = condition.BuildConditionSql();
int topCount = Convert.ToInt32(this.txtTopCount.Text);
#endregion
DataTable dt = BLLFactory<ConsumerList>.Instance.GetTopTradeReport(topCount, filter);
int i = 1;
foreach (DataRow row in dt.Rows)
{
row["Rank"] = i++;//修改名次信息
}
#region 增加汇总信息
if (dt.Rows.Count > 0)
{
DataRow dr = dt.NewRow();
dr["ItemName"] = string.Format("项目数:{0}", dt.Rows.Count);
decimal Price = 0M;
decimal Quantity = 0M;
decimal OriginalAmount = 0M;
decimal OfferMoney = 0M;
decimal Amount = 0M;
foreach (DataRow row in dt.Rows)
{
Price += Convert.ToDecimal(row["Price"]);
Quantity += Convert.ToDecimal(row["Quantity"]);
OriginalAmount += Convert.ToDecimal(row["OriginalAmount"]);
OfferMoney += Convert.ToDecimal(row["OfferMoney"]);
Amount += Convert.ToDecimal(row["Amount"]);
}
dr["Price"] = Price;
dr["Quantity"] = Quantity;
dr["OriginalAmount"] = OriginalAmount;
dr["OfferMoney"] = OfferMoney;
dr["Amount"] = Amount;
dt.Rows.Add(dt.NewRow());
dt.Rows.Add(dt.NewRow());
dt.Rows.Add(dr);
}
#endregion
this.winGridView1.DataSource = dt.DefaultView;
this.winGridView1.PrintTitle = Portal.gc.gAppUnit + " -- " + "客房按项目类别统计报表";
}
以上代码,和分页控件一样,就是对显示的字段进行中文的转义显示,构造查询条件并检索数据,汇总报表内容,然后绑定到自定义控件上,就可以了。
其中检索的代码大致如下所示就可以了,返回的DataTable,当然,如果你的数据源是实体类集合,如List<MyInfo>()的格式数据源,一样正常显示的。
/// 获取贸易排行报表
/// </summary>
/// <param name="condition"></param>
/// <returns></returns>
public DataTable GetTopTradeReport(int topCount, string condition)
{
string sql = string.Format(@"select top {0} '0' as Rank, ItemName, Price,
sum(Quantity) Quantity,sum(Price*Quantity) OriginalAmount,sum((Price-DiscountPrice)*Quantity) OfferMoney,sum(Amount) Amount
from KF_ConsumerList {1} And ItemName <> '部分结账'
group by ItemName,Price order by Sum(Quantity) DESC", topCount, condition);
return base.SqlTable(sql);
}
我们说看到的就是,基本上所有的报表展示,都不需要关注报表预览的问题,只是关注如何在GridView控件中显示就可以了,因为打印和导出,都是集中管理的。
最后,呈上我所封装的控件,大家可以直接过来使用就可以了,没有任何限制。
分页控件、报表显示控件:https://files.cnblogs.com/wuhuacong/WinformControl.rar
如果你有好的建议或想法,欢迎大家进行沟通交流。