本文源码的应用环境说明:Windows 7,Microsoft Visual Studio 2010,Microsoft Office Excel 2013

最近自己在做一个利用OLE/COM的实现MFC读取word、excel和ppt格式里面的内容,虽然有关这方面的介绍很多,但是感觉比较杂,比较乱,因此将自己整理加修改的结果写出来,希望能够对以后做这方面格式读取的有帮助。

1、安装office软件。

由于利用的是Office的OLE/COM控件来读取,所以Office是要预先装好

2.导入并封装Word、Excel和PPT中的接口

VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,然后再选择要导入的类型库中的接口。在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。

本文所导入的接口对应的类和头文件的说明如下所示:

Word接口 导入类 头文件 _Application CApplication CApplication Documents CDocuments CDocuments _Document CDocument0 CDocument0 Worksheets CRange CRange

Excel接口 导入类 头文件 _Application CApplication0 CApplication0 Workbooks CWorkbooks CWorkbooks _Workbook CWorkbook CWorkbook Worksheets CWorksheets CWorksheets _Worksheet CWorksheet CWorksheet Range CRange0 CRange0 ppt接口 导入类 头文件 _Application CApplication1 CApplication1 Presentations CPresentations CPresentations _Presentation CPresentation CPresentation Slides CSlides CSlides _Slide CSlide CSlide Shapes CShapes CShapes _Shape CShape CShape TextFrame CTextFrame CTextFrame TextRange CTextRange CTextRange

3.导入类型库

对每个导入的word头文件中的#import "E:\\Program Files\\Microsoft Office\\Office15\\MSWORD.OLB" no_namespace、excel头文件中的#import "E:\\Program Files\\Microsoft Office\\Office15\\EXCEL.EXE" no_namespace、ppt中的头文件中的#import "E:\\Program Files\\Microsoft Office\\Office15\\MSPPT.OLB" no_namespace注释掉,目的是防止重复导入,引起编译错误。

对于Excel中的CRange中的DialogBox报错的问题,在前面加下划线即可,即_DialogBox

4.包含对应的头文件,在一个文件中定义变量:

//word CApplication ?wordApp; ? ? ? ?CDocuments ?docs; ? ? ? ?CDocument0 ?doc; ? ? ? ?CRange ?wordRange; ? //excel CApplication0 excelApp; ? ? CWorkbooks books; ? ? CWorkbook book; ? ? CWorksheets sheets; ? ? CWorksheet sheet; ? ? CRange0 excelRange; //ppt CApplication1 ?pptApp;? CPresentations presentations; CPresentation presentation; CSlides ? ? ? ?slides;? CSlide ? ? ? ?slide; CShapes shapes; CShape shape; CTextFrame textFrame; CTextRange textRange; 5.操作步骤

这里以excel为例:

操作Excel的主要步骤如下:

(1)创建一个Excel应用程序。

(2)得到Workbook的容器。

(3)打开一个Workbook或者创建一个Workbook。

(4)得到Workbook中的Worksheet的容器。

(5)打开一个Worksheet或者创建一个WorkSheet。

(6)通过Range对WorkSheet中的单元格进行读写操作。

(7)保存Excel。

(8)释放资源。 这里用一个函数来实现读取excel表:

void ReadExcel(CString filename) { LPDISPATCH lpDisp = NULL; // COleVariant vResult; COleVariant ? ? ? ? covTrue((short)TRUE), ? ? ? ? covFalse((short)FALSE), ? ? ? ? vtMissing((long)DISP_E_PARAMNOTFOUND, VT_ERROR); ? ? ? //打开指定路径文件 CString FileName=filename; if (!excelApp.CreateDispatch(_T("Excel.Application"),NULL)) { AfxMessageBox(_T("Excel failed to start!")); return ; } //设置excel表不可见 excelApp.put_Visible(FALSE); //创建一个文本文件 CFile ? file; www.sxzhongrui.com(_T("tmp.txt"),CFile::modeCreate|CFile::modeWrite); WORD unicode = 0xFEFF; file.Write(&unicode,2); try ? ? { ? ? ? ? //打开一个工作簿 books.AttachDispatch(excelApp.get_Workbooks()); ? ? ? ? lpDisp = www.sxzhongrui.com(FileName,? ? ? ? ? ? ? vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, ? ? ? ? ? ? vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,? ? ? ? ? ? ? vtMissing, vtMissing, vtMissing, vtMissing); ? ? ? ? book.AttachDispatch(lpDisp); //得到Worksheets ? sheets.AttachDispatch(book.get_Worksheets()); //如果有单元格正处于编辑状态中,此操作不能返回,会一直等待 ? lpDisp=book.get_ActiveSheet(); ? sheet.AttachDispatch(lpDisp);? //得到工作簿中的Sheet的容器 // sheets.AttachDispatch(book.get_Sheets()); ? //读取已经使用区域的信息,包括已经使用的行数、列数、起始行、起始列 CRange0 usedRange; usedRange.AttachDispatch(sheet.get_UsedRange()); excelRange.AttachDispatch(usedRange.get_Rows()); long iRowNum=excelRange.get_Count(); ? ? ? ? ? ? ? ? ? //已经使用的行数 ? excelRange.AttachDispatch(usedRange.get_Columns()); long iColNum=excelRange.get_Count(); ? ? ? ? ? ? ? ? ? //已经使用的列数 ?? long iStartRow=usedRange.get_Row(); ? ? ? ? ? ? ? //已使用区域的起始行,从1开始 long iStartCol=usedRange.get_Column(); ? ? ? ? ? ?//已使用区域的起始列,从1开始 // long i,j; for(i=iStartRow;i<=iRowNum;i++) for(j=iStartCol;j<=iColNum;j++) { //读取第一个单元格的值 excelRange.AttachDispatch(sheet.get_Cells());? excelRange.AttachDispatch(excelRange.get_Item(COleVariant((long)i),COleVariant((long)j)).pdispVal ); COleVariant vResult =excelRange.get_Value2(); CString str; if(vResult.vt == VT_BSTR) ? ? ? //字符串 { ?str=vResult.bstrVal; } else if (vResult.vt==VT_R8) ? ? //8字节的数字? { ?str.Format(_T("%f"),vResult.dblVal); } else? str=""; //AfxMessageBox(str); file.Write(str,wcslen(str)*sizeof(wchar_t)); } } ? ? catch(...) ? ? { ? ? ? ?AfxMessageBox(_T("打开文件失败!")); ? ? } //关闭文档 file.Flush(); file.Close(); ? ? /*释放资源*/ ? ? sheet.ReleaseDispatch(); ? ? sheets.ReleaseDispatch(); ? ? book.ReleaseDispatch(); ? ? books.ReleaseDispatch(); ? ? excelApp.Quit(); ? ? excelApp.ReleaseDispatch(); //AfxMessageBox(aRange.get_Text()); }

至于word和ppt,操作过程类似,就这只给出操作代码,对于操作步骤的解释,就不赘述了。

void ReadWord(CString filename) { try{ //打开指定路径文件 CString FileName=filename; if (!wordApp.CreateDispatch(_T("Word.Application"),NULL)) { AfxMessageBox(_T("Word failed to start!")); return ; } wordApp.put_Visible(FALSE); docs = wordApp.get_Documents(); COleVariant vTrue((short)TRUE); ? ? COleVariant vFalse((short)FALSE); COleVariant vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); //COleVariant vFileName(FileName + ".docx"); COleVariant vFileName(FileName); doc = www.sxzhongrui.com(vFileName,vTrue,vTrue,vTrue,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional,vOptional); wordRange = doc.Range(vOptional,vOptional); //创建一个记事本文件 CFile ? file; www.sxzhongrui.com(_T("tmp.txt"),CFile::modeCreate|CFile::modeWrite); WORD unicode = 0xFEFF; file.Write(&unicode,2); //AfxMessageBox(wordRange.get_Text()); //将提取的word内容写入文件 CString str=wordRange.get_Text(); file.Write(str,wcslen(str)*sizeof(wchar_t)); //关闭文档 file.Flush(); file.Close(); ? //释放资源 doc.ReleaseDispatch(); docs.ReleaseDispatch(); wordApp.ReleaseDispatch(); }catch(...) { AfxMessageBox(_T("打开文件失败!")); } }

PPT的操作代码:

void ReadPowerPoint(CString filename) { CString strText; // if (!pptApp.CreateDispatch(_T("Powerpoint.Application"),NULL)) { AfxMessageBox(_T("ppt failed to start!")); return ; } //设置不可见 //pptApp.put_Visible(FALSE); pptApp.put_Visible((long)TRUE); try { //打开文件 presentations = pptApp.get_Presentations(); ? ? ? ? presentation = www.sxzhongrui.com(filename,0,0,1); // 获取幻灯片数目 int i,j; slides=presentation.get_Slides(); // //创建一个文本文件,用来存储提取的结果 CFile ? file; www.sxzhongrui.com(_T("tmp.txt"),CFile::modeCreate|CFile::modeWrite); WORD unicode = 0xFEFF; file.Write(&unicode,2); //提取每一页上的文本 for(i = 1; i <=slides.get_Count(); i++) { slide = slides.Range(COleVariant((long)(i))); shapes=slide.get_Shapes(); for(j = 0; j < shapes.get_Count(); j ++) { shape=shapes.Item(COleVariant((long)(j + 1))); if(shape.get_HasTextFrame()) { textFrame = shape.get_TextFrame(); textRange = textFrame.get_TextRange(); CString txt = textRange.get_Text(); if(txt.GetLength() > 0) { //strText += txt; //写入文本 file.Write(txt,wcslen(txt)*sizeof(wchar_t)); } } } } //关闭文档 file.Flush(); file.Close(); //AfxMessageBox(strText); //释放资源 presentation.Close(); pptApp.Quit(); }catch(...) { AfxMessageBox(_T("ppt文件打开失败!")); } }

至于参考资料,由于离当时查找的时候已经比较久了,所以没能一一列出,抱歉了!

VS2010怎么打开VS2013版本的工程

??? 1.把工程文件夹下的.sln文件用Notepad++(或者记事本)打开,修改如下

? 2.保存后双击该文件,可以打开了,但编译会出现错误:“指定的平台工具集(v120_xp)未安装或无效。请确保选择受支持的 PlatformToolset 值”

这时需要修改该工程的平台工具集,右键点击该工程->属性->配置属性->常规->平台工具集,把v120_xp改成v100,如下图

有时用到VS读写.mat文件,所以结合自己的操作过程,整理出如下的操作步骤

1.首先是环境变量Path的配置 ? 计算机->属性->高级系统设置->高级->环境变量 ? 在Path中已经存在D:\MATLAB_2011a\R2011a\bin\,但是D:\MATLAB_2011a\R2011a\bin\win32下有个重要的libmat.dll。如果不把D:\MATLAB_2011a\R2011a\bin\改为 ? ? ?D:\MATLAB_2011a\R2011a\bin\win32,程序无法运行。 ? 理论上D:\MATLAB_2011a\R2011a\bin\应该会向深一步检索到libmat.dll。坑爹的windows这一步并有去做。这步设置完成后要重启电脑。

2.VS 2010配置

? //新建一个工程,在属性管理器中选择 工程->属性->VC++目录。 ? //设置 ?包含目录为:D:\MATLAB_2011a\extern\include ? //设置 ?库目录为: ?D:\MATLAB_2011a\extern\lib\win32\microsoft

?上面的3条设置并不是必须的,所以用//表示出

1).工程属性->C/C++->常规->附加包含目录 添加:

? ??MATLAB\R2010b\extern\include

? ??MATLAB\R2010b\extern\include\win64

2).链接器->常规->附加库目录 添加:

? ??MATLAB\R2010b\extern\lib\win64\microsoft

? ??MATLAB\R2010b\extern\lib\win32\microsoft

3).链接器->输入->附加依赖库 添加:

? ? ?libmat.lib

? ? ?libmx.lib

? ? ?libmex.lib

? ? ?libeng.lib

由于所安装的matlab为64位,要调用其函数,需要将工程转换为X64

4).(顶菜单)生成->配置管理器->平台:X64

