轻松解析excel文件 —-利用MFC读取excel文件

轻松解析excel文件 —-利用MFC读取excel文件在项目中需要解析excel文件,尝试了很多办法,最后还是利用MFC自带的解析Excel类。网上的资源很多,前面添加类步骤基本差不多,都能成功,但是在自己写类进行封装的时候,抄袭现象很明显,很多错误还是接着一字不差的发上来。最后找了一个错误不是很多的,自己修改封装,先附上一个demo。(1)在Button控件下添加以下代码用于选取需要读取的文件stringpath; path=CT…

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

在项目中需要解析excel文件,尝试了很多办法,最后还是利用MFC自带的解析Excel类。网上的资源很多,前面添加类步骤基本差不多,都能成功,但是在自己写类进行封装的时候,抄袭现象很明显,很多错误还是接着一字不差的发上来。最后找了一个错误不是很多的,自己修改封装,先附上一个demo。

(1)在Button控件下添加以下代码用于选取需要读取的文件

string path;
	path = CT2A(Infilepath);
	//char* path = const_cast<char*>(line1.c_str()); //sting 转 char*
	Excel excl;
	bool bInit = excl.initExcel();

    //打开excel文件
	if (!excl.open(path.c_str()))
	{
		AfxMessageBox(_T("excel文件打开出错!"));
	}

	CString strSheetName = excl.getSheetName(1);//获取sheet名  
	bool bLoad = excl.loadSheet(strSheetName);//装载sheet  
	int nRow = excl.getRowCount();//获取sheet中行数  
	//int nCol = excl.getColumnCount();//获取sheet中列数  

(2)在需要调用的地方添加以下代码,可以读取任意表格

        string path;
	path = CT2A(Infilepath);
	//char* path = const_cast<char*>(line1.c_str()); //sting 转 char*
	Excel excl;
	bool bInit = excl.initExcel();

       //打开excel文件
	if (!excl.open(path.c_str()))
	{
		AfxMessageBox(_T("excel文件打开出错!"));
	}

	CString strSheetName = excl.getSheetName(1);//获取第一个sheet名  
	bool bLoad = excl.loadSheet(strSheetName);//装载sheet  
	int nRow = excl.getRowCount();//获取sheet中行数  
	int nCol = excl.getColumnCount();//获取sheet中列数  
        CString cell;
	string cells;
	for (int i = 1; i <= nRow; ++i)
	{
            for(int j = 1; j <=  nCol ; ++j){		
		cell = excl.getCellString(i, j);  获取一个单元格数据
	        cells = CT2A(cell);               //将获取的单元格转换为string类型数据
          }
        }

以上代码经过VS实测,保证正确。

 

下面附上详细调用MFC excel类的过程以及封装好的excel类。

1 创建mfc程序(这里以vs2015为例)

轻松解析excel文件 ----利用MFC读取excel文件

 到这里直接点击完成即可。

2 添加读取excel文件用到的类

  2.1 打开类向导(ctrl + alt + x)

    

 

轻松解析excel文件 ----利用MFC读取excel文件

2.2 添加类

轻松解析excel文件 ----利用MFC读取excel文件

 

将_Application、Range、_Workbook、_Worksheet、Workbooks、Worksheets添加到“生成的类”中

 

3 添加完成后,找到所有刚添加的相关头文件,注释/删除第一句话

      #import “D:\\software\\office2010\\Office14\\EXCEL.EXE”no_namespace

 

再次编译还是有错误

 定位错误信息,将DialogBox()改为_DialogBox()

5  特别注意:如果在有stdafx头文件时,一定要在每个头文件之前都加上,不然会报错(这个坑我进去很久才出来)

     到此,MFC里面解析excel就添加成功了。

 

最后添加上封装好excel.h和excel.cpp文件。以下为源码,保证能运行

//excel.h 
#pragma once
#include "CApplication.h"  
#include "CRange.h"  
#include "CWorkbook.h"  
#include "CWorkbooks.h"  
#include "CWorksheet.h"  
#include "CWorksheets.h" 


class Excel
{
private:
	CString openFileName;
	CWorkbook workBook;//当前处理文件  
	CWorkbooks books;//ExcelBook集合,多文件时使用  
	CWorksheet workSheet;//当前使用sheet  
	CWorksheets sheets;//Excel的sheet集合  
	CRange currentRange;//当前操作区域  

	bool isLoad;//是否已经加载了某个sheet数据  

	COleSafeArray safeArray;

protected:
	static CApplication application;//Excel进程实例  

public:
	Excel();
	virtual ~Excel();



	void show(bool bShow);

