C++ MFC实现list控件对Excel的读取

C++ MFC实现list控件对Excel的读取前面已经讲过了C++MFC程序对Excel文件的写入,链接如下:https://blog.csdn.net/V_Gogol/article/details/81782644后面很长时间没有更新读取数据操作,非常抱歉!看到网上有朋友问了读取的方法,于是就再写一了这一篇关于读取操作的博文。读取和写入大体相似,要引入的头文件和相关配置也是一样的,具体可以先看上面那一篇关于写入的博文,此篇为…

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

前面已经讲过了C++ MFC程序对Excel文件的写入,链接如下:

https://blog.csdn.net/V_Gogol/article/details/81782644

后面很长时间没有更新读取数据操作,非常抱歉!看到网上有朋友问了读取的方法,于是就再写一了这一篇关于读取操作的博文。

读取和写入大体相似,要引入的头文件和相关配置也是一样的,具体可以先看上面那一篇关于写入的博文,此篇为了节省篇幅便于阅读,就只写读取的具体代码和解释。

我将读取和写入操作都封装成了一个专门的类,便于后续的调用:

list控件读取Excel数据

将Excel数据读取到mfc控件中,我写的函数适用于Excel文件列数和list控件列数相同的情况,此处提供源码,读者可根据源码改成更通用的情况。具体代码如下:

//参数为列表控件
void CFileRW::ExcelToList(CListCtrl *datalist)
{
    //文件对话框,打开具体Excel文件
	CFileDialog filedlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		L"excel文件(*.xls)|*.xlsx|ALL Files(*.*)||");         //TRUE为打开,FALS为保存
	if (IDOK != filedlg.DoModal())
	{
		return;
	}
	//获取文件路径
	readxlspath = filedlg.GetPathName();
	if (!PathFileExists(readxlspath))
	{
		AfxMessageBox(readxlspath + "不存在");
		return;
	}
	if (!app.CreateDispatch(L"Excel.Application"))    //创建接口对象
	{
		AfxMessageBox(L"无法启动Excel服务器");
		return;
	}
	COleVariant	covOption((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
	//得到工作簿
	books.AttachDispatch(app.get_Workbooks());
	lpdisp = books.Open(readxlspath, covOption, covOption, covOption, covOption,
		covOption, covOption, covOption, covOption, covOption, covOption,
		covOption, covOption, covOption, covOption);
	//得到Workbook
	book.AttachDispatch(lpdisp);
	//sheets
	sheets.AttachDispatch(book.get_Worksheets());
	得到WorkSheet
	//sheet.AttachDispatch(sheets.get_sheet());
	//得到当前活跃sheet
	//如果有单元格正处于编辑状态,此操作不会返回,会一直等待
	lpdisp = book.get_ActiveSheet();
	sheet.AttachDispatch(lpdisp);
	usedrange.AttachDispatch(sheet.get_UsedRange());
	COleVariant vResult,vResult1;
	//读取已经使用区域的信息,包括已经使用的行数、列数、起始行、起始列
	range.AttachDispatch(sheet.get_UsedRange());
	//取得已经使用的行数
	range.AttachDispatch(range.get_Rows());
	long rownum = range.get_Count();
	//取得已经使用的列数
	range.AttachDispatch(range.get_Columns());
	long colnum = range.get_Count();
	//取得已使用区域的起始行,从1开始
	long startrow = range.get_Row();
	//取得已使用区域的起始列,从1开始
	long startcol = range.get_Column();
	//清空list控件内容
	datalist->DeleteAllItems();
	for (int i = startrow; i <= rownum; i++)
	{
		//先插入行首,即首列元素
		range.AttachDispatch(sheet.get_Cells());
		range.AttachDispatch(range.get_Item(_variant_t((long)i+1),
			_variant_t((long)startcol)).pdispVal);
		vResult = range.get_Value2();
		CString strread, stry0, strm0, strd0;
		SYSTEMTIME st0;
		if (vResult.vt == VT_BSTR)     //若是字符串
		{
			strread = vResult.bstrVal;
		}
		else if (vResult.vt == VT_R8) //8字节的数字
		{
			strread.Format(L"%f", vResult.dblVal);
		}
		else if (vResult.vt == VT_DATE) //时间格式
		{
			VariantTimeToSystemTime(vResult.date, &st0);
			stry0.Format(L"%d", st0.wYear);
			strm0.Format(L"%d", st0.wMonth);
			strd0.Format(L"%d", st0.wDay);
			strread = stry0 + L"-" + strm0 + L"-" + strd0;
		}
		else if (vResult.vt == VT_EMPTY) //单元为空
		{
			strread = L"";
		}
		else if (vResult.vt == VT_I4)
		{
			strread.Format(_T("%ld"), (int)vResult.lVal);
		};
		datalist->InsertItem(i , strread);

      //插入后面元素
		for (int j = startcol+1; j <= colnum; j++)
		{
			//读取单元格的值
			range.AttachDispatch(sheet.get_Cells());
			range.AttachDispatch(range.get_Item(_variant_t((long)i + 1),
				_variant_t((long)j)).pdispVal);
			vResult1 = range.get_Value2();
			CString str, stry, strm, strd;
			SYSTEMTIME st;
			if (vResult1.vt == VT_BSTR)     //若是字符串
			{
				str = vResult1.bstrVal;
			}
			else if (vResult1.vt == VT_R8) //8字节的数字
			{
				str.Format(L"%f", vResult1.dblVal);
			}
			else if (vResult1.vt == VT_DATE) //时间格式
			{
				VariantTimeToSystemTime(vResult1.date, &st);
				stry.Format(L"%d", st.wYear);
				strm.Format(L"%d", st.wMonth);
				strd.Format(L"%d", st.wDay);
				str = stry + L"-" + strm + L"-" + strd;
			}
			else if (vResult1.vt == VT_EMPTY) //单元为空
			{
				str = L"";
			}
			else if (vResult1.vt == VT_I4)
			{
				str.Format(_T("%ld"), (int)vResult1.lVal);
			}
			//datalist->SetItemText(static_cast<int>(i), static_cast<int>(j),str);
			datalist->SetItemText(i-1, j-1, str);
		}
	}
	release();
	AfxMessageBox(L"读取成功");
}

和写入时一样,读取完毕后也需要释放资源,我自己定义了一个资源释放函数release(),具体代码如下:

usedrange.ReleaseDispatch();
	range.ReleaseDispatch();
	sheet.ReleaseDispatch();
	sheets.ReleaseDispatch();
	book.ReleaseDispatch();
	books.ReleaseDispatch();
	app.Quit();
	app.ReleaseDispatch();

至此,mfc读取Excel就已经讲完了,后续会再更新一些简单的Excel样式控制,希望对大家有帮助,谢谢!

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

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

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

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

(0)


相关推荐

  • java string与stringbuffer的区别_string类和stringbuilder类的区别

    java string与stringbuffer的区别_string类和stringbuilder类的区别简单地说,就是一个变量和常量的关系。StringBuffer对象的内容可以修改;而String对象一旦产生后就不可以被修改,重新赋值其实是两个对象。StringBuffer的内部实现方式和String不同,StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuff…

  • jsonfield注解不生效(write javabean error fastjson)

    @jsonfield看源码它可以作用于字段和方法上。引用网上说的,一、作用field@jsonfield作用在field时,其name不仅定义了输入key的名称,同时也定义了输出的名称。但是我在使用中,发现并不如上所说。例如@jsonfield(name=”project_id”)privatelongprojectid发现bean转json的时候并是”project_id”:xxx的形式,…

  • win7系统opc服务器配置,win7 设置opc服务器

    win7系统opc服务器配置,win7 设置opc服务器win7设置opc服务器内容精选换一换创建媒体处理服务配置项。媒体处理服务配置项用于媒体处理服务中获取相关授权。参数和对应说明如表1。MpcConfigmpcConfig=newMpcConfig();mpcConfig.setEndPoint(“endPoint”);//设置转码节点地址mpcConfig.setProjectId(华为云帮助中心,为用户提供产品简介、价格说明、购买…

  • JMH使用指南[通俗易懂]

    JMH使用指南[通俗易懂]关于JMH,可以直接查看官网地址http://openjdk.java.net/projects/code-tools/jmh/本博客内容来自我正在撰写的新书《Java性能优化(暂定名)》,也欢迎购买经典书《SpringBoot2实战权威指南》1.3JMH1.3.1使用JMH通过手工编写一个性能压测程序有较多的问题不同需要性能比较方法放到一个虚拟机里调用,有可能会互相…

  • ARM64架构、国产系统UOS、银河麒麟离线安装jdk1.7、jdk1.8,jdk7、jdk8离线安装(100%成功)

    ARM64架构、国产系统UOS、银河麒麟离线安装jdk1.7、jdk1.8,jdk7、jdk8离线安装(100%成功)Linuxarm64架构下安装jdk1.7、jdk1.8说明:理论上适用于arm64架构的Linux系统,目前在银河麒麟、UOS测试可安装通过1.挂载ISO介质上传Kylin-4.0.2-FT2000Plus.iso到服务器到/opt/目录下,(如果没有该介质,请向笔者索要,网盘下载)创建挂载目录mkdir/mnt/apt挂载isomount/opt/Kylin-4.0.2-FT2000Plus.iso/mnt/apt2.修改本地源先备份本地源cp/et

  • pycharm 激活码 2022_通用破解码「建议收藏」

    pycharm 激活码 2022_通用破解码,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

发表回复

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

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