最近处理完一个 asp.net 项目,其中有大量的报表需要操作。客户是一个开发区的财政局和企业。因此,这些报表都是财务报表。(做过报表的朋友们肯定知道报表中最复杂的就是财务报表,且不说是典型的中国式报表,更是分组报表、交叉报表、三维汇总报表等等。)如果采用常用的报表工具,比如:水晶报表、如意报表等等比较流行的 WEB 报表,几十份报表如果还搞不晕你的话,绝对会将宝贵的项目时间浪费在报表界面的绘制上面。
我们的客户群体有个特点,计算机操作水平一般般,但是一般对 Excel 的操作比较熟练,对报表的输出形式或者表现形式要求不大,但是报表的格式一定要符合他们日常的工作方式。因为他们的工作如果说有一个工具软件必不可少的话,那就是 MS Office (非国产的那些)。他们对 Excel 中的各种排版、样式几乎是了如指掌。如果你拿水晶报表或者如意报表之类的辛辛苦苦绘制的报表到他们跟前,他们肯定会拿你的辛苦杰作和他的电脑中的 Excel 文件甚至是 Word 文件进行对比,很有可能就会将你的报表指的头破血淋,因为他们的参考标准就是他们自己的 Office 文档。我相信,现在还没有一种报表工具做出来的报表可以和 Excel 或 Word 的灵活性进行比较(也许有些做报表的公司不服气了,别争了,呵呵!),因为 Word 或者 Excel 根本就不是报表工具而是办公软件!
经过对以上情况的分析,我决定在项目中采取 Excel 报表(严格的说 Excel 并不是报表工具,正如上所述)。同时采用样表的方式。这也是我在本文中最想提到的一点。为什么要采用样表呢?我们对 Excel 的掌握程度没有我们的客户研究的那么仔细,他们是专家(奉承的话,别告密哦, ^^ )。他们也许对报表的表现要求五彩斑斓,但是没有关系,交给我一份样表吧!(给我一份样表,我就可以撑起整个需求,仿自伽利略, ^^ )告诉我那个单元格填写什么,记住别再变的太多(要不我也没有办法,如果内容也经常变化的,不使用这种方法阿,事前申明!),其他的格式,线条,字体,颜色,合并,你愿意怎么变就怎么变!表单的内容照常进行数据库操作,添加、修改和删除均填写正常的表单,当然表单的格式没有必要和 Excel 的表单完全一样(要是一样也够累的),存放到你制定的数据库表中(可以修改,如果没有这个必要可以跳过这里以及后面会涉及到的地方)。在需要生成报表的地方,从数据库中提取相应的内容,打开样表,一个萝卜一个坑,填空吧,哈哈!竟是如此地简单。居然可以做出要多么漂亮有多么漂亮的表格,呵呵!
最后的报表要显示给用户看或者是要预览怎么办,直接让他去下载 Excel 文件吧,哈哈!(这样,用户看到的是他自己设计或者想要的 Excel 文件!八路的!好的!)
光说不做那行!以下是项目的实际例子!
1. 既然是 Excel 报表,要引用 Excel 组件,位置如下: E:\Program Files\Microsoft Office\Office\EXCEL9.OLB
2.ReportExcelData.cs 文件是专么用来处理 Excel 报表的自定义类, 30 多个方法, 4000 多行代码。
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
namespace wjk.ZHKCGA
{
///
1<summary>
2
3/// 专门处理 Excel 报表文件的类
4
5/// by wjk
6
7/// </summary>
public class ReportExcelData
{
private DBHelper myDBHelper=new DBHelper();
private Function myFunc=new Function();
private ApproveData myApprove=new ApproveData();
DBHelper.strctSqlParam[] myParam1 = new DBHelper.strctSqlParam[1];
string strSQL;
int ret,iCount;
Excel.ApplicationClass myApp;
Excel.Workbook myBook;
Excel.Worksheet mySheet;
public ReportExcelData()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
///
1<summary>
2
3/// 财政基建资金拨款申请表
4
5/// </summary>
///
1<param name="id"/>
材料编号
///
1<param name="strPath"/>
临时文件路径
///
1<param name="strUser"/>
创建临时文件的用户
///
1<returns>-1 样表不存在 ;1 成功; 0 失败 </returns>
public int WriteExcel_JJ_BoKuan(int id,string strPath,string strUniteCode,string strReportName,out string strErr)
{
strErr="";
#region 样表文件
string strSampleName="[ 样表 ] 基建资金拨款申请表 ";
string strSampleFile=strPath+"File\\ 样表 \"+strSampleName+".xls";
string strReportFile=strPath+"File\\ 报表 \"+strUniteCode+"\"+strReportName+".xls";
string strReportFileDB="\\File\\ 报表 \"+strUniteCode+"\"+strReportName+".xls";
if(!File.Exists(strSampleFile))
{
strErr=" 样表不存在 ";
return -1;
}
Directory.CreateDirectory(strPath+"File\\ 报表 \"+strUniteCode);
if(File.Exists(strReportFile))
File.Delete(strReportFile);
File.Copy(strSampleFile,strReportFile);
#endregion
#region 写文件
myApp=null;
myBook=null;
mySheet=null;
object oMissiong=System.Reflection.Missing.Value;
myApp=new Excel.ApplicationClass();
myApp.Visible=false;
myApp.Workbooks.Open(strReportFile,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong);
myBook=myApp.Workbooks[1];
mySheet=(Excel.Worksheet)myBook.ActiveSheet;
#region 一个萝卜一个坑
DataSet mySet;
strSQL="select 项目名称 , 项目计划总投资 , 年度计划投资 , 合同造价 , 财政已拨资金 , 项目单位财务支出 ,"+
" 项目单位资金结余 , 计划投资财政未拨数 , 项目单位本次申请拨款 , 财政部门拟定拨款 , 财政部门核定拨款 ,"+
" 备注 , 请款单位说明 , 请款单位签名 , 请款单位日期 , 请款单位负责人 , 财务负责人 , 项目负责人 , 联系电话 "+
"from 基建 _ 基建资金拨款申请表 where 材料编号 ="+id+" order by 序号 ";
ret=myDBHelper.RunSQLReturnDataSet(strSQL,out mySet,out iCount,out strErr);
if(ret==0) return 0;
//if(iCount<1) return -1;
int iRow=7; // 初始行号
for(int i=0;i
1<icount;i++) #endregion="" #region="" if(icount="" mysheet.cells[irow+i,10]="mySet.Tables[0].Rows[i][9].ToString();" mysheet.cells[irow+i,11]="mySet.Tables[0].Rows[i][10].ToString();" mysheet.cells[irow+i,12]="mySet.Tables[0].Rows[i][11].ToString();" mysheet.cells[irow+i,1]="mySet.Tables[0].Rows[i][0].ToString();" mysheet.cells[irow+i,2]="mySet.Tables[0].Rows[i][1].ToString();" mysheet.cells[irow+i,3]="mySet.Tables[0].Rows[i][2].ToString();" mysheet.cells[irow+i,4]="mySet.Tables[0].Rows[i][3].ToString();" mysheet.cells[irow+i,5]="mySet.Tables[0].Rows[i][4].ToString();" mysheet.cells[irow+i,6]="mySet.Tables[0].Rows[i][5].ToString();" mysheet.cells[irow+i,7]="mySet.Tables[0].Rows[i][6].ToString();" mysheet.cells[irow+i,8]="mySet.Tables[0].Rows[i][7].ToString();" mysheet.cells[irow+i,9]="mySet.Tables[0].Rows[i][8].ToString();" {="" }="" 写单元格="">0)
2
3{
4
5mySheet.Cells[16,9]=mySet.Tables[0].Rows[0][12].ToString();
6
7mySheet.Cells[17,10]=mySet.Tables[0].Rows[0][13].ToString();
8
9mySheet.Cells[17,12]=mySet.Tables[0].Rows[0][14].ToString();
10
11mySheet.Cells[19,2]=mySet.Tables[0].Rows[0][15].ToString();
12
13mySheet.Cells[19,5]=mySet.Tables[0].Rows[0][16].ToString();
14
15mySheet.Cells[19,8]=mySet.Tables[0].Rows[0][17].ToString();
16
17mySheet.Cells[19,11]=mySet.Tables[0].Rows[0][18].ToString();
18
19}
20
21mySet.Dispose();
22
23#region 合计内容
24
25strSQL="select sum( 项目计划总投资 ),sum( 年度计划投资 ),sum( 合同造价 ),"+
26
27"sum( 财政已拨资金 ),sum( 项目单位财务支出 ),sum( 项目单位资金结余 ),"+
28
29"sum( 计划投资财政未拨数 ),sum( 项目单位本次申请拨款 ),sum( 财政部门拟定拨款 ),"+
30
31"sum( 财政部门核定拨款 ) "+
32
33" from 基建 _ 基建资金拨款申请表 where 材料编号 ="+id;
34
35ret=myDBHelper.RunSQLReturnDataSet(strSQL,out mySet,out iCount,out strErr);
36
37if(ret==0) return 0;
38
39iRow=13; // 初始行号
40
41for(int i=0;i<iCount;i++)
42
43{
44
45#region 具体参数
46
47mySheet.Cells[iRow+i,2]=mySet.Tables[0].Rows[i][0].ToString();
48
49mySheet.Cells[iRow+i,3]=mySet.Tables[0].Rows[i][1].ToString();
50
51mySheet.Cells[iRow+i,4]=mySet.Tables[0].Rows[i][2].ToString();
52
53mySheet.Cells[iRow+i,5]=mySet.Tables[0].Rows[i][3].ToString();
54
55mySheet.Cells[iRow+i,6]=mySet.Tables[0].Rows[i][4].ToString();
56
57mySheet.Cells[iRow+i,7]=mySet.Tables[0].Rows[i][5].ToString();
58
59mySheet.Cells[iRow+i,8]=mySet.Tables[0].Rows[i][6].ToString();
60
61mySheet.Cells[iRow+i,9]=mySet.Tables[0].Rows[i][7].ToString();
62
63mySheet.Cells[iRow+i,10]=mySet.Tables[0].Rows[i][8].ToString();
64
65mySheet.Cells[iRow+i,11]=mySet.Tables[0].Rows[i][9].ToString();
66
67#endregion
68
69}
70
71#endregion
72
73#endregion
74
75myBook.Save();;
76
77myBook.Close( true,strReportFile,true);
78
79//myApp.Quit();
80
81System.Runtime.InteropServices.Marshal.ReleaseComObject(mySheet);
82
83System.Runtime.InteropServices.Marshal.ReleaseComObject(myBook);
84
85System.Runtime.InteropServices.Marshal.ReleaseComObject(myApp);
86
87GC.Collect();
88
89#endregion
90
91#region 写数据库
92
93string strDate=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
94
95strSQL="update 附件表 set 路径 ='"+strReportFileDB+"', 类型 ='.xls', 日期 ='"+strDate+"', 操作者 ='"+strUniteCode+"' where 序号 ="+id;
96
97return myDBHelper.RunSQL(strSQL,out strErr);
98
99#endregion
100
101}
102
103/* 以下省去 30 个类似的操作例子 */
104
105}
106
1073.Excel2000 和 Excel2002 对 Excel 的引用对象是不一样的,一个是 EXCEL9.OLB ;另一个是 EXCEL10.OLB ;分别到相应的目录下去引用即可!同时, Excel2000 和 Excel2002 下面的参数是不一样的。 Excel2000 下面的参数少一个,将 oMissiong 干掉一个就 OK (这么简单阿!)。
108
1094\. 操作 Excel 的时候,可能会发生 Excel 进程被锁定,无法退出,解决方法</icount;i++)>