WinForm界面开发之酒店管理系统--报表篇 - 伍华聪

时间:2024-04-15 08:45:19

WinForm界面开发之酒店管理系统--报表篇

报表模块几乎是各种大小管理系统都是必不可少的一个模块,而往往报表都需要有数据查看、打印、导出、数据汇总等方面,原本我在准备做酒店管理系统的时候,曾经考虑过试用ActiveReport报表控件的,因为我以前的送水管理系统就是采用这个来做报表的,因此曾经写过一篇文章《ActiveReport报表开发---谈谈ActiveReport的中文化问题 》,提前为做中文报表做准备。

做ActiveReport的报表,大致需要下面几个步骤,设计好报表表现内容的文件,设计一个通用的窗体用来实现Preview功能的报表查看窗体,再设计一个通用的报表函数进行统一调用,如下所示:

代码
        /// <summary>
        
/// 提供通用的打印函数
        
/// </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进度条控件。

代码
        private void KFTopTradeReport_Load(object sender, EventArgs e)
        {
            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"));

        }

 

 

然后在所需要的地方,如按钮、更新操作,调用下面的函数就可以了。

代码
        private void BindItemCateData()
        {
            
#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>
        
/// 获取贸易排行报表
        
/// </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

如果你有好的建议或想法,欢迎大家进行沟通交流。