	//检查一个cell是否为字符串  
	bool isCellString(long iRow, long iColumn);

	//检查一个cell是否为数值  
	bool isCellInt(long iRow, long iColumn);

	//得到一个cell的string  
	CString getCellString(long iRow, long iColumn);

	//得到一个cell的整数  
	int getCellInt(long iRow, long iColumn);

	//得到一个cell的double数据  
	double getCellDouble(long iRow, long iColumn);

	//取得行的总数  
	int getRowCount();

	//取得列的整数  
	int getColumnCount();

	//使用某个shell  
	bool loadSheet(long tableId, bool preLoaded = false);
	bool loadSheet(CString sheet, bool preLoaded = false);


	//通过序号取得某个shell的名称  
	CString getSheetName(long tableID);

	//得到sheel的总数  
	int getSheetCount();

	//打开excel文件  
	bool open(const char* fileName);

	//关闭打开的excel文件  
	void close(bool ifSave = false);

	//另存为一个excel文件  
	void saveAsXLSFile(const CString &xlsFile);

	//取得打开文件的名称  
	CString getOpenFileName();

	//取得打开sheel的名称  
	CString getOpenSheelName();

	//向cell中写入一个int值  
	void setCellInt(long iRow, long iColumn, int newInt);

	//向cell中写入一个字符串  
	void setCellString(long iRow, long iColumn, CString newString);


public:
	//初始化 Excel_OLE  
	static bool initExcel();

	//释放Excel_OLE  
	static void release();

	//取得列的名称  
	static char* getColumnName(long iColumn);

protected:
	void preLoadSheet();
};
//Excel.cpp

#include "stdafx.h"  
#include <tchar.h>  
#include "Excel.h"  


COleVariant
covTrue((short)TRUE),
covFalse((short)FALSE),
covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

CApplication Excel::application;

Excel::Excel() :isLoad(false)
{
}

Excel::~Excel()
{
	//close();  
}
bool Excel::initExcel()
{
	//创建Excel 2000服务器(启动Excel)     
	if (!application.CreateDispatch(_T("Excel.application"), nullptr))
	{
		MessageBox(nullptr, _T("创建Excel服务失败,你可能没有安装EXCEL,请检查!"), _T("错误"), MB_OK);
		return FALSE;
	}

	application.put_DisplayAlerts(FALSE);
	return true;
}


void Excel::release()
{
	application.Quit();
	application.ReleaseDispatch();
	application = nullptr;
}

bool Excel::open(const char*  fileName)
{

	//先关闭文件  
	close();

	//利用模板建立新文档  
	books.AttachDispatch(application.get_Workbooks(), true);


	LPDISPATCH lpDis = nullptr;
	lpDis = books.Add(COleVariant(CString(fileName)));

	if (lpDis)
	{
		workBook.AttachDispatch(lpDis);

		sheets.AttachDispatch(workBook.get_Worksheets());

		openFileName = fileName;
		return true;
	}

	return false;
}

void Excel::close(bool ifSave)
{
	//如果文件已经打开,关闭文件  
	if (!openFileName.IsEmpty())
	{
		//如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待    
		if (ifSave)
		{
			//show(true);  
		}
		else
		{
			workBook.Close(COleVariant(short(FALSE)), COleVariant(openFileName), covOptional);
			books.Close();
		}

		//清空打开文件名称  
		openFileName.Empty();
	}


	sheets.ReleaseDispatch();
	workSheet.ReleaseDispatch();
	currentRange.ReleaseDispatch();
	workBook.ReleaseDispatch();
	books.ReleaseDispatch();
}

void Excel::saveAsXLSFile(const CString &xlsFile)
{
	workBook.SaveAs(COleVariant(xlsFile),
		covOptional,
		covOptional,
		covOptional,
		covOptional,
		covOptional,
		0,
		covOptional,
		covOptional,
		covOptional,
		covOptional,
		covOptional);
	return;
}


int Excel::getSheetCount()
{
	return sheets.get_Count();
}

CString Excel::getSheetName(long tableID)
{
	CWorksheet sheet;
	sheet.AttachDispatch(sheets.get_Item(COleVariant((long)tableID)));
	CString name = sheet.get_Name();
	sheet.ReleaseDispatch();
	return name;
}


void Excel::preLoadSheet()
{
	CRange used_range;

	used_range = workSheet.get_UsedRange();


	VARIANT ret_ary = used_range.get_Value2();
	if (!(ret_ary.vt & VT_ARRAY))
	{
		return;
	}
	//    
	safeArray.Clear();
	safeArray.Attach(ret_ary);
}

