失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > C++使用OLE高速读写EXCEL的源码

C++使用OLE高速读写EXCEL的源码

时间:2019-11-17 10:14:07

相关推荐

C++使用OLE高速读写EXCEL的源码

写了不少blog,也码了一点点文字,不知道为啥,被大家看的比较多几篇文章却总有那篇《C++读写EXCEL文件方式比较》。

小小伤心一下,我blog里面写的很认真的文字还有几篇,这篇大概是最随意的文章。个人估计这是SEO的作用导致的。

另外,由于文中提到了可以加快OLE读取的EXCEL的速度,总有一些哥们找我要代码。

好吧,好吧,把代码放出来,因为我原来也是找人家的代码逐步改的。来而不往非礼也。

我的代码参考的地方是这儿,再次感谢原作者

/gyssoft/archive//04/29/1592104.aspx

我根据自己的需要做了整理,干净了一点,而后根据发现的速度问题做了一些优化。

预加载的思路来自这个帖子

/t/0626/21/1962211.html

其实思路很简单,不再一个CELL一个CELL的伛数据,而是一次把表格里面所有的数据读取出来处理。

.h文件的源码代码如下:

其中的头文件都是OLE的头文件。如何导出可以参考

/wyz365889/article/details/7599924

我自己这儿一直保存了一套别人生成的这几个文件,也可以用。大家可以找找有没有下载的,不过我不太确认跨版本是否可行。

还有既然是OLE,你一定要安装EXCEL的。

#pragma once//OLE的头文件#include <CRange.h>#include <CWorkbook.h>#include <CWorkbooks.h>#include <CWorksheet.h>#include <CWorksheets.h>#include <CApplication.h>//////用于OLE的方式的EXCEL读写,class IllusionExcelFile{public://构造函数和析构函数IllusionExcelFile();virtual ~IllusionExcelFile();protected:///打开的EXCEL文件名称CString open_excel_file_;///EXCEL BOOK集合,(多个文件时)CWorkbooks excel_books_; ///当前使用的BOOK,当前处理的文件CWorkbookexcel_work_book_; ///EXCEL的sheets集合CWorksheets excel_sheets_; ///当前使用sheetCWorksheet excel_work_sheet_; ///当前的操作区域CRange excel_current_range_; ///是否已经预加载了某个sheet的数据BOOLalready_preload_;///Create the SAFEARRAY from the VARIANT ret.COleSafeArray ole_safe_array_;protected:///EXCEL的进程实例static CApplication excel_application_;public:///void ShowInExcel(BOOL bShow);///检查一个CELL是否是字符串BOOL IsCellString(long iRow, long iColumn);///检查一个CELL是否是数值BOOL IsCellInt(long iRow, long iColumn);///得到一个CELL的StringCString GetCellString(long iRow, long iColumn);///得到整数intGetCellInt(long iRow, long iColumn);///得到double的数据double GetCellDouble(long iRow, long iColumn);///取得行的总数int GetRowCount();///取得列的总数int GetColumnCount();///使用某个shet,shit,shitBOOL LoadSheet(long table_index,BOOL pre_load = FALSE);///通过名称使用某个sheet,BOOL LoadSheet(const char* sheet,BOOL pre_load = FALSE);///通过序号取得某个Sheet的名称CString GetSheetName(long table_index);///得到Sheet的总数int GetSheetCount();///打开文件BOOL OpenExcelFile(const char * file_name);///关闭打开的Excel 文件,有时候打开EXCEL文件就要void CloseExcelFile(BOOL if_save = FALSE);//另存为一个EXCEL文件void SaveasXSLFile(const CString &xls_file);///取得打开文件的名称CString GetOpenFileName();///取得打开sheet的名称CString GetLoadSheetName();///写入一个CELL一个intvoid SetCellInt(long irow, long icolumn,int new_int);///写入一个CELL一个stringvoid SetCellString(long irow, long icolumn,CString new_string);public:///初始化EXCEL OLEstatic BOOL InitExcel();///释放EXCEL的 OLEstatic void ReleaseExcel();///取得列的名称,比如27->AAstatic char *GetColumnName(long iColumn);protected://预先加载void PreLoadSheet();};

CPP文件的与代码如下:

