VS2010 MFC读取Excel文件中数据

VS2010 MFC读取Excel文件中数据前段时间写个工具需要从Excel文件中读取数据,Excel表格数据列数为确定值,行数不确定,从网上搜了些方法尝试,最终达到目的,总结如下:

大家好,又见面了,我是你们的朋友全栈君。

前段时间写个工具需要从Excel文件中读取数据,Excel表格数据列数为确定值,行数不确定,从网上搜了些方法尝试,最终达到目的,总结如下:

1. 新建一个基于对话框的MFC应用程序

2. 添加Excel相关类

打开类向导,添加类下拉框选择类型库中的MFC类,来源选择注册表(不容易出错),可用的类型库选择”Microsoft Excel …”(根据Excel的版本有所不同);接口选择:_Application,_WorkSheet,_WorkBook,Range,WorkSheets,WorkBooks;添加6个必要的类CApplication,CWorkbook,CWorksheet,CRange,CWorkbooks,CWorksheets

VS2010 MFC读取Excel文件中数据

3. 添加完成后,找到相关头文件,注释或删除:

//#import "D:\\Program Files (x86)\\Microsoft Office\\Office14\\EXCEL.EXE" no_namespace

在stdafx.h中添加:

#include "CApplication.h"
#include "CRange.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"

4. 编译出现错误:

1>e:\vs2010_project\demo\mfcexcel\crange.h(335): warning C4003: “DialogBoxW”宏的实参不足
1>e:\vs2010_project\demo\mfcexcel\crange.h(335): error C2059: 语法错误:“,”

解决方法:定位错误信息,在CRange类中将DialogBox()改为_DialogBox()

	VARIANT _DialogBox()
	{
		VARIANT result;
		InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, NULL);
		return result;
	}

5. 获取Excel文件路径全名(包括文件名)

添加一个打开文件按钮和显示路径的编辑框,按钮单击消息处理函数:

void COfflineDlg::OnBnClickedButtonOpenfile()
{
	// TODO: 在此添加控件通知处理程序代码
	CFileDialog file(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,  
		_T("EXCEL文件(*.xls;*.xlsx)|*.xls;*.xlsx||"),AfxGetMainWnd());  
	if(file.DoModal()==IDOK)  
	{  
		strPath=file.GetPathName();  
		GetDlgItem(IDC_EDIT_FilePath)->SetWindowText(strPath);
	}  
}

strPath为CString类型的对话框成员变量,用于存储路径

6. 读取Excel中数据

添加一个读取数据按钮,按钮单击消息处理函数:

void COfflineDlg::OnBnClickedButtonReaddata()
{
	// TODO: 在此添加控件通知处理程序代码
	if("" == strPath)
	{
		theApp.ShowInfo(_T("请先选择文件"));
		return;
	}

	GetDlgItem(IDC_BUTTON_ReadData)->EnableWindow(FALSE);
	theApp.ShowInfo(_T("读取数据..."));

	CApplication app;	//Excel程序
	CWorkbooks books;	//工作簿集合
	CWorkbook book;		//工作簿
	CWorksheets sheets;	//工作表集合 
	CWorksheet sheet;	//工作表
	CRange range;		//使用区域

	COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);  
	if (!app.CreateDispatch(_T("Excel.Application")))  
	{  
		MessageBox(_T("Error!Creat Excel Application Server Fail!"));  
		exit(1);  
	}  

	books.AttachDispatch(app.get_Workbooks(),true); 
	book.AttachDispatch(books.Add(_variant_t(strPath)));//获取选择的Excel文件
	sheets.AttachDispatch(book.get_Worksheets(),true);//获取文件中的所有sheet
	sheet.AttachDispatch(sheets.get_Item(_variant_t("sheet1")),true);//获取sheet1区域

	vstrCycleSets.clear();
	vstrCmdSeque.clear();
	vstrSendData.clear();
	vstrExpectData.clear();
	vstrTimeout.clear();
	vstrCheck.clear();
	vstrCycleCnt.clear();

	CString str;
	bool bExit = false;
	for(int irow=2;!bExit;irow++)
	{
		for(int icolumn=1;icolumn<8;icolumn++)
		{
			range.AttachDispatch(sheet.get_Cells(),true);//获取sheet1所有的单元格,重置当前区域为A1
			range.AttachDispatch(range.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal);//获取单元格
			switch(icolumn)
			{
			case 1: str = range.get_Value2(); 
					if(str.IsEmpty())
					{
						bExit = true; 
						break;
					}
					vstrCycleSets.push_back(str); 
					break;
			case 2: str = range.get_Value2();
					vstrCmdSeque.push_back(str);
					break;
			case 3: str = range.get_Value2();
					str.Replace(" ", "");
					vstrSendData.push_back(str);
					break;
			case 4: str = range.get_Value2();
					str.Replace(" ", "");
					vstrExpectData.push_back(str);
					break;
			case 5: str = range.get_Value2();
					vstrTimeout.push_back(str);
					break;
			case 6: str = range.get_Value2();
					vstrCheck.push_back(str);
					break;
			case 7: str = range.get_Value2();
					vstrCycleCnt.push_back(str);
					break;
			default: ;
			}
			if(bExit)
			{
				break;
			}
		}
	}

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

	if(!vstrCycleSets.empty())
	{
		theApp.ShowInfo(_T("读取数据成功"));
	}
	else
	{
		theApp.ShowInfo(_T("读取数据失败"));
	}

	GetDlgItem(IDC_BUTTON_ReadData)->EnableWindow(TRUE);
}