5).链接器->高级->目标计算机:

? ??MachineX64(/MACHINE:X64)

6).计算机环境变量->path 添加:

? ??D:\...\MATLAB\R2010b\extern\lib\win64\microsoft;

? ??D:\...\MATLAB\R2010b\bin\win64;

利用MATLAB提供的有关mat文件的编程接口函数,MATLAB的库函数中包含了mat文件接口函数库,其中有各种对mat文件进行读写的函数,都是以mat开头的函数。

/* 这个文件代码是用VS_2010读写由MATLAB生成的.mat文件: 1.整个代码的实现是参考网上《C++读写.mat文件》的一篇博客 ? 网址为http://www.sxzhongrui.com/left_la/article/details/8206645 2.首先对于VS_2010的整个配置是完全参照博客的内容 ? 配置时同时参考http://www.sxzhongrui.com/content/14/0408/16/15831056_367275320.shtml ? 《使用VS2010调用matlab的mat格式文件》的文章,尤其注意此文章中的红色字体部分。 3.对于原博客内容中的第12行代码“Matrix A(M,N);”编译通不过,对此作了修改, ? 用了Eigen的结构,所以头文件部分也加入了一些 4.因为目前还用不到写.mat文件,所以没调试 */

#include

#include

#if (_MSC_VER >= 1600)

#define __STDC_UTF_16__

#endif

#include

#include

int main()

{

MATFile *pmatFile = NULL;

mxArray *pMxArray = NULL;

// 读取.mat文件(例:mat文件名为"initUrban.mat",其中包含"initA")

double *initA;

pmatFile = matOpen("B.mat","r");

pMxArray = matGetVariable(pmatFile, "b");

initA = (double*) mxGetData(pMxArray);

int M = mxGetM(pMxArray);

int N = mxGetN(pMxArray);

Eigen::MatrixXd A(M,N);

for (int i=0; i

{

for (int j=0; j

A(i,j) = initA[M*j+i];

}

matClose(pmatFile);

mxFree(initA);

std::cout << M<<','<

std::cout << A << std::endl;

/*

// 生成.mat文件

double *outA = new double[M*N];

for (int i=0; i

for (int j=0; j

outA[M*j+i] = A(i,j);

pmatFile = matOpen("A.mat","w");

pMxArray = mxCreateDoubleMatrix(M, N, mxREAL);

mxSetData(pMxArray, outA);

matPutVariable(pmatFile, "A", pMxArray);

matClose(pmatFile);

*/

}