应用程序运行界面如图所示:
一、首先在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();
}