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 Office\Office15\EXCEL.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)