MFC如何操作Word和Excel

应用程序运行界面如图所示:

一、首先在VC6.0中创建MFC应用程序,类型为基本对话框,MFC库选静态的DLL(否则编译之后在其他电脑上无法运行),其他选项默认。然后按Ctrl+W调出MFC类向导,从Word和Exce的安装根目录下导入Word和Excel的库(word:MSWord.olb,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做准备

/*
**1.建立工程文件不要以excel命名,因为添加类的时候会默认生成excel.h和excel.cpp文件
**2.添加excel的类时,要改名,要不然_Application和Range类会重定义(因为word里也会添加进有同样的类)
*/

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static 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 str[LINE_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,str[i],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时,提示“此文件正由另一个应用程序或用户使用” normal.dot
  ** 解决办法是将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);
  }

  //得到第一行的值,保存在strArray[0...j-2]中
  CString strArray[EXCEL_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
    strArray[j-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=strArray[k];
   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);
 str[0].Format("%s",token);
 int i=1;
 while (true)
 {
  token=strtok(NULL,seps);
  if (token==NULL)
   break;
  str[i].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 strKeys[ITEM_COUNT]={""};
  int length=sizeof(strKeys)/sizeof(strKeys[0]); //得到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++)
   {
       strKeys[i].TrimLeft();
       strKeys[i].TrimRight();
       if (!strKeys[i].IsEmpty())
        ItemMap.SetAt(strKeys[i],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.IsEmpty())
   break;
 }
 insertPoint=i;
 return insertPoint;
}
/************************************************************************/
/* 写入Excel */
/************************************************************************/
BOOL WriteExcel(CString strValue,LPDISPATCH &lpDispatch,_Workbook &_book,_Worksheet &_sheet,Range_Excel &_range,long row,long col)
{
 GetCurrentSheet(lpDispatch,_book,_sheet);
 _range.AttachDispatch(_sheet.GetCells());
 _range.SetItem(COleVariant((long)row),COleVariant((long)col),COleVariant(strValue));
 return true;
}
/************************************************************************/
/* 初始化CMap对象保存匹配字符串   */
/************************************************************************/
void InitStringMap(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap)
{
 stringMap.SetAt("出生年月","birthday");
 stringMap.SetAt("年龄","birthday");
 stringMap.SetAt("生日","birthday");
 stringMap.SetAt("出生日期","birthday");

 stringMap.SetAt("教育水平","education");
 stringMap.SetAt("教育程度","education");
 stringMap.SetAt("教育","education");
 stringMap.SetAt("受教育程度","education");

 stringMap.SetAt("英文","english");
 stringMap.SetAt("英语","english");
 stringMap.SetAt("英语水平","english");
 stringMap.SetAt("英文水平","english");

 stringMap.SetAt("当前所在公司","company");
 stringMap.SetAt("当前公司","company");
 stringMap.SetAt("目前公司","company");
 stringMap.SetAt("所在公司","company");
 stringMap.SetAt("公司名称","company");

 stringMap.SetAt("部门","department");
 stringMap.SetAt("公司部门","department");
 stringMap.SetAt("所在部门","department");

 stringMap.SetAt("行业","industry");
 stringMap.SetAt("所在行业","industry");
 
 stringMap.SetAt("意向地区","expect_area");
 stringMap.SetAt("意向地点","expect_area");
 stringMap.SetAt("期望地区","expect_area");
 stringMap.SetAt("期望地点","expect_area");
 
 stringMap.SetAt("职位","job");
 stringMap.SetAt("所任职位","job");
 stringMap.SetAt("现任职位","job");

 stringMap.SetAt("年薪","salary");
 stringMap.SetAt("薪水","salary");
 stringMap.SetAt("薪资","salary");
 stringMap.SetAt("目前薪金","salary");
 stringMap.SetAt("目前薪水","salary");

 stringMap.SetAt("期望薪资","expect_salary");
 stringMap.SetAt("期望薪水","expect_salary");
 stringMap.SetAt("期望年薪","expect_salary");
 stringMap.SetAt("期望月薪","expect_salary");

 stringMap.SetAt("所在地","place");
 stringMap.SetAt("现居地","place");

 stringMap.SetAt("手机号码","telephone");
 stringMap.SetAt("手机","telephone");
 stringMap.SetAt("移动电话","telephone");

 stringMap.SetAt("其他联系方式","contact");
 stringMap.SetAt("电话","contact");
 stringMap.SetAt("QQ","contact");
 stringMap.SetAt("固定电话","contact");
 stringMap.SetAt("MSN","contact");

 stringMap.SetAt("电子邮件","email");
 stringMap.SetAt("电邮","email");
 stringMap.SetAt("邮件","email");

 stringMap.SetAt("婚姻状况","marriage");
 stringMap.SetAt("婚否","marriage");
}
/************************************************************************/
/* 查看指定键的值  */
/************************************************************************/
CString FindValue(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap,CString &key)
{
 CString strValue;
 stringMap.Lookup(key,strValue);
 return strValue;
}
/************************************************************************/
/* 通过值查找所有的键   */
/************************************************************************/
void FindKeys(CMap<CString, LPCTSTR, CString, LPCTSTR> &stringMap,CString *keys,CString &value)
{
 int i=0;
 //遍历整个CMap
 POSITION pos=stringMap.GetStartPosition();
 while (pos)
 {
  CString strKey,strValue;
  stringMap.GetNextAssoc(pos,strKey,strValue);
  if (strValue.Compare(value)==0)
   keys[i++]=strKey;
 }
}
/************************************************************************/
/* 退出Excel程序,该应用程序没有调用该函数  */
/************************************************************************/
BOOL CloseExcel(LPCTSTR xlsFileName,_Application_Excel &_app,Workbooks &_books,_Workbook &_book)
{
 COleVariant colOptional((LONG)DISP_E_PARAMNOTFOUND,VT_ERROR);
 _book.Close(colOptional,COleVariant((char *)xlsFileName),colOptional);
 _books.Close();
 _app.Quit();
 _app.ReleaseDispatch();
 return true;
}
/************************************************************************/
/* 退出  */
/************************************************************************/
void CNichole7Dlg::OnCancel()
{
 // TODO: Add extra cleanup here
 
 CDialog::OnCancel();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值