MFC中操作word和excel.doc
-作者xxxx-日期xxxxMFC中操作word和excel【精品文档】应用程序运行界面如图所示:一、首先在VC6.0中创建MFC应用程序,类型为基本对话框,MFC库选静态的DLL(否则编译之后在其他电脑上无法运行),其他选项默认。然后按Ctrl+W调出MFC类向导,从Word和Exce的安装根目录下导入Word和Excel的库(word:MSWord.dll,Excel:excel.exe(选全部文件下拉列表才能看到),然后分别导入Word中的四个类( _Application,Documents,_Document,Range)和Excel中的五个类(_Application,Workbooks,Worksheets,_Workbook,_Worksheet,Range),注意导入Excel中的_Application和Range类时要重命名(_Application_Excel,Range_Excel),要不然和Word导入的类重名了。 /*/ /* 工程名为Nichole7 */ /*/二、首先在CNichole7App:InitInstance()中最前面加入: /*/ /* 初始化COM库 */ /*/ if (:CoInitialize(NULL) != S_OK) AfxMessageBox("初始化COM支持库失败!"); exit(1); 然后在return FALSE前面加入:/*/ /* 释放COM库*/ /*/ :CoUninitialize();三、头文件#include "msword.h" /与Word操作相关的类#include "excel.h" /与Excel操作相关的类#include "afxtempl.h" /CMap类的头文件#include <AtlBase.h> /新增加了一个头文件,为使用CComVariant替代VARIANT做准备/*2.添加excel的类时,要改名,要不然_Application和Range类会重定义(因为word里也会添加进有同样的类)*/#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif#define LINE_SIZE 100 /Word行数(以换行符分隔)#define EXCEL_SIZE 50 /Excel的单元格数#define ITEM_COUNT 10 /歧义词最多项数BOOL InitWord(_Application &wordApp);BOOL InitExcel(_Application_Excel &_app);int Split(char *token,CString strs,CString *str,char *seps);void ExtractString(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap,CMap<CString, LPCTSTR, CString, LPCTSTR> &ItemMap,const CString strs,/*const CString seps=":"*/ const CString seps);BOOL OpenExcelFile(LPCTSTR xlsFileName,_Application_Excel &_app,LPDISPATCH &lpDispatch,Workbooks &_books,_Workbook &_book,Worksheets &_sheets);BOOL GetCurrentSheet(LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet);int GetInsertPoint(LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet,Range_Excel &_range);CString GetCellValue(LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet,Range_Excel &_range,long row,long col);BOOL WriteExcel(CString strValue,LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet,Range_Excel &_range,long row,long col);void InitStringMap(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap);CString FindValue(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap,CString &key);void FindKeys(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap,CString *keys,CString &value);四、在Nichole7Dlg.cpp中加入如下代码:/*/* 主要的读取和写入过程都在此函数内完成,点击“写入Excel”按钮时调用*/*/void CNichole7Dlg:OnOK() / TODO: Add extra validation here CString wFileName,eFileName;/*/* m_wName,m_eName分别是两个编辑框的控件变量 */*/ m_wName.GetWindowText(wFileName); m_eName.GetWindowText(eFileName); if (wFileName.IsEmpty() AfxMessageBox("请选择Word文档!"); else if (eFileName.IsEmpty() AfxMessageBox("请选择Excel文档!"); else CFileFind finder; BOOL bResult1,bResult2; bResult1=finder.FindFile(wFileName); bResult2=finder.FindFile(eFileName); if (!bResult1) AfxMessageBox("指定的Word文件不存在!"); return; /return与exit(1)的不同,后者退出整个应用程序 else if (!bResult2) AfxMessageBox("指定的Excel文件不存在!"); return; /定义变量 _Application wordApp; Documents docs; _Document doc; Range aRange; /操作Word COleVariant vTrue(short)TRUE),vFalse(short)FALSE),vOpt(long)DISP_E_PARAMNOTFOUND, VT_ERROR); if (InitWord(wordApp)=false) AfxMessageBox("初始化Word支持库失败!"); exit(1); docs=wordApp.GetDocuments(); doc=docs.Open(COleVariant(wFileName),vFalse,vTrue,vFalse,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt); aRange=doc.Range(vOpt,vOpt); /AfxMessageBox(aRange.GetText();/这里GetText得到的就是word文件的纯文本了,你可以将其写到txt文件中 CString strs=aRange.GetText(); /这里GetText得到的就是word的纯文本了,你可以将其写到txt文件中 char *token=NULL; CString strLINE_SIZE; char seps="r" /不能用"n",不知为何? int line_size=Split(token/*需要初始化*/,strs,str,seps); CMap<CString, LPCTSTR, CString, LPCTSTR> stringMap; CMap<CString, LPCTSTR, CString, LPCTSTR> ItemMap; /保存从Word返回的键-值对 InitStringMap(stringMap); const CString stops=":" for (int i=0/*退出for循环时,i仍然存在*/; i<line_size; i+) ExtractString(stringMap,ItemMap,stri,stops); aRange.ReleaseDispatch(); doc.ReleaseDispatch(); docs.ReleaseDispatch(); VARIANT SaveChanges,OriginalFormat,RouteDocument; /定义调用QUIT时使用的参数 SaveChanges.vt=VT_BOOL; /设置退出WORD时候的保存参数 SaveChanges.boolVal=VARIANT_FALSE; /为不保存任何文档,模板及设置 :VariantInit(&OriginalFormat); /清空变量 RouteDocument.vt=VT_EMPTY; /清空变量的另一种方法 /*/ /* 采用注释掉的方法会出现:vc调用并关闭word时,提示“此文件正由另一个应用程序或用户使用” * 解决办法是将wordApp.Quit()里的三个参数更改一下 */ /*/ /wordApp.Quit(vOpt,vOpt,vOpt); wordApp.Quit(&SaveChanges,&OriginalFormat,&RouteDocument); wordApp.ReleaseDispatch(); /定义变量 _Application_Excel _app; Workbooks _books; Worksheets _sheets; _Workbook _book; _Worksheet _sheet; Range_Excel _range; LPDISPATCH lpDispatch; /操作Excel if (InitExcel(_app)=false) AfxMessageBox("初始化Excel支持库失败!"); exit(1); /打开Excel文件 if (!OpenExcelFile(eFileName,_app,lpDispatch,_books,_book,_sheets) AfxMessageBox("打开Excel失败!"); exit(1); /得到第一行的值,保存在strArray0.j-2中 CString strArrayEXCEL_SIZE; CString strTemp; for (int j=1;j+) strTemp=GetCellValue(lpDispatch,_book,_sheet,_range,1,j); strTemp.TrimLeft(); strTemp.TrimRight(); if (strTemp.GetLength()=0) break; else strArrayj-1=strTemp; /得到写入Excel的位置 int insertPoint=GetInsertPoint(lpDispatch,_book,_sheet,_range); /将Word中读出的内容写入Excel指定开始位置 CString strMap; for (int k=0;k<=j-2;k+) CString strValue; strMap=strArrayk; ItemMap.Lookup(LPCTSTR)strMap,strValue/*保存返回值*/); strValue.TrimLeft(); strValue.TrimRight(); WriteExcel(strValue,lpDispatch,_book,_sheet,_range,insertPoint,k+1); /_book.SaveCopyAs(COleVariant("D:1.xls"); /相当于另存为 /相当于excel菜单的保存 COleVariant covOptional(LONG)DISP_E_PARAMNOTFOUND,VT_ERROR); /_book.SetSaved(true); _app.SetVisible(true); _app.SetUserControl(true); _book.SaveAs(COleVariant(eFileName),covOptional,covOptional, covOptional,covOptional,covOptional,(long)0, covOptional,covOptional,covOptional,covOptional,covOptional); _range.ReleaseDispatch(); _sheet.ReleaseDispatch(); _sheets.ReleaseDispatch(); /*/ /* 我们使用CComVariant替代VARIANT,CComVariant是一个模板类。 * 在定义的时候直接调用带参数的构造函数,比VARIANT使用简单得多 * CComVariant SaveChanges(false),OriginalFormat,RouteDocument; * 使用CComVariant的不带参数的构造函数,默认就是使用VT_EMPTY,设置为空类型 * 另外,除了CComVariant,你还可以使用COleVariant和_variant_t,但我个人最喜欢前者 */ /*/ CComVariant SaveChanges1(false),OriginalFormat1,RouteDocument1; /*/ /* 为了达到保存后不关闭Excel,故将以下代码全部注释掉,也即不关闭工作簿_book和应用程序_app * 但是这样也没有出现再次写入初始化_app失败的情况,若有此可以在InitExcel里将_app先关闭再打开 */ /*/ /_book.Close(SaveChanges1,OriginalFormat1,RouteDocument1); /_book.ReleaseDispatch(); /_books.ReleaseDispatch(); /要想彻底关闭excel进程,必须把_app.Quit()放在_app.ReleaseDispatch()之前 /_app.Quit(); /_app.ReleaseDispatch(); AfxMessageBox("成功写入Excel,文件位于:"+eFileName+"目录下!"); /CDialog:OnOK();/*/* 创建Word服务器 */*/BOOL InitWord(_Application &wordApp) /创建Word服务器(启动Word) if (!wordApp.CreateDispatch("Word.Application",NULL) AfxMessageBox("创建Word服务失败!"); return false; wordApp.SetVisible(true); /设置Word可见 wordApp.SetDisplayAlerts(false); /屏蔽vc关闭word时跳出的保存对话框 return true;/*/* 创建Excel服务器 */*/BOOL InitExcel(_Application_Excel &_app) /创建Excel服务器(启动Excel) if (!_app.CreateDispatch("Excel.Application",NULL) AfxMessageBox("创建Excel服务失败!"); return false; _app.SetVisible(true); /将excel设为可见 _app.SetUserControl(true); /设置是否可以让其它用户操作 _app.SetDisplayFullScreen(false); _app.SetDisplayAlerts(false); /屏蔽vc关闭excel时跳出的保存对话框 return true;/*/* 将word内容以换行符分隔开来,分开后的内容保存在一个数组str中*/*/int Split(char *token,CString strs,CString *str,char *seps) int count=strs.GetLength(); token=strtok(strs.GetBuffer(count),seps); str0.Format("%s",token); int i=1; while (true) token=strtok(NULL,seps); if (token=NULL) break; stri.Format("%s",token); i+; return i;/*/* 将word中一行内容以分隔符":"分隔开来,*分开后的内容以健-值对的形式保存在一个CMap对象中*/*/void ExtractString(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap,CMap<CString, LPCTSTR, CString, LPCTSTR> &ItemMap,const CString strs,/*const CString seps=":"*/ const CString seps) CString string(strs); string.TrimLeft(); string.TrimRight(); if (string.IsEmpty() return; int pos=string.Find(seps); if(pos!=-1) CString key=string.Left(pos); CString value=string.Mid(pos+seps.GetLength(); CString strValue; CString strKeysITEM_COUNT="" int length=sizeof(strKeys)/sizeof(strKeys0); /得到CString数组长度 key.TrimLeft(); key.TrimRight(); value.TrimLeft(); value.TrimRight(); /查看指定键的值 strValue=FindValue(stringMap,key); strValue.TrimLeft(); strValue.TrimRight(); /*/ /* 未找到匹配项直接插入*/ /*/ if (strValue.IsEmpty() ItemMap.SetAt(key,value); /*/ /* 否则的话反找键组插入多个记录*/ /*/ else /通过值查找所有的键 FindKeys(stringMap,strKeys,strValue); for (int i=0;i<length;i+) strKeysi.TrimLeft(); strKeysi.TrimRight(); if (!strKeysi.IsEmpty() ItemMap.SetAt(strKeysi,value); else break; /*/* 选择Word文档,选择“导入”按钮时调用 */*/void CNichole7Dlg:OnWord() / TODO: Add your control notification handler code here CString fileName; CString OpenFilter="Word文件(*.doc;*.docx)|*.doc;*.DOC;*.docx;*.DOCX|" CFileDialog FileOpenDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,OpenFilter); if (IDOK=FileOpenDlg.DoModal() fileName=FileOpenDlg.GetPathName(); m_wName.SetWindowText(fileName); /*/* 选择Excel模板文件,选择“选择”按钮时调用 */*/void CNichole7Dlg:OnExcel() / TODO: Add your control notification handler code here CString fileName; CString OpenFilter="Excel文件(*.xls;*.xlsx)|*.xls;*.XLS;*.xlsx;*.XLSX|" CFileDialog FileOpenDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,OpenFilter); if (IDOK=FileOpenDlg.DoModal() fileName=FileOpenDlg.GetPathName(); m_eName.SetWindowText(fileName); /*/* 打开Excel文件 */*/BOOL OpenExcelFile(LPCTSTR xlsFileName,_Application_Excel &_app,LPDISPATCH &lpDispatch,Workbooks &_books,_Workbook &_book,Worksheets &_sheets) COleVariant colOptional(LONG)DISP_E_PARAMNOTFOUND,VT_ERROR); _books.AttachDispatch(_app.GetWorkbooks(); lpDispatch=_books.Open(xlsFileName,colOptional,colOptional,colOptional, colOptional,colOptional,colOptional,colOptional,colOptional,colOptional, colOptional,colOptional,colOptional,colOptional,colOptional); _book.AttachDispatch(lpDispatch); _sheets.AttachDispatch(_book.GetWorksheets(); return true;/*/* 获取当前活动的工作表 */*/BOOL GetCurrentSheet(LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet) lpDispatch=_book.GetActiveSheet(); _sheet.AttachDispatch(lpDispatch); return true;/*/* 获取指定单元格(row,col)的值 */*/CString GetCellValue(LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet,Range_Excel &_range,long row,long col) CString strTemp; if (!GetCurrentSheet(lpDispatch,_book,_sheet) AfxMessageBox("获取当前活动的工作表失败"); exit(1); /得到全部Cells,此时,_range是cells的集合 _range.AttachDispatch(_sheet.GetCells(); _range.AttachDispatch(_range.GetItem(COleVariant(long)row),COleVariant(long)col).pdispVal); COleVariant vResult=_range.GetValue2(); switch(vResult.vt) case VT_BSTR: strTemp=_T(vResult.bstrVal); break; case VT_INT: strTemp.Format("%d",vResult.iVal); break; return strTemp;/*/* 得到写入点位置 */*/int GetInsertPoint(LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet,Range_Excel &_range) CString strTemp; int insertPoint; /循环判断第一列的各行,直到找到不为空的行 for (int i=2; ;i+) strTemp=GetCellValue(lpDispatch,_book,_sheet,_range,i,1); if (strTemp.I