//按照名称加载sheet表格,也可提前加载所有表格  
bool Excel::loadSheet(long tableId, bool preLoaded)
{
	LPDISPATCH lpDis = nullptr;
	currentRange.ReleaseDispatch();
	currentRange.ReleaseDispatch();
	lpDis = sheets.get_Item(COleVariant((long)tableId));
	if (lpDis)
	{
		workSheet.AttachDispatch(lpDis, true);
		currentRange.AttachDispatch(workSheet.get_Cells(), true);
	}
	else
	{
		return false;
	}

	isLoad = false;
	//如果进行预先加载    
	if (preLoaded)
	{
		preLoadSheet();
		isLoad = true;
	}

	return true;
}


bool Excel::loadSheet(CString sheet, bool preLoaded)
{
	LPDISPATCH lpDis = nullptr;
	currentRange.ReleaseDispatch();
	currentRange.ReleaseDispatch();

	lpDis = sheets.get_Item(COleVariant(sheet));
	if (lpDis)
	{
		workSheet.AttachDispatch(lpDis, true);
		currentRange.AttachDispatch(workSheet.get_Cells(), true);
	}
	else
	{
		return false;
	}

	isLoad = false;
	//如果进行预先加载    
	if (preLoaded)
	{
		preLoadSheet();
		isLoad = true;
	}

	return true;
}


int Excel::getColumnCount()
{
	CRange range;
	CRange usedRange;

	usedRange.AttachDispatch(workSheet.get_UsedRange(), true);
	range.AttachDispatch(usedRange.get_Columns(), true);
	int count = range.get_Count();

	usedRange.ReleaseDispatch();
	range.ReleaseDispatch();

	return count;
}
int Excel::getRowCount()
{
	CRange range;
	CRange usedRange;

	usedRange.AttachDispatch(workSheet.get_UsedRange(), true);
	range.AttachDispatch(usedRange.get_Rows(), true);

	int count = range.get_Count();

	usedRange.ReleaseDispatch();
	range.ReleaseDispatch();

	return count;
}
bool Excel::isCellString(long iRow, long iColumn)
{
	CRange range;
	range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
	COleVariant vResult = range.get_Value2();
	//VT_BSTR标示字符串    
	if (vResult.vt == VT_BSTR)
	{
		return true;
	}
	return false;
}

bool Excel::isCellInt(long iRow, long iColumn)
{

	CRange range;
	range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
	COleVariant vResult = range.get_Value2();
	//VT_BSTR标示字符串    
	if (vResult.vt == VT_INT || vResult.vt == VT_R8)
	{
		return true;
	}
	return false;
}
CString Excel::getCellString(long iRow, long iColumn)
{
	COleVariant vResult;
	CString str;
	//字符串    
	if (isLoad == false)
	{
		CRange range;
		range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
		vResult = range.get_Value2();
		range.ReleaseDispatch();
	}
	//如果数据依据预先加载了    
	else
	{
		long read_address[2];
		VARIANT val;
		read_address[0] = iRow;
		read_address[1] = iColumn;
		safeArray.GetElement(read_address, &val);
		vResult = val;
	}

	if (vResult.vt == VT_BSTR)
	{
		str = vResult.bstrVal;
	}
	//整数    
	else if (vResult.vt == VT_INT)
	{
		str.Format(_T("%d"), vResult.pintVal);
	}
	//8字节的数字     
	else if (vResult.vt == VT_R8)
	{
		str.Format(_T("%0.0f"), vResult.dblVal);
	}
	//时间格式    
	else if (vResult.vt == VT_DATE)
	{
		SYSTEMTIME st;
		VariantTimeToSystemTime(vResult.date, &st);
		CTime tm(st);
		str = tm.Format(_T("%Y-%m-%d"));

	}
	//单元格空的    
	else if (vResult.vt == VT_EMPTY)
	{
		str = "";
	}

	return str;
}

double Excel::getCellDouble(long iRow, long iColumn)
{
	double rtn_value = 0;
	COleVariant vresult;
	//字符串    
	if (isLoad == false)
	{
		CRange range;
		range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
		vresult = range.get_Value2();
		range.ReleaseDispatch();
	}
	//如果数据依据预先加载了    
	else
	{
		long read_address[2];
		VARIANT val;
		read_address[0] = iRow;
		read_address[1] = iColumn;
		safeArray.GetElement(read_address, &val);
		vresult = val;
	}

	if (vresult.vt == VT_R8)
	{
		rtn_value = vresult.dblVal;
	}

	return rtn_value;
}

