VS2010+MFC解析Excel文件中数据

转自:http://www.vcfans.com/2010/08/vs2010-mfc-excel-file-in-the-data-analysis.html

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

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

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

? View Code CPP
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.将刚才导入的类头文件,加到模块中。

? View Code CPP
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


5. 引入之后如果编译遇到错误,Not enough actual parameters for macro ''DialogBoxW''. 让人头疼!

解决方法是在CRange类中,
1     VARIANT DialogBox()  
2     {  
3           VARIANT result;  
4           InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT,(void*)&result, NULL);  
5           return result;  
6     }  
DialogBox()前面添加下划线变成_DialogBox(),解决了!


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

有图有真像:




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【前言】 工作或学习可能需要实现基于VC读\写Excel文件的功能,本人最近也遇到了该问题。间虽经波折,但是最终还是找到了解决问题的办法。 在此跟大家分享,希望对跟我同样迷茫过的同学们有所帮助。 1、程序功能 1)打开一个excel文件; 2)显示到CListCtrl上; 3)新建一个Excel文件。 以上均在对话框实现。 2、平台 VC++2010 3、实现方法 常用的Excel打开方式有两种 1)通过数据库打开; 2)OLE方式打开。 由于方式1)操作繁琐,经常出现莫名的错误,这里选用方式2). 4、准备步骤 首先新建一个Dialog窗体程序,添加list control和两个按钮 1)将ExcelLib文件夹拷贝到程序目录下; 2)将Export2Excel.h,Export2Excel.cpp两个文件添加到项目; 3)包含头文件,#include "ExcelLib/Export2Excel.h" 通过以上步骤在程序引入了可以读取Excle文件的CExport2Excel类; 5、打开excel文件 通过按钮点击打开 void CExcelTestDlg::OnBnClickedButtonOpenExcel() { //获取文件路径 CFileDialog* lpszOpenFile; CString szGetName; lpszOpenFile = new CFileDialog(TRUE,"","",OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,"Excel File(*.xlsx;*.xls)|*.xls;*.xlsx",NULL); if (lpszOpenFile->DoModal()==IDOK) { szGetName = lpszOpenFile->GetPathName(); SetWindowText(szGetName); delete lpszOpenFile; } else return; //打开文件 //文件包含多个sheet时,默认打开第一个sheet CExport2Excel Excel_example; Excel_example.OpenExcel(szGetName); //获取sheet个数 int iSheetNum = Excel_example.GetSheetsNumber(); //获取已使用表格行列数 int iRows = Excel_example.GetRowCount(); int iCols = Excel_example.GetColCount(); //获取单元格的内容 CString cs_temp = Excel_example.GetText(1,1); //AfxMessageBox(cs_temp); //List control上显示 //获取工作表列名(第一行) CStringArray m_HeadName; m_HeadName.Add(_T("ID")); for (int i=1;iGetItemCount()>0) { m_list.DeleteColumn(0); } //初始化ClistCtrl,加入列名 InitList(m_list,m_HeadName); //填入内容 //第一行是标题,所以从第2行开始 CString num; int pos; for (int row = 2;row<=iRows; row++) { pos = m_list.GetItemCount(); num.Format(_T("%d"),pos +1); m_list.InsertItem(pos,num); for (int colum=1;columDoModal()==IDOK) { szGetName = lpszOpenFile->GetPathName(); SetWindowText(szGetName); delete lpszOpenFile; } else return; //文件全名称 CString csFileName = szGetName; //需要添加的两个sheet的名称 CString csSheetName = "newSheet"; CString csSheetName2 = "newSheet2"; // 新建一个excel文件,自己写入文字 CExport2Excel Excel_example; //新建excel文件 Excel_example.CreateExcel(csFileName); //添加sheet,新加的sheet在前,也就是序号为1 Excel_example.CreateSheet(csSheetName); Excel_example.CreateSheet(csSheetName2); //操作最开始添加的sheet:(newSheet) Excel_example.SetSheet(2); //添加表头 Excel_example.WriteHeader(1,"第一列"); Excel_example.WriteHeader(2,"第二列"); //添加核心数据 Excel_example.WriteData(1,1,"数据1"); Excel_example.WriteData(1,2,"数据2"); //保存文件 Excel_example.Save(); //关闭文件 Excel_example.Close(); } 7、注意事项 1)一般单个Excel文件包含多个sheet,程序默认打开第一个; 2)指定操作sheet,使用Excel_example.SetSheet(2)函数; 3)打开文件时最左侧的sheet序号为1,新建excel时最新添加的sheet序号为1. 【后记】 本程序主要基于网络CSDN---“Excel封装库V2.0”---完成,下载地址是:http://download.csdn.net/detail/yeah2000/3576494,在此表示感谢!同时, 1)在其基础上作了小改动,改正了几个小错误,添加了几个小接口; 2)添加了如何使用的例子,原程序是没有的; 3)详细的注释 发现不足之处,还请大家多多指教!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值