ExcelQuicker模板功能的高级应用示例——薪资报表
在广大网友的支持下,ExcelQuicker V2.2发现了两个BUG,在发这篇文章的同时Release新版本ExcelQuicker,版本号:2.2修订版。
主要修正,
1、EQWebKit中取得相对路径;
2、EQTable的InsertMode=true时的数据导出
ExcelQuicker模板功能的高级应用——薪资报表
这张薪资报表的需求原型是如下
(图1)
数据表Schema如下
Employee
Position
Salary
Bonus
这些信息是直接导出到上表中的前四列,另外:
(1) Insurance为Salary的18%;
(2) Tax的计算方式如个人所得税计算方式,阶梯型计算,以除去Insurance后的Salary加上Bonus为扣税基数
(3) Housing Income,住房公积金帐户,为Salary的14%
(4) Income=Salary+Bonus-Insurance-Tax+Housing Income
收入=基本工资+奖金-四金-税+住房公积金(虽然还有养老保险、医保等,但养老保险是几十年后的事情,医保太少,这里就不计入了^_^)
Employee-Income列表下方的:
Salary Expenditure为所有员工的工资+Bonus
Insurance Expenditure为公司为所有员工交纳的四金,为员工基本工资的44%
Total为上两项总和
由于四金和税的计算方式变化很快,根据用户需要,要做的很灵活,能够对需求的变更做出快速响应,甚至是现场解决,基于此,把四金和税的计算放在C#中硬编码明显不符合用户的需要。这套报表使用ExcelQuicker来实现,我选择了在模板上实现这些计算功能,以便在需求变更时,能够直接修改Excel模板文件。
我们知道在Excel中,是支持Formula公式的,对于一行Employee-Salary记录的设置或许不难,我简单描述如下,
(图2)
设置Insurance单元格”= C5*
这样就完成了一行的设置,看看我的模板行吧,
(图3)
(也就是说,只要在这行列中输入Salary、Bonus后,就会自动显示Insurance、Tax、Housing Income和Income数据。)
在实际编码中,我们会从数据库得到Employee,Position,Salary和Bonus四列的DataTable数据集,它对应于ExcelQuicker中的EQTable对象,EQTable的主要作用是将Datagrid或者DataTable导出到报表中,它有一个属性叫InsertMode,意为是否是插入模式,当设置为true时,它会将整个DataTable对象插入到Excel中指定的一行(其实现原理是不断的复制该行,使其行数与需要导出的行数一样时,再导出每一行数据)。
EQTable tableEmployee = new EQTable(dt, 5, 1);//dt是DataTable对象
tableEmployee.InsertMode = true;
上面语句的意思是将dt导出到Excel中的第5行第1列(该行为我们设置的上述模板行),使用插入模式。
这样,在导出时,ExcelQuicker会自动复制该模板行,并将其应用到DataTable数据集中的每一行数据,这样就完整的显示了整个Employee-Salary列表
我们注意到列表下方还有Salary Expenditure,Insurance Expenditure和Total,它们的定义这里不再累述。
在模板中,我设置
Salary Expenditure = SUM(C5:C6)+SUM(D5:D6)
Insurance Expenditure = SUM(C5:C6)*0.42
Total =SUM(B7,B8)
这里需要说明一下,为什么是设置C5:C6呢?
因为EQTable对象是插入到C5:C6,而Excel高级的地方在于,当有插入是,它会自动改变公式的计算范围,实际上对于上述的Salary Expenditure = SUM(C5:C6)+SUM(D5:D6)就会因为插入的EQTable而动态的改变公式为= SUM(C5:CRow)+SUM(D5:DRow),同样Insurance Expenditure,Total也会改变随着Employee-Salary数据的插入而改变公式。
在理解上上面的Excel模板原理后,我们来看看剩下的C#编码
DataTable dt = DataEntity.GetEmployees();
//Set excel template document
string strTemplate = "Sample6.xls";
//Get the output report file name from ExcelQuicker dynamically.
string strFileName = EQWebKit.GenerateAutoFileName();
//Construct EQApplication object
EQApplication objApp = new EQApplication(strFileName, strTemplate, true);
//Declare and set the name of worksheet
EQWorksheet objWS = new EQWorksheet("Salary");
//Set the report month-year
objWS.Add(new EQCell(DateTime.Now.ToString("yyyy-MM"), 2, 2));
//Construct EQTable object to output variable dt
EQTable tableEmployee = new EQTable(dt, 5, 1);
tableEmployee.InsertMode = true;
objWS.Add(tableEmployee);
objApp.Add(objWS);
objApp.Output();
这样,当我们的算法发生改变需要调整时,我们只需要调整Excel模板中的公式即可,完全没有必要编译工程,甚至稍微对Excel精通一点的客户也可以自己解决。
该示例可以在最新的ExcelQuicker Web Sample 6中找到
http://220.165.4.133:81/ControlAndSource/ExcelQuicker_Source.rar
http://220.165.4.133:81/ControlAndSource/ExcelQuicker_Web_Sample.rar