/******************************************************************************************Copyright : 2000-, Appache 2.0FileName : illusion_excel_file.cppAuthor : SailVersion : Date Of Creation : 4月3日Description : Others : Function List : 1. ......Modification History:1.Date :Author :Modification :这个类是从网上下载的,我坐享其成,感谢原来的作者,我只试试是稍稍做了一下修正。修正包括一些参数的使用不谨慎,bool 改为BOOL等,对于对象关系,我改了一部分,感觉原来的作者对于OO的思路部分不是很清楚。对于这类东西OLE,我完全不了解,用别人封装的东西感觉还是放心了很多,C++,伟大的C++/gyssoft/archive//04/29/1592104.aspxOLE读写EXCEL都比较慢,所以应该尽量减少OLE的次数对于读取,还有解决方法,请试用一下预加载的方式,这个方法一次加载所有的读取数据,如此速度就飞快了。据说写数据是没有什么方法加快的/t/0626/21/1962211.html增加了一些写入方式的代码,保证可以写入EXCEL数据区,但是对于保存,我发现如果调用CLOSE并且保存的方式,速度非常慢,我不理解为什么。所以我吧EXCEL打开了,让你进行后续管理,******************************************************************************************///-----------------------excelfile.cpp----------------#include "StdAfx.h"#include "illusion_excel_file.h"COleVariantcovTrue((short)TRUE),covFalse((short)FALSE),covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); //CApplication IllusionExcelFile::excel_application_;IllusionExcelFile::IllusionExcelFile():already_preload_(FALSE){}IllusionExcelFile::~IllusionExcelFile(){//CloseExcelFile();}//初始化EXCEL文件,BOOL IllusionExcelFile::InitExcel(){//创建Excel 2000服务器(启动Excel) if (!excel_application_.CreateDispatch("Excel.Application",NULL)) { AfxMessageBox("创建Excel服务失败,你可能没有安装EXCEL,请检查!"); return FALSE;}excel_application_.put_DisplayAlerts(FALSE); return TRUE;}//void IllusionExcelFile::ReleaseExcel(){excel_application_.Quit();excel_application_.ReleaseDispatch();excel_application_=NULL;}//打开excel文件BOOL IllusionExcelFile::OpenExcelFile(const char *file_name){//先关闭CloseExcelFile();//利用模板文件建立新文档 excel_books_.AttachDispatch(excel_application_.get_Workbooks(),true); LPDISPATCH lpDis = NULL;lpDis = excel_books_.Add(COleVariant(file_name)); if (lpDis){excel_work_book_.AttachDispatch(lpDis); //得到Worksheets excel_sheets_.AttachDispatch(excel_work_book_.get_Worksheets(),true); //记录打开的文件名称open_excel_file_ = file_name;return TRUE;}return FALSE;}//关闭打开的Excel 文件,默认情况不保存文件void IllusionExcelFile::CloseExcelFile(BOOL if_save){//如果已经打开,关闭文件if (open_excel_file_.IsEmpty() == FALSE){//如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待if (if_save){ShowInExcel(TRUE);}else{//excel_work_book_.Close(COleVariant(short(FALSE)),COleVariant(open_excel_file_),covOptional);excel_books_.Close();}//打开文件的名称清空open_excel_file_.Empty();}excel_sheets_.ReleaseDispatch();excel_work_sheet_.ReleaseDispatch();excel_current_range_.ReleaseDispatch();excel_work_book_.ReleaseDispatch();excel_books_.ReleaseDispatch();}void IllusionExcelFile::SaveasXSLFile(const CString &xls_file){excel_work_book_.SaveAs(COleVariant(xls_file),covOptional,covOptional,covOptional,covOptional,covOptional,0,covOptional,covOptional,covOptional,covOptional,covOptional);return;}int IllusionExcelFile::GetSheetCount(){return excel_sheets_.get_Count();}CString IllusionExcelFile::GetSheetName(long table_index){CWorksheet sheet;sheet.AttachDispatch(excel_sheets_.get_Item(COleVariant((long)table_index)),true);CString name = sheet.get_Name();sheet.ReleaseDispatch();return name;}//按照序号加载Sheet表格,可以提前加载所有的表格内部数据BOOL IllusionExcelFile::LoadSheet(long table_index,BOOL pre_load){LPDISPATCH lpDis = NULL;excel_current_range_.ReleaseDispatch();excel_work_sheet_.ReleaseDispatch();lpDis = excel_sheets_.get_Item(COleVariant((long)table_index));if (lpDis){excel_work_sheet_.AttachDispatch(lpDis,true);excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);}else{return FALSE;}already_preload_ = FALSE;//如果进行预先加载if (pre_load){PreLoadSheet();already_preload_ = TRUE;}return TRUE;}//按照名称加载Sheet表格,可以提前加载所有的表格内部数据BOOL IllusionExcelFile::LoadSheet(const char* sheet,BOOL pre_load){LPDISPATCH lpDis = NULL;excel_current_range_.ReleaseDispatch();excel_work_sheet_.ReleaseDispatch();lpDis = excel_sheets_.get_Item(COleVariant(sheet));if (lpDis){excel_work_sheet_.AttachDispatch(lpDis,true);excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);}else{return FALSE;}//already_preload_ = FALSE;//如果进行预先加载if (pre_load){already_preload_ = TRUE;PreLoadSheet();}return TRUE;}//得到列的总数int IllusionExcelFile::GetColumnCount(){CRange range;CRange usedRange;usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);range.AttachDispatch(usedRange.get_Columns(), true);int count = range.get_Count();usedRange.ReleaseDispatch();range.ReleaseDispatch();return count;}//得到行的总数int IllusionExcelFile::GetRowCount(){CRange range;CRange usedRange;usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);range.AttachDispatch(usedRange.get_Rows(), true);int count = range.get_Count();usedRange.ReleaseDispatch();range.ReleaseDispatch();return count;}//检查一个CELL是否是字符串BOOL IllusionExcelFile::IsCellString(long irow, long icolumn){CRange range;range.AttachDispatch(excel_current_range_.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;}//检查一个CELL是否是数值BOOL IllusionExcelFile::IsCellInt(long irow, long icolumn){CRange range;range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);COleVariant vResult =range.get_Value2();//好像一般都是VT_R8if(vResult.vt == VT_INT || vResult.vt == VT_R8) {return TRUE;}return FALSE;}//CString IllusionExcelFile::GetCellString(long irow, long icolumn){COleVariant vResult ;CString str;//字符串if (already_preload_ == FALSE){CRange range;range.AttachDispatch(excel_current_range_.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;ole_safe_array_.GetElement(read_address, &val);vResult = val;}if(vResult.vt == VT_BSTR){str=vResult.bstrVal;}//整数else if (vResult.vt==VT_INT){str.Format("%d",vResult.pintVal);}//8字节的数字 else if (vResult.vt==VT_R8){str.Format("%0.0f",vResult.dblVal);}//时间格式else if(vResult.vt==VT_DATE) {SYSTEMTIME st;VariantTimeToSystemTime(vResult.date, &st);CTime tm(st); str=tm.Format("%Y-%m-%d");}//单元格空的else if(vResult.vt==VT_EMPTY) {str="";} return str;}double IllusionExcelFile::GetCellDouble(long irow, long icolumn){double rtn_value = 0;COleVariant vresult;//字符串if (already_preload_ == FALSE){CRange range;range.AttachDispatch(excel_current_range_.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;ole_safe_array_.GetElement(read_address, &val);vresult = val;}if (vresult.vt==VT_R8){rtn_value = vresult.dblVal;}return rtn_value;}//VT_R8int IllusionExcelFile::GetCellInt(long irow, long icolumn){int num;COleVariant vresult;if (already_preload_ == FALSE){CRange range;range.AttachDispatch(excel_current_range_.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;ole_safe_array_.GetElement(read_address, &val);vresult = val;}//num = static_cast<int>(vresult.dblVal);return num;}void IllusionExcelFile::SetCellString(long irow, long icolumn,CString new_string){COleVariant new_value(new_string);CRange start_range = excel_work_sheet_.get_Range(COleVariant("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 IllusionExcelFile::SetCellInt(long irow, long icolumn,int new_int){COleVariant new_value((long)new_int);CRange start_range = excel_work_sheet_.get_Range(COleVariant("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 IllusionExcelFile::ShowInExcel(BOOL bShow){excel_application_.put_Visible(bShow);excel_application_.put_UserControl(bShow);}//返回打开的EXCEL文件名称CString IllusionExcelFile::GetOpenFileName(){return open_excel_file_;}//取得打开sheet的名称CString IllusionExcelFile::GetLoadSheetName(){return excel_work_sheet_.get_Name();}//取得列的名称,比如27->AAchar *IllusionExcelFile::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;}//预先加载void IllusionExcelFile::PreLoadSheet(){CRange used_range;used_range = excel_work_sheet_.get_UsedRange();VARIANT ret_ary = used_range.get_Value2();if (!(ret_ary.vt & VT_ARRAY)){return;}//ole_safe_array_.Clear();ole_safe_array_.Attach(ret_ary); }

【本文作者是雁渡寒潭,本着自由的精神,你可以在无盈利的情况完整转载此文档,转载时请附上BLOG链接:/fullsail/ 或者/fullsail,否则每字一元,每图一百不讲价。对Baidu文库。360doc加价一倍】

如果觉得《C++使用OLE高速读写EXCEL的源码》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。