我读取的Excel表格数据列数固定为7,数据不确定所以行数不确定,第一行为表头,所以从第二行A2单元格开始读,通过Ai是否为空来判断数据是否读完。采用容器来保存数据对象比较方便,容器定义为对话框成员变量:

	//存储Excel读取的数据
	vector<CString> vstrCycleSets;
	vector<CString> vstrCmdSeque;
	vector<CString> vstrSendData;
	vector<CString> vstrExpectData;
	vector<CString> vstrTimeout;
	vector<CString> vstrCheck;
	vector<CString> vstrCycleCnt;

至此,就完成了从Excel中读取数据。

我们都是站在巨人的肩膀上,参考资料:

http://blog.csdn.net/u013507368/article/details/42143913

http://blog.csdn.net/jason___bourne/article/details/39643419

http://blog.csdn.net/fkzh2651/article/details/12185611

http://blog.csdn.net/tc297520702/article/details/20745457

http://blog.csdn.net/wangzhiyang925/article/details/37572695

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150086.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 关于cBridge2.0,你不能错过的关键信息(三)!

    关于cBridge2.0,你不能错过的关键信息(三)!上篇ELI5短文中我们讨论了cBridge2.0如何解决「自管」流动性模型中与状态守卫者网络(SGN)的协调问题。今天我们来继续讨论自管模型的最后一个话题:cBridge2.0的设计如何利用SGN为非托管桥接系统中的「作恶问题」提供有史以来第一个解决方案。那么什么是「作恶」呢?首先我们要知道,在cBridge2.0自管桥接模型中,对于桥接节点和用户来说,跨链交易的发生总是需要两个步骤,其顺序如下: 用户的第1步:向源链上的桥接节点进行「时间锁定」的转账,发起转账的用户…

  • centos下修改mysql默认端口_centos7修改mysql默认端口「建议收藏」

    centos下修改mysql默认端口_centos7修改mysql默认端口「建议收藏」项目运行时,一般mysql的默认端口是3306。如何修改呢?现在我将带领大家一起做实验。修改mysql的默认端口一般有三个步骤:1、编辑mysql的配置文件/etc/my.cnf修改你的端口号比如将3306修改成33232、防火墙开放3323端口3、修改项目配置文件中的配置项hostport首先是编辑配置文件,将[mysqld]下面的port=3306改成port=3323v…

    2022年10月30日
  • Windows Mobile 6.1 on T-Mobile MDA Pro 1970

    Windows Mobile 6.1 on T-Mobile MDA Pro 1970

  • MySQL基础知识:存储过程 – Stored Procedure

    MySQL基础知识:存储过程 – Stored ProcedureMySQL存储过程(StoredProcedure)主要的知识点:分隔符(delimiter)变量(variable)参数(parameters)分隔符(DELIMITER)MySQL通过

  • 傅里叶变换公式整理

    傅里叶变换公式整理1、一维傅里叶变换1.1一维连续傅里叶变换正变换:F(ω)=∫−∞∞f(t)⋅e−iωtdtF(\omega)=\int_{-\infty}^{\infty}f(t)\cdote^{-i\omegat}dtF(ω)=∫−∞∞​f(t)⋅e−iωtdt逆变换:f(t)=∫−∞∞F(ω)⋅eiωtdωf(t)=\int_{-\infty}^{\infty}F(\o…

  • Android Layout 之 RelativeLayout RelativeLayout.LayoutParams

    Android Layout 之 RelativeLayout RelativeLayout.LayoutParamsAndroidLayout之RelativeLayout使用AbsoluteLayout可以直接指定其子View的绝对位置,这种布局方式虽然简单,但是不够灵活。比如在一个程序中,按钮2位于按钮1的下方且和按钮1左对齐,我们可以使用指定两个按钮的绝对位置的方式布局,但是当布局完成后,由于某些原因,这两个按钮需要相左平移一些距离以便在父View右边留出一些空白区域…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号