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

写了不少blog,也码了一点点文字,不知道为啥,被大家看的比较多几篇文章却总有那篇《C++读写EXCEL文件方式比较》。

小小伤心一下,我blog里面写的很认真的文字还有几篇,这篇大概是最随意的文章。个人估计这是SEO的作用导致的。

另外,由于文中提到了可以加快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的。


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

  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);   
  489. }  
/******************************************************************************************
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); 
}

【本文作者是雁渡寒潭,本着自由的精神,你可以在无盈利的情况完整转载此文档,转载时请附上BLOG链接:http://www.cnblogs.com/fullsail/ 或者http://blog.csdn.net/fullsail,否则每字一元,每图一百不讲价。对Baidu文库。360doc加价一倍】




  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++Builder精彩编程实例集锦的源代码(1,2,3部分): 第一部分 界面设计 实例001 如何实现程序闪屏效果 实例002 如何实现程序窗口闪烁 实例003 如何制作吸附窗口程序 实例004 如何制作透明程序窗口 实例005 如何制作半透明程序窗口 实例006 如何制作不规则程序窗口 实例007 如何制作程序渐变背景 实例008 如何设置程序背景图像 实例009 如何设置MDI程序背景图像 实例010 如何动态关闭MDI程序所有子窗口 实例011 如何去掉MDI程序子窗口标题栏 实例012 如何拖动非标题栏区域移动窗口 实例013 如何控制程序最小化窗口 实例014 如何限制程序最大最小化窗口 实例015 如何控制程序窗口自动隐藏或显示 实例016 如何隐藏应用程序 实例017 如何控制程序在任务栏上是否出现 实例018 如何使一个程序在任务栏同时出现多个标题 实例019 如何使程序窗口总在最前面显示 实例020 如何隐藏应用程序标题栏 实例021 如何设置程序主标题 实例022 如何设置程序图标 实例023 如何在程序中改变菜单位置 实例024 如何删除程序系统关闭菜单 实例025 如何拷贝当前程序界面 实例026 如何动态创建程序表单 实例027 如何遍历窗体所有组件 实例028 如何保证组件位置相对固定 实例029 如何在窗体中动态增加组件 实例030 如何使组件在程序运行时可以移动 实例031 如何使用组件创建托盘程序 实例032 如何使用动画组件播放动画 实例033 如何在状态栏上加载进度条 实例034 如何在编辑框内显示图像 实例035 如何在列表框中增加水平滚动条 实例036 如何在列表框中同时显示图像和文字 实例037 如何设置属性表组件标签图像 实例038 如何控制Memo组件的文字边界 实例039 如何使用代码控制文字滚动 实例040 如何纵向显示字符串 实例041 如何旋转显示字符串 实例042 如何设置显示文字分辨率 第二部分 程序设置 实例043 如何使用消息框 实例044 如何显示简单关于对话框 实例045 如何在程序中增加热键 实例046 如何在程序中自定义消息 实例047 如何在程序中自定义系统菜单 实例048 如何在执行程序间进行数据通信 实例049 如何使用OLE技术启动画图 实例050 如何在程序中添加Word文档表格 实例051 如何在程序中设置Word文档的字体风格 实例052 如何使用Onldle事件 实例053 如何使程序在循环时响应外界事件 实例054 如何设置程序在系统启动时自动运行 实例055 如何创建多线程程序 实例056 如何创建可独立执行程序 实例057 如何编写单文档应用程序 实例058 如何编写多文档应用程序 实例059 如何编写COM服务器程序 实例060 如何编写COM客户端程序 实例061 如何编写DDE服务器程序 实例062 如何编写DDE客户端程序 实例063 如何编写DLL服务器程序 实例064 如何编写DLL客户端程序 实例065 如何注册DLL服务器程序 实例066 如何制作聊天服务器程序 实例067 如何制作聊天客户端程序 实例068 如何获取程序名称和路径 实例069 如何获取程序命令行参数 实例070 如何析取动态链接库中的图标 实例071 如何设置Edit组件的文本选择范围 实例072 如何将小写金额转换成大写金额 实例073 如何将全角字符串转换成半角字符串 实例074 如何按照指定的有效位数转换数字 实例075 如何获取汉字的拼音索引 实例076 如何设置输入方法 实例077 如何控制数据输入格式 实例078 如何控制编辑框中的输入法 实例079 如何设置回车键后的焦点 实例080 如何将项目保存到对象库 实例081 如何检测鼠标信息 实例082 如何读取鼠标信息 实例083 如何实现鼠标拖动操作 实例084 如何限制鼠标活动范围 实例085 如何读取键盘信息 第三部分 文件操作 实例086 如何复制文件 实例087 如何定制文件复制操作 实例088 如何更名文件 实例089 如何更改文件扩展名 实例090 如何删除文件 实例091 如何删除文件夹 实例092 如何选择文件夹 实例093 如何创建多层文件夹 实例094 如何自动获取文件夹和文件 实例095 如何搜索指定目录下的文件 实例096 如何搜索指定目录下的隐藏文件 实例097 如何搜索文本文件中的字符串 实例098 如何替换文本文件中的字符串 实例099 如何将长文件名转换为短文件名 实例100 如何在文件打开对话框中选择多个文件 实例101 如何定制文件打开和关闭对话框 实例102 如何修改文件打开对话框的按钮标题 实例103 如何使用查找与替换对话框 实例104 如何获取和设置当前目录 实例105 如何判断文件类型 实例106 如何获取系统所有文件类型 实例107 如何获取和设置文件属性 实例108 如何获取和设置文件时间属性 实例109 如何对文件名函数进行操作 实例110 如何读写文本文件 实例111 如何打印文本文件 实例112 如何创建特大型文件 实例113 如何制作临时文件 实例114 如何启动帮助文件 实例115 如何使用组件在主机问传送文件 实例116 如何对文件进行编码和解码 实例117 如何设置RichEdit组件的存盘格式 实例118 如何在WIN.INI文件中保存程序信息 实例119 如何将数据转换成Word文档格式 实例120 如何直接从Excel文件导入数据 实例121 如何直接将数据导入到Excel文件 实例122 如何发送电子邮件(一) 实例123 如何发送电子邮件(二)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值