MFC 与Excel文件的交互操作

    假日快要结束了。带着沉重的心情写下之前关于MFC与Excel文件交互的总结。

因为VS的版本号不同可能在操作上有些差异。所以在此指明下本篇文章的project环境为VS2013,也建议大家用最新的。

    说到程序对于Excel的操作,应该不能算是什么新需求了。方法也有好几种,诸如利用office提供的接口、开源码之类的。本文在查了一些资料之后选择了实现起来较为反便的一种。事实上现的方法基本上全然照抄的这篇文章的,假设看本篇不大明确的能够去看看。

    參考的文章说。“踏破铁鞋无觅处。得来费死了工夫”。然而进过了博主的努力,后人须要做的也就是看一看,抄一抄就完事了。开源的力量伟大至极,本篇将发扬博主的精神。在整理内容的同一时候,写出一个Demoproject提供下载,假设懒得做这些工作的人仅仅须要下载了这个project就能够直接用起来了(亲測能够),project在最后面给出。

   原文地址

    以下開始主要内容

    第一步:创建一个空的MFC对话框project

    第二步:下拉VS菜单条的“项目”项。选择加入类。在弹出对话框中选中“TypeLib中的MFC类”,点击加入。弹出“从类型库加入类向导”对话框。

    

    第三步:弹出的对话框例如以下图,“从下面来源加入类”中有两个选项,假设选择的是“注冊表”,在“可用的类型库”中选择“Microsoft Excel 15.0 Object Library<1.8>”(Office版本号不同可能有些许差异,这个是Office2013)。假设选择的是“文件”,则"位置"选择Office安装路径下的EXCEL.EXE,本人32位Office的默认安装,路径为“C:Program Files (x86)Microsoft OfficeOffice15EXCEL.EXE”。上面两个选项达到的效果是一样的,仅仅是路径不同而已,做完效果例如以下:


    第四步:选中“接口”中的“_Application”,“_WorkSheet”,“_WorkBook”,“WorkSheets”,“WorkBooks”,“Range”这几项。放到右边去,点击完毕。例如以下图:


    第五步:做完第四步后,project中会多出几个导入类的头文件CApplication.h”,“CWorkSheet.h”,“CWorkBook.h”,“CWorkSheets.h”,“CWorkBooks.h”,“CRange.h”。将每个头文件中面的都有的第一句代码“#import "C:\Program Files (x86)\Microsoft Office\Office15\EXCEL.EXE" no_namespace”(路径可能不同)都凝视掉。

例如以下图:


    第六步:既然有头文件,自然就要包括这些头文件啦,在须要调用的文件头写入例如以下代码:

#include "CApplication.h"
#include "CRange.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"
    第七步:这个时候按理说环境已经是搭建好了,可是点击编译还是会报出语法错误,幸好前文提到的博客也给出了解决方法,定位到"CRange,h",将
VARIANT DialogBox()
{
	VARIANT result;
	InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, NULL);
	return result;
}
    中的DialogBox改为_DialogBox,如今编译就没有问题了。接下来调用就能够了,调用代码例如以下:

CApplication app;
CWorkbooks books;
CWorkbook book;
CWorksheets sheets;
CWorksheet sheet;
CRange range;
LPDISPATCH lpDisp;
COleVariant vResult;
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
if (!app.CreateDispatch(L"Excel.Application"))
{
	AfxMessageBox(L"无法启动Excelserver!");
	return;
}
books.AttachDispatch(app.get_Workbooks());
CString path = L"demo.xlsx";//文件路径

TCHAR szPath[MAX_PATH];//获得当前运行路径
GetModuleFileName(NULL, szPath, MAX_PATH);
CString PathName(szPath);
PathName=PathName.Left(PathName.ReverseFind(_T('\')) + 1);

lpDisp = books.Open(PathName+path, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional);

book.AttachDispatch(lpDisp);//得到Workbook  
sheets.AttachDispatch(book.get_Worksheets());//得到Worksheets  

lpDisp = book.get_ActiveSheet();//得到当前活跃sheet,假设有单元格正处于编辑状态中,此操作不能返回。会一直等待  
sheet.AttachDispatch(lpDisp);

//读取第rows行、第cols列单元格的值
/*假设遍历则重复运行这段代码并推断界限*/
int rows = 1, cols = 2;
range.AttachDispatch(sheet.get_Cells());
range.AttachDispatch(range.get_Item(COleVariant((long)rows), COleVariant((long)cols)).pdispVal);
vResult = range.get_Value2();
CString data;
if (vResult.vt == VT_BSTR)//字符串  
{
	data = vResult.bstrVal;
}
else if (vResult.vt == VT_R8)//8字节的数字  
{
	data.Format(L"%.0f", vResult.dblVal);
}
else if(vResult.vt==VT_EMPTY)//单元格空的
{
	data = "";
}
MessageBox(data);
/*假设遍历则重复运行这段代码并推断界限*/

//释放对象    
books.Close();
app.Quit();// 退出  
range.ReleaseDispatch();
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
app.ReleaseDispatch();

    OK,到此便实现了Excel数据的读取,至于创建和写入也几乎相同,以后实用到再加入上来。

    project下载(VS2013)



 

原文地址:https://www.cnblogs.com/wzzkaifa/p/7070414.html