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

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的。

  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文件的与代码如下:

  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. }

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

  1. VC用OLE方式读写Excel

    前几天要做一个项目,需要读取Excel中的数据.从网上查资料发现,主要是有两种方式.一是把Excel表当成数据库使用ODBC读写,这样操作起来就跟操作Access数据库似的.但这种方式效率比较低.另一 ...

  2. C++读写EXCEL文件OLE,java读写excel文件POI 对比

    C++读写EXCEL文件方式比较 有些朋友问代码的问题,将OLE读写的代码分享在这个地方,大家请自己看.http://www.cnblogs.com/destim/p/5476915.html C++ ...

  3. [IO] C# INI文件读写类与源码下载 (转载)

    /// <summary> /// 类说明:INI文件读写类. /// 编 码 人:苏飞 /// 联系方式:361983679 /// 更新网站:[url]http://www.sufei ...

  4. 使用OLE DB读写Excel

    说明: 使用这种技术的好处是无需引用对象,坏处是无法处理类似合并单元格这样的复杂情况 一些更新: 为了使用Office 2010,需要安装Microsoft Access 2010 数据库引擎可再发行 ...

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

    @RequestMapping(value = "/result/export") public String export(ResultIn in,HttpServletRequ ...

  6. Winfrom 嵌入word、excel实现源码

    效果图: winform中嵌入word的方法有多种:调用API,使用webBroser或使用DSOFRAMER控件: API过于繁琐: webbroser读取小文件还行,大文件就太痛苦了: 所以还是选 ...

  7. Netty源码解析 -- ChannelPipeline机制与读写过程

    本文继续阅读Netty源码,解析ChannelPipeline事件传播原理,以及Netty读写过程. 源码分析基于Netty 4.1 ChannelPipeline Netty中的ChannelPip ...

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

    研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程序运行行为和性能瓶颈.Profiling技术是一种在应用运行时收集程序相关信息的动态分析手段,常用的JVM Profiler可以从多个方面对程 ...

  9. Flink sql 之 微批处理与MiniBatchIntervalInferRule (源码分析)

    本文源码基于flink1.14 平台用户在使用我们的flinkSql时经常会开启minaBatch来优化状态读写 所以从源码的角度具体解读一下miniBatch的原理 先看一下flinksql是如何触 ...

随机推荐

  1. [STL源码剖析]RB-tree的插入操作

    RB-tree的性质 对于RB-tree,首先做一个了解,先看一张维基百科的RB-tree: 再看RB-tree的性质: 性质1. 节点是红色或黑色. 性质2. 根是黑色,所有叶子都是黑色(叶子节点指 ...

  2. Linux学习之sed命令详解

    概述 sed是stream editor的简称,也就是流编辑器.它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区 ...

  3. JavaWeb核心编程之(三.4)Servlet Context 配置

    ServletContextServlet引擎为每个Web应用程序都创建一个对应的ServletContext对象, ServletContext对象被包含在ServletConfig对象中, 调用S ...

  4. javascript自定义日期函数

    1.格式化日期(YYYY-MM-DD) 代码: var DateFormat = function (date) { if (!(date instanceof Date)) { date = dat ...

  5. PHP的接口类(interface)和抽象类(abstract)的区别

    <?php /** * 接口类:interface * 其实他们的作用很简单,当有很多人一起开发一个项目时,可能都会去调用别人写的一些类, * 那你就会问,我怎么知道他的某个功能的实现方法是怎么 ...

  6. weather compare

  7. tr删除替换详解

    tr(translate缩写)主要用于删除文件中的控制字符,或进行字符转换. 语法:tr  [–c/d/s/t] [SET1] [SET2]    #SET1: 字符集1: SET2:字符集2 -c: ...

  8. 製程能力介紹(SPC introduction) ─ 製程能力的三種表示法

    製程能力的三種表示法 Ck: 準度指標 (accuracy)   Ck=(M-X)/(T/2) Cp: 精度指標 (precision)   Cp=T/(6σp) 規格為單邊時:Cp=(Tu-X)/3 ...

  9. Wafer管芯数量及成本估算

    芯片流片费用一般不按颗数计价,现在流片主要分为全晶圆和MPW两种方式.   MPW是现在很流行的一种tapout方法,主要是按晶圆面积来均分价格.   如果是整个wafer的话,成本主要是wafer费 ...

  10. QSqlDatabase的进一步封装(多线程支持+更加简单的操作)——同时支持MySQL, SQL Server和Sqlite

    开发背景: 1.直接用QSqlDatabase我觉得太麻烦了: 2.对于某些数据库,多个线程同时使用一个QSqlDatabase的时候会崩溃: 3.这段时间没什么干货放出来觉得浑身不舒服,就想写一个. ...