int Excel::getCellInt(long iRow, long iColumn)
{
	int num;
	COleVariant vresult;

	if (isLoad == FALSE)
	{
		CRange range;
		range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
		vresult = range.get_Value2();
		range.ReleaseDispatch();
	}
	else
	{
		long read_address[2];
		VARIANT val;
		read_address[0] = iRow;
		read_address[1] = iColumn;
		safeArray.GetElement(read_address, &val);
		vresult = val;
	}
	//    
	num = static_cast<int>(vresult.dblVal);

	return num;
}

void Excel::setCellString(long iRow, long iColumn, CString newString)
{
	COleVariant new_value(newString);
	CRange start_range = workSheet.get_Range(COleVariant(_T("A1")), covOptional);
	CRange write_range = start_range.get_Offset(COleVariant((long)iRow - 1), COleVariant((long)iColumn - 1));
	write_range.put_Value2(new_value);
	start_range.ReleaseDispatch();
	write_range.ReleaseDispatch();
}

void Excel::setCellInt(long iRow, long iColumn, int newInt)
{
	COleVariant new_value((long)newInt);
	CRange start_range = workSheet.get_Range(COleVariant(_T("A1")), covOptional);
	CRange write_range = start_range.get_Offset(COleVariant((long)iRow - 1), COleVariant((long)iColumn - 1));
	write_range.put_Value2(new_value);
	start_range.ReleaseDispatch();
	write_range.ReleaseDispatch();
}


void Excel::show(bool bShow)
{
	application.put_Visible(bShow);
	application.put_UserControl(bShow);
}

CString Excel::getOpenFileName()
{
	return openFileName;
}

CString Excel::getOpenSheelName()
{
	return workSheet.get_Name();
}

char* Excel::getColumnName(long iColumn)
{
	static char column_name[64];
	size_t str_len = 0;

	while (iColumn > 0)
	{
		int num_data = iColumn % 26;
		iColumn /= 26;
		if (num_data == 0)
		{
			num_data = 26;
			iColumn--;
		}
		column_name[str_len] = (char)((num_data - 1) + 'A');
		str_len++;
	}
	column_name[str_len] = '\0';
	//反转    
	_strrev(column_name);

	return column_name;
}

到这儿就能正常解析excel文件

ps:demo里面仅仅展示了excel类的部分功能,按照需要使用…….

 

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

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

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

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

(0)


相关推荐

  • Idea激活码永久有效Idea2020.2.1激活码教程-持续更新,一步到位

    Idea激活码永久有效Idea2020.2.1激活码教程-持续更新,一步到位Idea激活码永久有效2020.2.1激活码教程-Windows版永久激活-持续更新,Idea激活码2020.2.1成功激活

  • xshell 连接虚拟机「建议收藏」

    xshell 连接虚拟机「建议收藏」首先先下载Xshell无论什么版本的Xshell都可以再用Xshell连接虚拟机的时候首先你需要在虚拟机里面查看自己的ip如图所示输入命令ipa 拿到这个ip之后在Xshell里面新建会话 把ip输入进去。然后左边有一个登录验证点击进去验证你在虚拟机上面的登录账号和密码然后连接最后接受验证就可以啦…

  • Instruments10 分析某个类中方法的执行时间

    Instruments10 分析某个类中方法的执行时间

  • mesh和ADhoc区别[通俗易懂]

    mesh和ADhoc区别[通俗易懂]adhoc网络和无线Mesh网络都采用分布式、自组织的思想形成网络,网络每个节点都具备路由功能,随时为其他节点的数据传输提供路由和中继服务。adhoc网络主要侧重应用于移动环境中,确保网络内任意两个节点的可靠通信,网络内数据流可以包括语音、数据和多媒体信息。无线Mesh网络是一种无线宽带接入网络,利用分布式思想构建网络,让用户在任何时间、任何地点都可以对互联网进行高速无线访问,是由ADh…

    2022年10月30日
  • 虚拟现实技术成功应用案例分析_虚拟现实技术的案例

    虚拟现实技术成功应用案例分析_虚拟现实技术的案例心理治疗方面,VR技术以治疗恐怖症、PTSD等闻名于世,近年来不断拓广应用领域。英国伦敦大学学院(UCL)、西班牙巴塞罗那大学和英国德比大学的心理学家和计算机科学家们发表了一项研究,提出一种可以提升自我同情的心理治疗新方法——利用虚拟现实技术。具体的案例被称为“化身实验”,在试验的过程中,被试者会化身为安抚者、被安抚者、第三人视角进行试验,研究结果显示,以从虚拟儿童的角度回溯安抚过程的女性,会…

发表回复

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

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