浙公网安备 33010602011771号
评论
excel的小计和分组同实际报表输出有很大的差异,至于分页,更是差别很大 ,你能和对这个系统功能作个对比吗?
http://www.afalinasoft.com/active-xl-report/ 回复
但是作为一款Open Source的项目,我想说的是它本身应该属于每个人使用它的人,如果你有新的创意、修改,你可以修改它,如果你愿意与大家共享,可以Mail我,我会Release出新版本。
国人在这方面做的很不好,Open Source对于大部分人只是开源,能够拿到源码,使用上心理更有底气,而不是去参与它的建设。
ExcelQuicker同时在CodeProject、SourceForge上发布,却有很多国外朋友一起探讨怎么进行优化和提高,其实这是Release的2.2修订版,正是一位来自South American的朋友发现的问题。国人的反馈只有怎么用怎么配置、要和什么什么商业项目做对比等,其实我想说的是,作为开源项目是需要更多的人去维护,需要自己的参与,想想作为一个免费的东西,作者我的精力是有限的,我不可能辞掉工作时时专注于此,所以,我认为需要更多人去维护它、参与它的开发,否则,失去了开源的意义。 回复
如果仅仅专注于导出,这个项目并没有什么意义
验证excelquicker是否实用,拿它去做一个进销存的报表即可,现在这种情形,显然是用不起来的 回复
既然有人在使用和关注,我想会有它存在的价值,其他我就不多说了。 回复
回复
-----------------------------------
to dd:
請尊重別人的勞動成果,在尊重別人的同時,也就是尊重你自己 回复
连接受别人评论的勇气也没有吗? 不要忘了excelquicker标称为报表方案!是报表方案,就要拿出点报表功能来
其实,就报表而言,还不如progame 的那个vb小程序实用呢
花时间写这些东西,就是对作者最好的尊重,要不,我才不看呢
回复
To dd,我的确标称为ExcelQuicker报表方案,因为它对我所经历的项目而言,的确就是报表方案,我和以前现在的同事做过的6个系统都是基于这种方案,并且有效的提高了开发效率,也赢得了用户的喜爱。曾经一个User就这么说,为什么你们以前的报表不做得和这个(系统)的(使用ExcelQuicker)一样呢?
而且,ExcelQuicker本身就是为了产生报表,所以,我个人认为叫它为方案并不过分。 回复
tableEmployee.InsertMode = true;
上面语句的意思是将dt导出到Excel中的第5行第1列(该行为我们设置的上述模板行),使用插入模式。 */
这样一来 数据和模板之间还是有依赖性的 数据无法和view分离开来 回复
我以前做过类似的东西,不过没有做完,我是这样做得, 通过一个报表定义的表,指出报表的模板,需要填充的行列,需要的字段. 不知道有没有用 回复
Why I always get error:
exp.Message = "Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046} failed due to the following error: 80070005."
when I run websample1 to:
this.ReportFiles = objApp.Output();
I have already add asp.net to administrators 回复
未将对象引用设置到对象的实例
是什么原因啊!!! 回复
1、我将移到Delphi2005中使用,发现EQRange.Create(value:array of array of object,...)函数第一个参数用不起来,只要修改源码,加了一个新函数;
2、EQWebKit中GetRelativeFileName(string fileName)函数有一个小bug, “pos = strFileName.IndexOf(strApplicationName);”有可能pos=-1,这种情况下一句可能出现文件名前面几个字符会被截掉,加下下面一句话后一切OK,"if (pos > -1 )"
3、EQCell我没有找到读取功能,我想打开已经存在的Excel文件,再进行读取其中的内容,请大家帮助一下? 回复