zoukankan      html  css  js  c++  java
  • 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的。


    [cpp] view plain copy
     
    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] view plain copy
     
    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] = '';  
    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);   
  • 相关阅读:
    STL 清除模板容器 clear.h
    建立ORACLE10G DATA GUARD---&gt;Physical Standby
    WWDC 2014 Session 205/217 Extension 注意事项
    Android 布局管理器
    软件测试的基本方法(五岁以下儿童)单元测试
    HDU 4896 Minimal Spanning Tree(矩阵高速功率)
    泛泰A860(高通公司8064 cpu 1080p) 拂4.4中国民营recovery TWRP2.7.1.2文本(通过刷第三版)
    Android L SDK -- 一些有趣的新功能
    Jquery在线咨询地址
    项目开发录制两个
  • 原文地址:https://www.cnblogs.com/timssd/p/5476915.html
Copyright © 2011-2022 走看看