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样式控制,希望对大家有帮助,谢谢!

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

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

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • oninput事件

    oninput事件js监听input等表单输入框的变化事件oninput,手机页面开发中使用到文本框textarea输入字符监听文本框变化计算还可以输入多少字符,如果使用onkeyup的话是无法监听到输入法输入的文本变化的,复制粘贴也不能监听到,于是就用到了oninput事件来监听文本框value值的改变。由于是手机端页面没有考虑IE这货。js代码如下://计算文本输入统计(function

    2022年6月11日
  • Snort安装_snorer

    Snort安装_snorer1、下载源文件wgethttps://www.snort.org/downloads/snort/daq-2.0.6.tar.gzwgethttps://www.snort.org/downloads/snort/snort-2.9.8.0.tar.gz2、解压安装tarxvfzdaq-2.0.6.tar.gzcddaq-2.0.6./configure;mak

    2022年10月24日
  • goland2021.8激活码(注册激活)[通俗易懂]

    (goland2021.8激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月25日
  • web服务交互中HTTP数据内容GZIP,ZLIB格式压缩与解压缩封装(共享)

    web服务交互中HTTP数据内容GZIP,ZLIB格式压缩与解压缩封装(共享)

    2022年2月1日
  • 网上英语学习资源大整理

    网上英语学习资源大整理 翻译http://www.bilinguist.com/汉英论坛,高手云集[url]http://www.chinatranslate.net/[/url]中国翻译网,号称全国最大的翻译专业网站[url]http://gb.transea.com/[/url]机器即时翻译,适合整体翻译网站及段落,但不够准确。适合一般人[url]http://www.si-chi…

    2022年10月26日
  • linux宝塔卸载,宝塔面板卸载与安装[通俗易懂]

    linux宝塔卸载,宝塔面板卸载与安装[通俗易懂]一键卸载宝塔Linux面板及运行环境命令1-使用xshell链接服务进入服务器命令:wgethttp://download.bt.cn/install/bt-uninstall.sh2-执行脚本命令:shbt-uninstall.sh3-根据提示4-完成更多功能及文档2,安装宝塔面板执行以下代码进行安装宝塔6.9免费版。宝塔6.9版本已经很稳定了,推荐大家直接安装6.9版本(注意:…

    2022年9月6日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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