博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++使用OLE高速读写EXCEL的源码
阅读量:5892 次
发布时间:2019-06-19

本文共 11710 字,大约阅读时间需要 39 分钟。

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

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

 

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

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

 

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

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

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

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

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

 

CPP文件的与代码如下:

[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.  
  9. Others              :  
  10. Function List       :  
  11.     1.  ...... 
  12.         Modification History: 
  13.     1.Date  : 
  14. Author  : 
  15. Modification  : 
  16.  
  17.     这个类是从网上下载的,我坐享其成,感谢原来的作者,我只试试是稍稍做了一下修正。 
  18.     修正包括一些参数的使用不谨慎,bool 改为BOOL等,对于对象关系,我改了一部分,感觉原来的作者对于OO的思路部分不是很清楚。 
  19.     对于这类东西OLE,我完全不了解,用别人封装的东西感觉还是放心了很多,C++,伟大的C++ 
  20.      http://blog.csdn.net/gyssoft/archive/2007/04/29/1592104.aspx 
  21.  
  22.     OLE读写EXCEL都比较慢,所以应该尽量减少OLE的次数 
  23.     对于读取,还有解决方法,请试用一下预加载的方式,这个方法一次加载所有的读取数据,如此速度就飞快了。 
  24.     据说写数据是没有什么方法加快的 
  25.     http://topic.csdn.net/t/20030626/21/1962211.html 
  26.  
  27.     增加了一些写入方式的代码,保证可以写入EXCEL数据区,但是对于保存,我发现如果调用CLOSE并且保存的方式, 
  28.     速度非常慢,我不理解为什么。 
  29.     所以我吧EXCEL打开了,让你进行后续管理, 
  30.  
  31.  
  32. ******************************************************************************************/  
  33.   
  34.   
  35.   
  36.   
  37. //-----------------------excelfile.cpp----------------  
  38.   
  39. #include "StdAfx.h"  
  40. #include "illusion_excel_file.h"  
  41.   
  42.   
  43.   
  44. COleVariant  
  45. covTrue((short)TRUE),  
  46. covFalse((short)FALSE),  
  47. covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);      
  48.   
  49. //  
  50. CApplication IllusionExcelFile::excel_application_;  
  51.   
  52.   
  53. IllusionExcelFile::IllusionExcelFile():  
  54.     already_preload_(FALSE)  
  55. {  
  56. }  
  57.   
  58. IllusionExcelFile::~IllusionExcelFile()  
  59. {  
  60.     //  
  61.     CloseExcelFile();  
  62. }  
  63.   
  64.   
  65. //初始化EXCEL文件,  
  66. BOOL IllusionExcelFile::InitExcel()  
  67. {  
  68.   
  69.     //创建Excel 2000服务器(启动Excel)   
  70.     if (!excel_application_.CreateDispatch("Excel.Application",NULL))   
  71.     {   
  72.         AfxMessageBox("创建Excel服务失败,你可能没有安装EXCEL,请检查!");   
  73.         return FALSE;  
  74.     }  
  75.   
  76.     excel_application_.put_DisplayAlerts(FALSE);   
  77.     return TRUE;  
  78. }  
  79.   
  80. //  
  81. void IllusionExcelFile::ReleaseExcel()  
  82. {  
  83.     excel_application_.Quit();  
  84.     excel_application_.ReleaseDispatch();  
  85.     excel_application_=NULL;  
  86. }  
  87.   
  88. //打开excel文件  
  89. BOOL IllusionExcelFile::OpenExcelFile(const char *file_name)  
  90. {  
  91.     //先关闭  
  92.     CloseExcelFile();  
  93.       
  94.     //利用模板文件建立新文档   
  95.     excel_books_.AttachDispatch(excel_application_.get_Workbooks(),true);   
  96.   
  97.     LPDISPATCH lpDis = NULL;  
  98.     lpDis = excel_books_.Add(COleVariant(file_name));   
  99.     if (lpDis)  
  100.     {  
  101.         excel_work_book_.AttachDispatch(lpDis);   
  102.         //得到Worksheets   
  103.         excel_sheets_.AttachDispatch(excel_work_book_.get_Worksheets(),true);   
  104.           
  105.         //记录打开的文件名称  
  106.         open_excel_file_ = file_name;  
  107.   
  108.         return TRUE;  
  109.     }  
  110.       
  111.     return FALSE;  
  112. }  
  113.   
  114. //关闭打开的Excel 文件,默认情况不保存文件  
  115. void IllusionExcelFile::CloseExcelFile(BOOL if_save)  
  116. {  
  117.     //如果已经打开,关闭文件  
  118.     if (open_excel_file_.IsEmpty() == FALSE)  
  119.     {  
  120.         //如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待  
  121.         if (if_save)  
  122.         {  
  123.             ShowInExcel(TRUE);  
  124.         }  
  125.         else  
  126.         {  
  127.             //  
  128.             excel_work_book_.Close(COleVariant(short(FALSE)),COleVariant(open_excel_file_),covOptional);  
  129.             excel_books_.Close();  
  130.         }  
  131.   
  132.         //打开文件的名称清空  
  133.         open_excel_file_.Empty();  
  134.     }  
  135.   
  136.       
  137.   
  138.     excel_sheets_.ReleaseDispatch();  
  139.     excel_work_sheet_.ReleaseDispatch();  
  140.     excel_current_range_.ReleaseDispatch();  
  141.     excel_work_book_.ReleaseDispatch();  
  142.     excel_books_.ReleaseDispatch();  
  143. }  
  144.   
  145. void IllusionExcelFile::SaveasXSLFile(const CString &xls_file)  
  146. {  
  147.     excel_work_book_.SaveAs(COleVariant(xls_file),  
  148.         covOptional,  
  149.         covOptional,  
  150.         covOptional,  
  151.         covOptional,  
  152.         covOptional,  
  153.         0,  
  154.         covOptional,  
  155.         covOptional,  
  156.         covOptional,  
  157.         covOptional,  
  158.         covOptional);  
  159.     return;  
  160. }  
  161.   
  162.   
  163. int IllusionExcelFile::GetSheetCount()  
  164. {  
  165.     return excel_sheets_.get_Count();  
  166. }  
  167.   
  168.   
  169. CString IllusionExcelFile::GetSheetName(long table_index)  
  170. {  
  171.     CWorksheet sheet;  
  172.     sheet.AttachDispatch(excel_sheets_.get_Item(COleVariant((long)table_index)),true);  
  173.     CString name = sheet.get_Name();  
  174.     sheet.ReleaseDispatch();  
  175.     return name;  
  176. }  
  177.   
  178. //按照序号加载Sheet表格,可以提前加载所有的表格内部数据  
  179. BOOL IllusionExcelFile::LoadSheet(long table_index,BOOL pre_load)  
  180. {  
  181.     LPDISPATCH lpDis = NULL;  
  182.     excel_current_range_.ReleaseDispatch();  
  183.     excel_work_sheet_.ReleaseDispatch();  
  184.     lpDis = excel_sheets_.get_Item(COleVariant((long)table_index));  
  185.     if (lpDis)  
  186.     {  
  187.         excel_work_sheet_.AttachDispatch(lpDis,true);  
  188.         excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);  
  189.     }  
  190.     else  
  191.     {  
  192.         return FALSE;  
  193.     }  
  194.       
  195.     already_preload_ = FALSE;  
  196.     //如果进行预先加载  
  197.     if (pre_load)  
  198.     {  
  199.         PreLoadSheet();  
  200.         already_preload_ = TRUE;  
  201.     }  
  202.   
  203.     return TRUE;  
  204. }  
  205.   
  206. //按照名称加载Sheet表格,可以提前加载所有的表格内部数据  
  207. BOOL IllusionExcelFile::LoadSheet(const char* sheet,BOOL pre_load)  
  208. {  
  209.     LPDISPATCH lpDis = NULL;  
  210.     excel_current_range_.ReleaseDispatch();  
  211.     excel_work_sheet_.ReleaseDispatch();  
  212.     lpDis = excel_sheets_.get_Item(COleVariant(sheet));  
  213.     if (lpDis)  
  214.     {  
  215.         excel_work_sheet_.AttachDispatch(lpDis,true);  
  216.         excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);  
  217.           
  218.     }  
  219.     else  
  220.     {  
  221.         return FALSE;  
  222.     }  
  223.     //  
  224.     already_preload_ = FALSE;  
  225.     //如果进行预先加载  
  226.     if (pre_load)  
  227.     {  
  228.         already_preload_ = TRUE;  
  229.         PreLoadSheet();  
  230.     }  
  231.   
  232.     return TRUE;  
  233. }  
  234.   
  235. //得到列的总数  
  236. int IllusionExcelFile::GetColumnCount()  
  237. {  
  238.     CRange range;  
  239.     CRange usedRange;  
  240.     usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);  
  241.     range.AttachDispatch(usedRange.get_Columns(), true);  
  242.     int count = range.get_Count();  
  243.     usedRange.ReleaseDispatch();  
  244.     range.ReleaseDispatch();  
  245.     return count;  
  246. }  
  247.   
  248. //得到行的总数  
  249. int IllusionExcelFile::GetRowCount()  
  250. {  
  251.     CRange range;  
  252.     CRange usedRange;  
  253.     usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);  
  254.     range.AttachDispatch(usedRange.get_Rows(), true);  
  255.     int count = range.get_Count();  
  256.     usedRange.ReleaseDispatch();  
  257.     range.ReleaseDispatch();  
  258.     return count;  
  259. }  
  260.   
  261. //检查一个CELL是否是字符串  
  262. BOOL IllusionExcelFile::IsCellString(long irow, long icolumn)  
  263. {  
  264.     CRange range;  
  265.     range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);  
  266.     COleVariant vResult =range.get_Value2();  
  267.     //VT_BSTR标示字符串  
  268.     if(vResult.vt == VT_BSTR)         
  269.     {  
  270.         return TRUE;  
  271.     }  
  272.     return FALSE;  
  273. }  
  274.   
  275. //检查一个CELL是否是数值  
  276. BOOL IllusionExcelFile::IsCellInt(long irow, long icolumn)  
  277. {  
  278.     CRange range;  
  279.     range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);  
  280.     COleVariant vResult =range.get_Value2();  
  281.     //好像一般都是VT_R8  
  282.     if(vResult.vt == VT_INT || vResult.vt == VT_R8)         
  283.     {  
  284.         return TRUE;  
  285.     }  
  286.     return FALSE;  
  287. }  
  288.   
  289. //  
  290. CString IllusionExcelFile::GetCellString(long irow, long icolumn)  
  291. {  
  292.      
  293.     COleVariant vResult ;  
  294.     CString str;  
  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.   
  314.     if(vResult.vt == VT_BSTR)  
  315.     {  
  316.         str=vResult.bstrVal;  
  317.     }  
  318.     //整数  
  319.     else if (vResult.vt==VT_INT)  
  320.     {  
  321.         str.Format("%d",vResult.pintVal);  
  322.     }  
  323.     //8字节的数字   
  324.     else if (vResult.vt==VT_R8)       
  325.     {  
  326.         str.Format("%0.0f",vResult.dblVal);  
  327.     }  
  328.     //时间格式  
  329.     else if(vResult.vt==VT_DATE)      
  330.     {  
  331.         SYSTEMTIME st;  
  332.         VariantTimeToSystemTime(vResult.date, &st);  
  333.         CTime tm(st);   
  334.         str=tm.Format("%Y-%m-%d");  
  335.   
  336.     }  
  337.     //单元格空的  
  338.     else if(vResult.vt==VT_EMPTY)     
  339.     {  
  340.         str="";  
  341.     }    
  342.   
  343.     return str;  
  344. }  
  345.   
  346. double IllusionExcelFile::GetCellDouble(long irow, long icolumn)  
  347. {  
  348.     double rtn_value = 0;  
  349.     COleVariant vresult;  
  350.     //字符串  
  351.     if (already_preload_ == FALSE)  
  352.     {  
  353.         CRange range;  
  354.         range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);  
  355.         vresult =range.get_Value2();  
  356.         range.ReleaseDispatch();  
  357.     }  
  358.     //如果数据依据预先加载了  
  359.     else  
  360.     {  
  361.         long read_address[2];  
  362.         VARIANT val;  
  363.         read_address[0] = irow;  
  364.         read_address[1] = icolumn;  
  365.         ole_safe_array_.GetElement(read_address, &val);  
  366.         vresult = val;  
  367.     }  
  368.       
  369.     if (vresult.vt==VT_R8)       
  370.     {  
  371.         rtn_value = vresult.dblVal;  
  372.     }  
  373.       
  374.     return rtn_value;  
  375. }  
  376.   
  377. //VT_R8  
  378. int IllusionExcelFile::GetCellInt(long irow, long icolumn)  
  379. {  
  380.     int num;  
  381.     COleVariant vresult;  
  382.   
  383.     if (already_preload_ == FALSE)  
  384.     {  
  385.         CRange range;  
  386.         range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);  
  387.         vresult = range.get_Value2();  
  388.         range.ReleaseDispatch();  
  389.     }  
  390.     else  
  391.     {  
  392.         long read_address[2];  
  393.         VARIANT val;  
  394.         read_address[0] = irow;  
  395.         read_address[1] = icolumn;  
  396.         ole_safe_array_.GetElement(read_address, &val);  
  397.         vresult = val;  
  398.     }  
  399.     //  
  400.     num = static_cast<int>(vresult.dblVal);  
  401.   
  402.     return num;  
  403. }  
  404.   
  405. void IllusionExcelFile::SetCellString(long irow, long icolumn,CString new_string)  
  406. {  
  407.     COleVariant new_value(new_string);  
  408.     CRange start_range = excel_work_sheet_.get_Range(COleVariant("A1"),covOptional);  
  409.     CRange write_range = start_range.get_Offset(COleVariant((long)irow -1),COleVariant((long)icolumn -1) );  
  410.     write_range.put_Value2(new_value);  
  411.     start_range.ReleaseDispatch();  
  412.     write_range.ReleaseDispatch();  
  413.   
  414. }  
  415.   
  416. void IllusionExcelFile::SetCellInt(long irow, long icolumn,int new_int)  
  417. {  
  418.     COleVariant new_value((long)new_int);  
  419.       
  420.     CRange start_range = excel_work_sheet_.get_Range(COleVariant("A1"),covOptional);  
  421.     CRange write_range = start_range.get_Offset(COleVariant((long)irow -1),COleVariant((long)icolumn -1) );  
  422.     write_range.put_Value2(new_value);  
  423.     start_range.ReleaseDispatch();  
  424.     write_range.ReleaseDispatch();  
  425. }  
  426.   
  427.   
  428. //  
  429. void IllusionExcelFile::ShowInExcel(BOOL bShow)  
  430. {  
  431.     excel_application_.put_Visible(bShow);  
  432.     excel_application_.put_UserControl(bShow);  
  433. }  
  434.   
  435. //返回打开的EXCEL文件名称  
  436. CString IllusionExcelFile::GetOpenFileName()  
  437. {  
  438.     return open_excel_file_;  
  439. }  
  440.   
  441. //取得打开sheet的名称  
  442. CString IllusionExcelFile::GetLoadSheetName()  
  443. {  
  444.     return excel_work_sheet_.get_Name();  
  445. }  
  446.   
  447. //取得列的名称,比如27->AA  
  448. char *IllusionExcelFile::GetColumnName(long icolumn)  
  449. {     
  450.     static char column_name[64];  
  451.     size_t str_len = 0;  
  452.       
  453.     while(icolumn > 0)  
  454.     {  
  455.         int num_data = icolumn % 26;  
  456.         icolumn /= 26;  
  457.         if (num_data == 0)  
  458.         {  
  459.             num_data = 26;  
  460.             icolumn--;  
  461.         }  
  462.         column_name[str_len] = (char)((num_data-1) + 'A' );  
  463.         str_len ++;  
  464.     }  
  465.     column_name[str_len] = '\0';  
  466.     //反转  
  467.     _strrev(column_name);  
  468.   
  469.     return column_name;  
  470. }  
  471.   
  472. //预先加载  
  473. void IllusionExcelFile::PreLoadSheet()  
  474. {  
  475.   
  476.     CRange used_range;  
  477.   
  478.     used_range = excel_work_sheet_.get_UsedRange();   
  479.   
  480.   
  481.     VARIANT ret_ary = used_range.get_Value2();  
  482.     if (!(ret_ary.vt & VT_ARRAY))  
  483.     {  
  484.         return;  
  485.     }  
  486.     //  
  487.     ole_safe_array_.Clear();  
  488.     ole_safe_array_.Attach(ret_ary);   
你可能感兴趣的文章
读取FTP上的excel文件,并写入数据库
查看>>
vs2008快捷键极其技巧 转载
查看>>
window 7上安装Visual Studio 2017失败的解决方法
查看>>
JavaScript 正整数正则表达式
查看>>
单元测试之Stub和Mock
查看>>
【转】Java泛型-类型擦除
查看>>
PredictionIO+Universal Recommender快速开发部署推荐引擎的问题总结(2)
查看>>
【232】◀▶ IDL显示地理图像
查看>>
【116】Windows 系统组合键
查看>>
学习进度表 04
查看>>
python---__getattr__\__setattr_重载'.'操作
查看>>
谈谈javascript中的prototype与继承
查看>>
时序约束优先级_Vivado工程经验与各种时序约束技巧分享
查看>>
nginx win 启动关闭_windows下nginx启动与关闭的批处理脚本
查看>>
minio 并发数_MinIO 参数解析与限制
查看>>
eap wifi 证书_用openssl为EAP-TLS生成证书(CA证书,服务器证书,用户证书)
查看>>
mysql 应用程序是哪个文件夹_Mysql 数据库文件存储在哪个目录?
查看>>
mysql半同步和无损复制_MySQL半同步复制你可能没有注意的点
查看>>
mysql能看见表显示表不存在_遇到mysql数据表不存在的问题
查看>>
使用mysql实现宿舍管理_JSP+Struts2+JDBC+Mysql实现的校园宿舍管理系统
查看>>