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

C++读写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的。

[cpp] view plaincopy

  1. #pragma once
  2. //OLE的头文件
  3. #include <CRange.h>
  4. #include <CWorkbook.h>
  5. #include <CWorkbooks.h>
  6. #include <CWorksheet.h>
  7. #include <CWorksheets.h>
  8. #include <CApplication.h>
  9. ///
  10. ///用于OLE的方式的EXCEL读写,
  11. class IllusionExcelFile
  12. {
  13. public:
  14. //构造函数和析构函数
  15. IllusionExcelFile();
  16. virtual ~IllusionExcelFile();
  17. protected:
  18. ///打开的EXCEL文件名称
  19. CString       open_excel_file_;
  20. ///EXCEL BOOK集合,(多个文件时)
  21. CWorkbooks    excel_books_;
  22. ///当前使用的BOOK,当前处理的文件
  23. CWorkbook     excel_work_book_;
  24. ///EXCEL的sheets集合
  25. CWorksheets   excel_sheets_;
  26. ///当前使用sheet
  27. CWorksheet    excel_work_sheet_;
  28. ///当前的操作区域
  29. CRange        excel_current_range_;
  30. ///是否已经预加载了某个sheet的数据
  31. BOOL          already_preload_;
  32. ///Create the SAFEARRAY from the VARIANT ret.
  33. COleSafeArray ole_safe_array_;
  34. protected:
  35. ///EXCEL的进程实例
  36. static CApplication excel_application_;
  37. public:
  38. ///
  39. void ShowInExcel(BOOL bShow);
  40. ///检查一个CELL是否是字符串
  41. BOOL    IsCellString(long iRow, long iColumn);
  42. ///检查一个CELL是否是数值
  43. BOOL    IsCellInt(long iRow, long iColumn);
  44. ///得到一个CELL的String
  45. CString GetCellString(long iRow, long iColumn);
  46. ///得到整数
  47. int     GetCellInt(long iRow, long iColumn);
  48. ///得到double的数据
  49. double  GetCellDouble(long iRow, long iColumn);
  50. ///取得行的总数
  51. int GetRowCount();
  52. ///取得列的总数
  53. int GetColumnCount();
  54. ///使用某个shet,shit,shit
  55. BOOL LoadSheet(long table_index,BOOL pre_load = FALSE);
  56. ///通过名称使用某个sheet,
  57. BOOL LoadSheet(const char* sheet,BOOL pre_load = FALSE);
  58. ///通过序号取得某个Sheet的名称
  59. CString GetSheetName(long table_index);
  60. ///得到Sheet的总数
  61. int GetSheetCount();
  62. ///打开文件
  63. BOOL OpenExcelFile(const char * file_name);
  64. ///关闭打开的Excel 文件,有时候打开EXCEL文件就要
  65. void CloseExcelFile(BOOL if_save = FALSE);
  66. //另存为一个EXCEL文件
  67. void SaveasXSLFile(const CString &xls_file);
  68. ///取得打开文件的名称
  69. CString GetOpenFileName();
  70. ///取得打开sheet的名称
  71. CString GetLoadSheetName();
  72. ///写入一个CELL一个int
  73. void SetCellInt(long irow, long icolumn,int new_int);
  74. ///写入一个CELL一个string
  75. void SetCellString(long irow, long icolumn,CString new_string);
  76. public:
  77. ///初始化EXCEL OLE
  78. static BOOL InitExcel();
  79. ///释放EXCEL的 OLE
  80. static void ReleaseExcel();
  81. ///取得列的名称,比如27->AA
  82. static char *GetColumnName(long iColumn);
  83. protected:
  84. //预先加载
  85. void PreLoadSheet();
  86. };

CPP文件的与代码如下:

