C++使用OLE高速读写EXCEL的源码
http://blog.csdn.net/gyssoft/archive/2007/04/29/1592104.aspx
我根据自己的需要做了整理,干净了一点,而后根据发现的速度问题做了一些优化。
预加载的思路来自这个帖子
http://topic.csdn.net/t/20030626/21/1962211.html
其实思路很简单,不再一个CELL一个CELL的伛数据,而是一次把表格里面所有的数据读取出来处理。
.h文件的源码代码如下:
其中的头文件都是OLE的头文件。如何导出可以参考
http://blog.csdn.net/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,当前处理的文件
- CWorkbook excel_work_book_;
- ///EXCEL的sheets集合
- CWorksheets excel_sheets_;
- ///当前使用sheet
- CWorksheet excel_work_sheet_;
- ///当前的操作区域
- CRange excel_current_range_;
- ///是否已经预加载了某个sheet的数据
- BOOL already_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的String
- CString GetCellString(long iRow, long iColumn);
- ///得到整数
- int GetCellInt(long iRow, long iColumn);
- ///得到double的数据
- double GetCellDouble(long iRow, long iColumn);
- ///取得行的总数
- int GetRowCount();
- ///取得列的总数
- int GetColumnCount();
- ///使用某个shet,shit,shit
- BOOL 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一个int
- void SetCellInt(long irow, long icolumn,int new_int);
- ///写入一个CELL一个string
- void SetCellString(long irow, long icolumn,CString new_string);
- public:
- ///初始化EXCEL OLE
- static BOOL InitExcel();
- ///释放EXCEL的 OLE
- static void ReleaseExcel();
- ///取得列的名称,比如27->AA
- static char *GetColumnName(long iColumn);
- protected:
- //预先加载
- void PreLoadSheet();
- };
CPP文件的与代码如下:
- /******************************************************************************************
- Copyright : 2000-2004, Appache 2.0
- FileName : illusion_excel_file.cpp
- Author : Sail
- Version :
- Date Of Creation : 2009年4月3日
- Description :
- Others :
- Function List :
- 1. ......
- Modification History:
- 1.Date :
- Author :
- Modification :
- 这个类是从网上下载的,我坐享其成,感谢原来的作者,我只试试是稍稍做了一下修正。
- 修正包括一些参数的使用不谨慎,bool 改为BOOL等,对于对象关系,我改了一部分,感觉原来的作者对于OO的思路部分不是很清楚。
- 对于这类东西OLE,我完全不了解,用别人封装的东西感觉还是放心了很多,C++,伟大的C++
- http://blog.csdn.net/gyssoft/archive/2007/04/29/1592104.aspx
- OLE读写EXCEL都比较慢,所以应该尽量减少OLE的次数
- 对于读取,还有解决方法,请试用一下预加载的方式,这个方法一次加载所有的读取数据,如此速度就飞快了。
- 据说写数据是没有什么方法加快的
- http://topic.csdn.net/t/20030626/21/1962211.html
- 增加了一些写入方式的代码,保证可以写入EXCEL数据区,但是对于保存,我发现如果调用CLOSE并且保存的方式,
- 速度非常慢,我不理解为什么。
- 所以我吧EXCEL打开了,让你进行后续管理,
- ******************************************************************************************/
- //-----------------------excelfile.cpp----------------
- #include "StdAfx.h"
- #include "illusion_excel_file.h"
- COleVariant
- covTrue((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_R8
- if(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_R8
- int 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->AA
- char *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);
- }
C++使用OLE高速读写EXCEL的源码的更多相关文章
- VC用OLE方式读写Excel
前几天要做一个项目,需要读取Excel中的数据.从网上查资料发现,主要是有两种方式.一是把Excel表当成数据库使用ODBC读写,这样操作起来就跟操作Access数据库似的.但这种方式效率比较低.另一 ...
- C++读写EXCEL文件OLE,java读写excel文件POI 对比
C++读写EXCEL文件方式比较 有些朋友问代码的问题,将OLE读写的代码分享在这个地方,大家请自己看.http://www.cnblogs.com/destim/p/5476915.html C++ ...
- [IO] C# INI文件读写类与源码下载 (转载)
/// <summary> /// 类说明:INI文件读写类. /// 编 码 人:苏飞 /// 联系方式:361983679 /// 更新网站:[url]http://www.sufei ...
- 使用OLE DB读写Excel
说明: 使用这种技术的好处是无需引用对象,坏处是无法处理类似合并单元格这样的复杂情况 一些更新: 为了使用Office 2010,需要安装Microsoft Access 2010 数据库引擎可再发行 ...
- 使用SpringMvc调用POI jar导出excel的源码
@RequestMapping(value = "/result/export") public String export(ResultIn in,HttpServletRequ ...
- Winfrom 嵌入word、excel实现源码
效果图: winform中嵌入word的方法有多种:调用API,使用webBroser或使用DSOFRAMER控件: API过于繁琐: webbroser读取小文件还行,大文件就太痛苦了: 所以还是选 ...
- Netty源码解析 -- ChannelPipeline机制与读写过程
本文继续阅读Netty源码,解析ChannelPipeline事件传播原理,以及Netty读写过程. 源码分析基于Netty 4.1 ChannelPipeline Netty中的ChannelPip ...
- JVM CPU Profiler技术原理及源码深度解析
研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程序运行行为和性能瓶颈.Profiling技术是一种在应用运行时收集程序相关信息的动态分析手段,常用的JVM Profiler可以从多个方面对程 ...
- Flink sql 之 微批处理与MiniBatchIntervalInferRule (源码分析)
本文源码基于flink1.14 平台用户在使用我们的flinkSql时经常会开启minaBatch来优化状态读写 所以从源码的角度具体解读一下miniBatch的原理 先看一下flinksql是如何触 ...
随机推荐
- [STL源码剖析]RB-tree的插入操作
RB-tree的性质 对于RB-tree,首先做一个了解,先看一张维基百科的RB-tree: 再看RB-tree的性质: 性质1. 节点是红色或黑色. 性质2. 根是黑色,所有叶子都是黑色(叶子节点指 ...
- Linux学习之sed命令详解
概述 sed是stream editor的简称,也就是流编辑器.它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区 ...
- JavaWeb核心编程之(三.4)Servlet Context 配置
ServletContextServlet引擎为每个Web应用程序都创建一个对应的ServletContext对象, ServletContext对象被包含在ServletConfig对象中, 调用S ...
- javascript自定义日期函数
1.格式化日期(YYYY-MM-DD) 代码: var DateFormat = function (date) { if (!(date instanceof Date)) { date = dat ...
- PHP的接口类(interface)和抽象类(abstract)的区别
<?php /** * 接口类:interface * 其实他们的作用很简单,当有很多人一起开发一个项目时,可能都会去调用别人写的一些类, * 那你就会问,我怎么知道他的某个功能的实现方法是怎么 ...
- weather compare
- tr删除替换详解
tr(translate缩写)主要用于删除文件中的控制字符,或进行字符转换. 语法:tr [–c/d/s/t] [SET1] [SET2] #SET1: 字符集1: SET2:字符集2 -c: ...
- 製程能力介紹(SPC introduction) ─ 製程能力的三種表示法
製程能力的三種表示法 Ck: 準度指標 (accuracy) Ck=(M-X)/(T/2) Cp: 精度指標 (precision) Cp=T/(6σp) 規格為單邊時:Cp=(Tu-X)/3 ...
- Wafer管芯数量及成本估算
芯片流片费用一般不按颗数计价,现在流片主要分为全晶圆和MPW两种方式. MPW是现在很流行的一种tapout方法,主要是按晶圆面积来均分价格. 如果是整个wafer的话,成本主要是wafer费 ...
- QSqlDatabase的进一步封装(多线程支持+更加简单的操作)——同时支持MySQL, SQL Server和Sqlite
开发背景: 1.直接用QSqlDatabase我觉得太麻烦了: 2.对于某些数据库,多个线程同时使用一个QSqlDatabase的时候会崩溃: 3.这段时间没什么干货放出来觉得浑身不舒服,就想写一个. ...