Excel为发人员提供了强大的外部接口,方便开发人员进行二次开发。最近笔者就采用excel 的automation技术成功地解决了excel报表的自动生成功能.
首先给大家介绍一下报表创建模块的组成,如下图所示 模版文件。由于笔者设计的报表都是周期性的固定报表,做成模版更适合数据的读写操作和图表的生成,所以将全部的报表归纳整理生成了几类模版。 模版描述文件。主要纪录数据写在那个行那个列,那个图表对应什么类型的数据。它跟随模版文件的变更一起变更,时刻与模版文件保持同步,这样可以不必修改程序就能够更改输出报表的格式。 数据源描述文件。主要描述对应文件的源数据所在的那种数据库。 接下来给大家介绍一下程序操作excel的流程: 一、插入类型库 1、 在一个已有的MFC工程按Ctrl + W 弹出ClassWizard对话框。 2、 Add Class.../From a type Library... 在 Office 目录中,找到你想使用的Excel类型库。若你安装的是Offce2000则选择安装目录下的EXCEL9.OLB文件进行倒入,生成的倒入文件名称叫做excel9.h和excel9.cpp;若你安装的时office2003则选择。选择安装目录下EXCEL.exe进行到入,生成的倒入文件时excel.h和excel.cpp。两者的部分接口有所不同。 3、 在弹出的对话框中选择要添加的类,具体选那些类要根据实际情况而定。当然你也可以全选 说明:类型库会给出Excel的全部接口类,可以根据需要挑选自己需要的类,但是一般情况下的EXCEL文的操作都会涉及以下的几个类:_Application、WorkBooks、_WorkBook、WorkSheets、_WorkSheet、Range。若涉及图表的操作还会涉及如下的几个类:ChartObjects、ChartObject、_Chart、Series 二、服务的启动和关闭 服务器的启动
_Workbook excelBook;
Worksheets excelSheets; _Application excelApp; BOOL CreateApplication() ...{ if (!excelApp.CreateDispatch('Excel.Application',NULL)) ...{ AfxMessageBox('创建Excel服务失败!'); return FALSE; } excelApp.SetVisible(FALSE); excelApp.SetDisplayAlerts(FALSE); return TRUE; } 说明: 在此之前要添加CoInitialize(NULL)函数初始化Com接口。 关键词'Excel.Application'是启动Excel的COM服务的唯一标示。 SetVisible函数表示运行的进程是否可见。 SetDisplayAlerts函数表示是否忽略警告信息,比如提示“文件xxx.xls已经存在是否覆盖?”,若SetDisplayAlerts的参数为FALSE则不出现提示信并默认覆盖。 服务的关闭
void DestroryApplication()
...{ excelApp.Quit(); excelApp.ReleaseDispatch(); } 三、文件的打开与保存 文件的打开
BOOL Open(char* pFileName)
...{ Workbooks excelBooks; excelBooks.AttachDispatch(excelApp.GetWorkbooks()); LPDISPATCH lpDisp = excelBooks.Add(SV(pFileName)); if(lpDisp == NULL) return FALSE; excelBook.AttachDispatch(lpDisp); excelSheets.AttachDispatch(excelBook.GetWorksheets()); return TRUE; } 文件的保存
void Save(char* pFile,_Worksheet exceSheet)
...{ exceSheet.SaveAs(pFile,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing, vtMissing,vtMissing,vtMissing); } 说明: 对于文件的保存2000版和2003版有所区别,2000版比2003版少了一个参数。 四、操作的退出 上面提到得服务的退出不代表文件就关闭了,当服务停止后内存中依然驻留着一个Excel.exe进程必须杀掉该进程才算完整的退出。实现代码如下:
KillProgram(“Excel.exe”);
BOOL CALLBACK EnumWinProc(HWND hwnd, LPARAM lParam) ...{ DWORD dwID; GetWindowThreadProcessId(hwnd,&dwID); if(dwID == (DWORD)lParam) ...{ PostMessage(hwnd, WM_QUIT, 0, 0); return FALSE; } return TRUE; } void KillProgram(LPCSTR ExeName) ...{ LPCSTR File; HANDLE hProcessSnap; PROCESSENTRY32 pe32; MODULEENTRY32 me32; if(!ExeName || !ExeName[0]) return; File = strrchr(ExeName, '/'); if(File!=0) ExeName = File + 1; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == (HANDLE)-1) return; memset(&pe32, 0, sizeof(pe32)); pe32.dwSize = sizeof(PROCESSENTRY32); if(Process32First(hProcessSnap, &pe32)) ...{ do ...{ memset(&me32, 0, sizeof(me32)); me32.dwSize = sizeof(me32); File = strrchr(pe32.szExeFile, '/'); File = File ? File+1 : pe32.szExeFile; if(strcmpi(File,ExeName) == 0) EnumWindows((WNDENUMPROC)EnumWinProc, pe32.th32ProcessID); } while(Process32Next(hProcessSnap,&pe32)); } CloseHandle(hProcessSnap); } |
|