[cpp] view plaincopy

  1. /******************************************************************************************
  2. Copyright           : 2000-2004, Appache  2.0
  3. FileName            : illusion_excel_file.cpp
  4. Author              : Sail
  5. Version             :
  6. Date Of Creation    : 2009年4月3日
  7. Description         :
  8. Others              :
  9. Function List       :
  10. 1.  ......
  11. Modification History:
  12. 1.Date  :
  13. Author  :
  14. Modification  :
  15. 这个类是从网上下载的,我坐享其成,感谢原来的作者,我只试试是稍稍做了一下修正。
  16. 修正包括一些参数的使用不谨慎,bool 改为BOOL等,对于对象关系,我改了一部分,感觉原来的作者对于OO的思路部分不是很清楚。
  17. 对于这类东西OLE,我完全不了解,用别人封装的东西感觉还是放心了很多,C++,伟大的C++
  18. http://blog.csdn.net/gyssoft/archive/2007/04/29/1592104.aspx
  19. OLE读写EXCEL都比较慢,所以应该尽量减少OLE的次数
  20. 对于读取,还有解决方法,请试用一下预加载的方式,这个方法一次加载所有的读取数据,如此速度就飞快了。
  21. 据说写数据是没有什么方法加快的
  22. http://topic.csdn.net/t/20030626/21/1962211.html
  23. 增加了一些写入方式的代码,保证可以写入EXCEL数据区,但是对于保存,我发现如果调用CLOSE并且保存的方式,
  24. 速度非常慢,我不理解为什么。
  25. 所以我吧EXCEL打开了,让你进行后续管理,
  26. ******************************************************************************************/
  27. //-----------------------excelfile.cpp----------------
  28. #include "StdAfx.h"
  29. #include "illusion_excel_file.h"
  30. COleVariant
  31. covTrue((short)TRUE),
  32. covFalse((short)FALSE),
  33. covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  34. //
  35. CApplication IllusionExcelFile::excel_application_;
  36. IllusionExcelFile::IllusionExcelFile():
  37. already_preload_(FALSE)
  38. {
  39. }
  40. IllusionExcelFile::~IllusionExcelFile()
  41. {
  42. //
  43. CloseExcelFile();
  44. }
  45. //初始化EXCEL文件,
  46. BOOL IllusionExcelFile::InitExcel()
  47. {
  48. //创建Excel 2000服务器(启动Excel)
  49. if (!excel_application_.CreateDispatch("Excel.Application",NULL))
  50. {
  51. AfxMessageBox("创建Excel服务失败,你可能没有安装EXCEL,请检查!");
  52. return FALSE;
  53. }
  54. excel_application_.put_DisplayAlerts(FALSE);
  55. return TRUE;
  56. }
  57. //
  58. void IllusionExcelFile::ReleaseExcel()
  59. {
  60. excel_application_.Quit();
  61. excel_application_.ReleaseDispatch();
  62. excel_application_=NULL;
  63. }
  64. //打开excel文件
  65. BOOL IllusionExcelFile::OpenExcelFile(const char *file_name)
  66. {
  67. //先关闭
  68. CloseExcelFile();
  69. //利用模板文件建立新文档
  70. excel_books_.AttachDispatch(excel_application_.get_Workbooks(),true);
  71. LPDISPATCH lpDis = NULL;
  72. lpDis = excel_books_.Add(COleVariant(file_name));
  73. if (lpDis)
  74. {
  75. excel_work_book_.AttachDispatch(lpDis);
  76. //得到Worksheets
  77. excel_sheets_.AttachDispatch(excel_work_book_.get_Worksheets(),true);
  78. //记录打开的文件名称
  79. open_excel_file_ = file_name;
  80. return TRUE;
  81. }
  82. return FALSE;
  83. }
  84. //关闭打开的Excel 文件,默认情况不保存文件
  85. void IllusionExcelFile::CloseExcelFile(BOOL if_save)
  86. {
  87. //如果已经打开,关闭文件
  88. if (open_excel_file_.IsEmpty() == FALSE)
  89. {
  90. //如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待
  91. if (if_save)
  92. {
  93. ShowInExcel(TRUE);
  94. }
  95. else
  96. {
  97. //
  98. excel_work_book_.Close(COleVariant(short(FALSE)),COleVariant(open_excel_file_),covOptional);
  99. excel_books_.Close();
  100. }
  101. //打开文件的名称清空
  102. open_excel_file_.Empty();
  103. }
  104. excel_sheets_.ReleaseDispatch();
  105. excel_work_sheet_.ReleaseDispatch();
  106. excel_current_range_.ReleaseDispatch();
  107. excel_work_book_.ReleaseDispatch();
  108. excel_books_.ReleaseDispatch();
  109. }
  110. void IllusionExcelFile::SaveasXSLFile(const CString &xls_file)
  111. {
  112. excel_work_book_.SaveAs(COleVariant(xls_file),
  113. covOptional,
  114. covOptional,
  115. covOptional,
  116. covOptional,
  117. covOptional,
  118. 0,
  119. covOptional,
  120. covOptional,
  121. covOptional,
  122. covOptional,
  123. covOptional);
  124. return;
  125. }
  126. int IllusionExcelFile::GetSheetCount()
  127. {
  128. return excel_sheets_.get_Count();
  129. }
  130. CString IllusionExcelFile::GetSheetName(long table_index)
  131. {
  132. CWorksheet sheet;
  133. sheet.AttachDispatch(excel_sheets_.get_Item(COleVariant((long)table_index)),true);
  134. CString name = sheet.get_Name();
  135. sheet.ReleaseDispatch();
  136. return name;
  137. }
  138. //按照序号加载Sheet表格,可以提前加载所有的表格内部数据
  139. BOOL IllusionExcelFile::LoadSheet(long table_index,BOOL pre_load)
  140. {
  141. LPDISPATCH lpDis = NULL;
  142. excel_current_range_.ReleaseDispatch();
  143. excel_work_sheet_.ReleaseDispatch();
  144. lpDis = excel_sheets_.get_Item(COleVariant((long)table_index));
  145. if (lpDis)
  146. {
  147. excel_work_sheet_.AttachDispatch(lpDis,true);
  148. excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);
  149. }
  150. else
  151. {
  152. return FALSE;
  153. }
  154. already_preload_ = FALSE;
  155. //如果进行预先加载
  156. if (pre_load)
  157. {
  158. PreLoadSheet();
  159. already_preload_ = TRUE;
  160. }
  161. return TRUE;
  162. }
  163. //按照名称加载Sheet表格,可以提前加载所有的表格内部数据
  164. BOOL IllusionExcelFile::LoadSheet(const char* sheet,BOOL pre_load)
  165. {
  166. LPDISPATCH lpDis = NULL;
  167. excel_current_range_.ReleaseDispatch();
  168. excel_work_sheet_.ReleaseDispatch();
  169. lpDis = excel_sheets_.get_Item(COleVariant(sheet));
  170. if (lpDis)
  171. {
  172. excel_work_sheet_.AttachDispatch(lpDis,true);
  173. excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);
  174. }
  175. else
  176. {
  177. return FALSE;
  178. }
  179. //
  180. already_preload_ = FALSE;
  181. //如果进行预先加载
  182. if (pre_load)
  183. {
  184. already_preload_ = TRUE;
  185. PreLoadSheet();
  186. }
  187. return TRUE;
  188. }
  189. //得到列的总数
  190. int IllusionExcelFile::GetColumnCount()
  191. {
  192. CRange range;
  193. CRange usedRange;
  194. usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);
  195. range.AttachDispatch(usedRange.get_Columns(), true);
  196. int count = range.get_Count();
  197. usedRange.ReleaseDispatch();
  198. range.ReleaseDispatch();
  199. return count;
  200. }
  201. //得到行的总数
  202. int IllusionExcelFile::GetRowCount()
  203. {
  204. CRange range;
  205. CRange usedRange;
  206. usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);
  207. range.AttachDispatch(usedRange.get_Rows(), true);
  208. int count = range.get_Count();
  209. usedRange.ReleaseDispatch();
  210. range.ReleaseDispatch();
  211. return count;
  212. }
  213. //检查一个CELL是否是字符串
  214. BOOL IllusionExcelFile::IsCellString(long irow, long icolumn)
  215. {
  216. CRange range;
  217. range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);
  218. COleVariant vResult =range.get_Value2();
  219. //VT_BSTR标示字符串
  220. if(vResult.vt == VT_BSTR)
  221. {
  222. return TRUE;
  223. }
  224. return FALSE;
  225. }
  226. //检查一个CELL是否是数值
  227. BOOL IllusionExcelFile::IsCellInt(long irow, long icolumn)
  228. {
  229. CRange range;
  230. range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);
  231. COleVariant vResult =range.get_Value2();
  232. //好像一般都是VT_R8
  233. if(vResult.vt == VT_INT || vResult.vt == VT_R8)
  234. {
  235. return TRUE;
  236. }
  237. return FALSE;
  238. }
  239. //
  240. CString IllusionExcelFile::GetCellString(long irow, long icolumn)
  241. {
  242. COleVariant vResult ;
  243. CString str;
  244. //字符串
  245. if (already_preload_ == FALSE)
  246. {
  247. CRange range;
  248. range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);
  249. vResult =range.get_Value2();
  250. range.ReleaseDispatch();
  251. }
  252. //如果数据依据预先加载了
  253. else
  254. {
  255. long read_address[2];
  256. VARIANT val;
  257. read_address[0] = irow;
  258. read_address[1] = icolumn;
  259. ole_safe_array_.GetElement(read_address, &val);
  260. vResult = val;
  261. }
  262. if(vResult.vt == VT_BSTR)
  263. {
  264. str=vResult.bstrVal;
  265. }
  266. //整数
  267. else if (vResult.vt==VT_INT)
  268. {
  269. str.Format("%d",vResult.pintVal);
  270. }
  271. //8字节的数字
  272. else if (vResult.vt==VT_R8)
  273. {
  274. str.Format("%0.0f",vResult.dblVal);
  275. }
  276. //时间格式
  277. else if(vResult.vt==VT_DATE)
  278. {
  279. SYSTEMTIME st;
  280. VariantTimeToSystemTime(vResult.date, &st);
  281. CTime tm(st);
  282. str=tm.Format("%Y-%m-%d");
  283. }
  284. //单元格空的
  285. else if(vResult.vt==VT_EMPTY)
  286. {
  287. str="";
  288. }
  289. return str;
  290. }
  291. double IllusionExcelFile::GetCellDouble(long irow, long icolumn)
  292. {
  293. double rtn_value = 0;
  294. COleVariant vresult;
  295. //字符串
  296. if (already_preload_ == FALSE)
  297. {
  298. CRange range;
  299. range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);
  300. vresult =range.get_Value2();
  301. range.ReleaseDispatch();
  302. }
  303. //如果数据依据预先加载了
  304. else
  305. {
  306. long read_address[2];
  307. VARIANT val;
  308. read_address[0] = irow;
  309. read_address[1] = icolumn;
  310. ole_safe_array_.GetElement(read_address, &val);
  311. vresult = val;
  312. }
  313. if (vresult.vt==VT_R8)
  314. {
  315. rtn_value = vresult.dblVal;
  316. }
  317. return rtn_value;
  318. }
  319. //VT_R8
  320. int IllusionExcelFile::GetCellInt(long irow, long icolumn)
  321. {
  322. int num;
  323. COleVariant vresult;
  324. if (already_preload_ == FALSE)
  325. {
  326. CRange range;
  327. range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);
  328. vresult = range.get_Value2();
  329. range.ReleaseDispatch();
  330. }
  331. else
  332. {
  333. long read_address[2];
  334. VARIANT val;
  335. read_address[0] = irow;
  336. read_address[1] = icolumn;
  337. ole_safe_array_.GetElement(read_address, &val);
  338. vresult = val;
  339. }
  340. //
  341. num = static_cast<int>(vresult.dblVal);
  342. return num;
  343. }
  344. void IllusionExcelFile::SetCellString(long irow, long icolumn,CString new_string)
  345. {
  346. COleVariant new_value(new_string);
  347. CRange start_range = excel_work_sheet_.get_Range(COleVariant("A1"),covOptional);
  348. CRange write_range = start_range.get_Offset(COleVariant((long)irow -1),COleVariant((long)icolumn -1) );
  349. write_range.put_Value2(new_value);
  350. start_range.ReleaseDispatch();
  351. write_range.ReleaseDispatch();
  352. }
  353. void IllusionExcelFile::SetCellInt(long irow, long icolumn,int new_int)
  354. {
  355. COleVariant new_value((long)new_int);
  356. CRange start_range = excel_work_sheet_.get_Range(COleVariant("A1"),covOptional);
  357. CRange write_range = start_range.get_Offset(COleVariant((long)irow -1),COleVariant((long)icolumn -1) );
  358. write_range.put_Value2(new_value);
  359. start_range.ReleaseDispatch();
  360. write_range.ReleaseDispatch();
  361. }
  362. //
  363. void IllusionExcelFile::ShowInExcel(BOOL bShow)
  364. {
  365. excel_application_.put_Visible(bShow);
  366. excel_application_.put_UserControl(bShow);
  367. }
  368. //返回打开的EXCEL文件名称
  369. CString IllusionExcelFile::GetOpenFileName()
  370. {
  371. return open_excel_file_;
  372. }
  373. //取得打开sheet的名称
  374. CString IllusionExcelFile::GetLoadSheetName()
  375. {
  376. return excel_work_sheet_.get_Name();
  377. }
  378. //取得列的名称,比如27->AA
  379. char *IllusionExcelFile::GetColumnName(long icolumn)
  380. {
  381. static char column_name[64];
  382. size_t str_len = 0;
  383. while(icolumn > 0)
  384. {
  385. int num_data = icolumn % 26;
  386. icolumn /= 26;
  387. if (num_data == 0)
  388. {
  389. num_data = 26;
  390. icolumn--;
  391. }
  392. column_name[str_len] = (char)((num_data-1) + ‘A‘ );
  393. str_len ++;
  394. }
  395. column_name[str_len] = ‘\0‘;
  396. //反转
  397. _strrev(column_name);
  398. return column_name;
  399. }
  400. //预先加载
  401. void IllusionExcelFile::PreLoadSheet()
  402. {
  403. CRange used_range;
  404. used_range = excel_work_sheet_.get_UsedRange();
  405. VARIANT ret_ary = used_range.get_Value2();
  406. if (!(ret_ary.vt & VT_ARRAY))
  407. {
  408. return;
  409. }
  410. //
  411. ole_safe_array_.Clear();
  412. ole_safe_array_.Attach(ret_ary);
  413. }
