生活的天平本不平衡,只有通过努力改变其偏向。

VS2010+MFC解析Excel文件中数据

2010-08-26

前两天折腾一个小功能,需求是解析Excel中的数据出来。网上一般使用的方案:
1. ODBC当数据库来操作。
2. 使用第三方的类库
3. 使用COM调用Excel.exe中的接口。

第三方类库我怕MS升级版本后,是否仍然使用是个问号。使用ODBC的方案感觉很怪怪的,但据说不能修改删除什么的,不过我没有试验,还是放弃此种方案。我最终还是使用COM来做的,本来是没什么实现代码,都是COM实现好的,没什么可写的。难点在于VS2010的版本与MSDN上的说法严重不一致,折腾死人。MSDN上说的方案是VC6.0的实现方法。而且加入COM后与VS的SDK库冲突,无法编译。下面说说我的使用方法。

第一步:初化COM接口。在InitInstance中加入如下代码:

1
2
3
4
5
if(!AfxOleInit())
	{
		AfxMessageBox(_T( "Cannot initialize COM dll" ));
		return FALSE;
	}

第二步:向工程添加Excel的C++操作类。具体步骤见下图:
1.Ctrl+Shift+X 打开类向导。

2.添加“类型库中MFC类”。此处操作与VC6.0有很大的不一样,让我找了半天,如下图:

3.添加需要的类文件。如下图:

4.将刚才导入的类头文件,加到模块中。

1
2
3
4
5
6
#include "CApplication.h"
#include "CWorkbooks.h"
#include "CWorksheets.h"
#include "CWorkbook.h"
#include "CWorksheet.h"
#include "CRange.h"

到此好像一切都结束了,下面就是写调用上面载入的代码了。But……,当你编译时。MS将给你如下惊喜:

1>d:\xls\xls\debug\excel.tlh(74974): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(74974): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(74974): warning C4183: “GetMailEnvelope”: 缺少返回类型;假定为返回“int”的成员函数
1>d:\xls\xls\debug\excel.tlh(75683): error C2146: 语法错误: 缺少“;”(在标识符“HTMLProject”的前面)
1>d:\xls\xls\debug\excel.tlh(75683): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75683): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75693): error C2146: 语法错误: 缺少“;”(在标识符“CommandBars”的前面)
1>d:\xls\xls\debug\excel.tlh(75693): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75693): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75737): error C2146: 语法错误: 缺少“;”(在标识符“VBProject”的前面)
1>d:\xls\xls\debug\excel.tlh(75737): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75737): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75739): error C2146: 语法错误: 缺少“;”(在标识符“Permission”的前面)
1>d:\xls\xls\debug\excel.tlh(75739): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75739): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75741): error C2146: 语法错误: 缺少“;”(在标识符“SharedWorkspace”的前面)
1>d:\xls\xls\debug\excel.tlh(75741): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75741): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75743): error C2146: 语法错误: 缺少“;”(在标识符“Sync”的前面)
1>d:\xls\xls\debug\excel.tlh(75743): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75743): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75757): error C2146: 语法错误: 缺少“;”(在标识符“SmartDocument”的前面)
1>d:\xls\xls\debug\excel.tlh(75757): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75757): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int
1>d:\xls\xls\debug\excel.tlh(75759): error C2146: 语法错误: 缺少“;”(在标识符“DocumentLibraryVersions”的前面)
1>d:\xls\xls\debug\excel.tlh(75759): fatal error C1003: 错误计数超过 100;正在停止编译
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

我也不知道为什么造成这种结果,可能是由于这类接口是MS在N年前就弄好,后来VS升级了,相关接口也就年久失修了。造成我们这帮使用老技术的人的尴尬,后来求助于万能的Google大侠,得到如下方案:

将刚才导入的几个头文件中的:

?Download download.txt
1
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace

替换成:

?Download download.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#pragma region Import the type libraries
 
#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" \
	rename("RGB", "MSORGB") \
	rename("DocumentProperties", "MSODocumentProperties")
// [-or-]
//#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
//	rename("RGB", "MSORGB") \
//	rename("DocumentProperties", "MSODocumentProperties")
 
using namespace Office;
 
#import "libid:0002E157-0000-0000-C000-000000000046"
// [-or-]
//#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
 
using namespace VBIDE;
 
#import "libid:00020813-0000-0000-C000-000000000046" \
	rename("DialogBox", "ExcelDialogBox") \
	rename("RGB", "ExcelRGB") \
	rename("CopyFile", "ExcelCopyFile") \
	rename("ReplaceText", "ExcelReplaceText") \
	no_auto_exclude
// [-or-]
//#import "C:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
//	rename("DialogBox", "ExcelDialogBox") \
//	rename("RGB", "ExcelRGB") \
//	rename("CopyFile", "ExcelCopyFile") \
//	rename("ReplaceText", "ExcelReplaceText") \
//	no_auto_exclude
 
#pragma endregion

到此搞定环境问题,下面就根据需求对Excel进行操作吧。

有图有真像:

作者:lonkil | 分类目录:本站原创 | 标签:

19 条评论

  1. flashmouse 说道:

    恩人啊!!!!多谢了!!

  2. Peter 说道:

    DialogBox() 改为 _DialogBox() 就可以编译成功了

  3. billschen 说道:

    warning C4003: “DialogBoxW”宏的实参不足
    我也遇到此类错误,如何处理!
    多谢!

  4. 葡萄糖酸钠 说道:

    第三方的类库我的不可以用,刚才试了下你说的,不错,学习啦!

  5. clwahaha 说道:

    发现生成的CRange.h文件编译通不过啊!
    crange.h(345): warning C4003: “DialogBoxW”宏的实参不足
    crange.h(345): error C2059: 语法错误:“,”
    这是怎么回事啊 我是vs2010 SP1 + vin7 旗舰版

  6. clwahaha 说道:

    亲,爱死你了!找了半天,终于发现了!

  7. 刷机包 说道:

    文章很好,看了半天,终于明白了。

  8. 像前辈学习 说道:

    一个VC工程,刚刚建的一个对话框类后,设置断点,居然不能调试了,
    点击单步运行,VC直接进入了汇编代码区域,不能在设置的部分停留了,在InitInstance()函数内,设置断点有效,不知道程序运行哪里,就进入了汇编代码了,
    请问怎么解决??

  9. 老飞的小窝 说道:

    也学过一段时间vc,不过感觉好难哦,呵呵

  10. lonkil 说道:

    @ cdutboy:

    格式开放了?

    谢谢,分享。

  11. cdutboy 说道:

    之前做过二进制解析word2003来分析其中是否捆绑木马,微软已经开发了office03/07的格式文档,如果要长久的可用,博主不妨一试,效率更高。不过我没分析过07的。

  12. 看过以后我总喜欢留过脚印而已

  13. C瓜哥 说道:

    升级到win7啦?

    我的等级还太低,现在看不懂,55……

  14. Koma 说道:

    白沫 !

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>