时间: 2024-12-11 05:23:53

C++使用OLE高速读写EXCEL的源码的相关文章

C#读写游戏内存源码

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; namespace 内存读写实例 { public class 原创外挂类 { #region Api引用 //打开进程,返回进程句柄 [DllImportAttribute("kernel32.dl

使用SpringMvc调用POI jar导出excel的源码

@RequestMapping(value = "/result/export") public String export(ResultIn in,HttpServletRequest request, HttpServletResponse response) throws Exception { ResultXls xls=resultService.getResultXls(in); HSSFWorkbook wb = resultService.toExcel(xls); r

读写图片文件源码

package com.cqhope.read; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; /** * 操作图片文件类. * @author yanghaita

JVM CPU Profiler技术原理及源码深度解析

研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程序运行行为和性能瓶颈.Profiling技术是一种在应用运行时收集程序相关信息的动态分析手段,常用的JVM Profiler可以从多个方面对程序进行动态分析,如CPU.Memory.Thread.Classes.GC等,其中CPU Profiling的应用最为广泛.CPU Profiling经常被用于分析代码的执行热点,如“哪个方法占用CPU的执行时间最长”.“每个方法占用CPU的比例是多少”等等,通过CPU Profiling得到上述相

MFC vs2012 Office2013 读写excel文件

近期在忙一个小项目(和同学一起搞的),在这里客户要求不但读写txt,而且可以读写excel文件,这里本以为很简单,结果...废话少说,过程如下: 笔者环境:win7 64+VS2012+Office2013+MFC. 说明:读写excel文件,通常包括1.ODBC数据库实现;2.通过解析Excel表格文件;3.通过OLE/COM的几种实现方法.本文主要研究通过OLE/COM实现对Excel表格的操作. 步骤: 1.新建MFC对话框.注意勾选自动化,否则后面加入不了需要的库,导致启动服务失败等错误

集算器读写EXCEL文件的代码示例

集算器可以方便地读写Excel文件,下面用一个例子进行说明:     描述:从data.xlsx读取订单数据和销售员列表,根据这两个sheet计算各部门的销售额,计算结果写入result.xlsx.     源Excel文件:data.xlsx有两个sheet,其中订单数据如下: 销售员列表如下:     集算器代码: A1-A2:从excel文件data.xlsx分别读取第1和第2个sheet,以序表的形式存储在A1.A2格,即订单数据和销售员列表. A3-A4:先将订单数据和销售员列表按照员

c#使用NPOI进行Excel导入导出,附源码,vs2010

目录 1. 介绍:描述第三方类库NPOI以及Excel结构 2. Excel导入:介绍C#如何调用NPOI进行Excel导入,包含:流程图.NOPI以及C#代码 3. Excel导出:介绍C#如何调用NPOI进行Excel导出,包含:流程图.NOPI以.C#代码以及代码分析 4. 源码下载:展示运行图及源码下载 1. 介绍 1.1 第三方类库:NPOI 说明:NPOI是POI项目的.NET 版本,可用于Excel.Word的读写操作. 优点:不用装Office环境. 下载地址:http://np

VB读写Excel

近期用excel和VB比較多,就简单的学习了一下VB中对Excel的处理.今天就介绍一些吧. 在VB中要想调用Excel,须要打开VB编程环境“project”菜单中的“引用”项目,并选取项目中的“Microsoft Excel 11.0 object library”项.因为你的Excel版本号不同,所以这个选项的版本号号也是不同的. 由于EXCEL是以层次结构组织对象的,其对象模型中含有很多不同的对象元素. 第一层:Application对象,即Excel本身: 第二层:workbooks对

mysql-proxy源码安装及配置mysql读写分离

安装Mysql-proxy关联系统包 libevent libevent-devel glib2 glib2-devel lua 5.1.x lua-devel-5.1.x pkg-config mysql-devel openssl openssl-devel gcc* 2安装MySQL-proxy 0.8.5 下载源码包并解压 在源码包路径下安装 ./configure –prefix=/u01/mysql-proxy make make install 3.配置mysql-proxy.cn