无Office环境读写Excel

/**************************************************************************************/
/*                                                                                                                                                                        */
/*                             XLSRW相关说明                                                                                                            */
/*                                                                                                                                                                        */
/*            wxy3064one##163.com        2009.11.18         Version:1.0                                                       */
/**************************************************************************************/

(一) 功能介绍

      XLSRW.dll是读取EXCEL5.0及其以上版本EXCEL文件的COM库

      能正确读取中文。无需OFFICE环境,效率高。
      目前最新版本是1.0.0.3  ,暂未实现写功能.
      
(二)  版本历史

      v1.0.0.0:  
           wxy   2009.11.17 ~ 2009.11.18:  将EXCEL文件格式用com的方式进行了封装,实现了读取功能.
      v1.0.0.1:      
           wxy   2009.12.9: 1.修改了FormatNumber函数,使之能够准确地显示EXCEL的浮点数,精度最高8位. 
                            2.增加了日期的显示支持.
      v1.0.0.2:                                                                                    
          wxy    2009.12.16:1.增加了EXCEL 2007(XLSX)的读取
      v1.0.0.3:
          wxy    2010.6.28: 1.修正了读取XLSX时 的死循环问题, 主要是读取每个sheet时,某些参数需重新置0
                            2.修正了读取XLSX时最后一行数据读不到的情况
 
(三)  发布方法
      1.XLSRW.dll,ICSharpCode.SharpZipLib.dll放在一起.
      2.执行Init.exe.
(四) 使用方法

      (1) XLSRW接口说明如下:

     [Guid("63B7592C-45FB-4895-B0DD-E83348E99176")]
     public interface XLSRW_Interface
     {
          [DispId(1)]
          /*
          函数名 : InitXLSRW
          参数   :
          功能   : 初始化XLSRW环境
          */
          void InitXLSRW();

          [DispId(2)]
          /*
          函数名 : ReleaseXLSRW
          参数   :
          功能   : 释放XLSRW环境
          */
          void ReleaseXLSRW();

          [DispId(3)]
          /*
          函数名 : OpenXLS
          参数   : _xlsfile EXCEL文件名
          功能   : 打开指定的EXCEL文件
               返回值 : 成功EXCEL文件的句柄,失败为-1
          */
          int OpenXLS(string _xlsfile);

          [DispId(4)]
          /*
          函数名 : CloseXLS
          参数   : _xlshandle EXCEL文件句柄
          功能   : 关闭EXCEL文件
          */
          void CloseXLS(int _xlshandle);

          /************************EXCEL文件读取*****************************/
          [DispId(5)]
          /*
          函数名 : GetWorksheetByName
          参数   : _xlshandle EXCEL文件句柄 ,_sheetname Sheet名字
          功能   : 在当前EXCEL中打开对应的Sheet
               返回值 : 成功返回true,否则为false
          */
          bool  GetWorksheetByName(int _xlshandle,string _sheetname);

          [DispId(6)]
          /*
          函数名 : GetWorksheetByIndex
          参数   :  _xlshandle EXCEL文件句柄 , _sheetindex Sheet序号,从0开始
          功能   : 在当前EXCEL中打开对应的Sheet
               返回值 : 成功返回true,否则为false
          */
          bool GetWorksheetByIndex(int _xlshandle, int _sheetindex);

          [DispId(7)]
          /*
          函数名 : getSheetTotalRows
          参数   :
          功能   : 得到当前Sheet的行数
          */
          int getSheetTotalRows();

          [DispId(8)]
          /*
          函数名 : getSheetTotalCols
          参数   :
          功能   : 得到当前Sheet的列数
          */
          int getSheetTotalCols();

          [DispId(9)]
          /*
               函数名 : getCellStr
               参数   : row 行(从0开始) col 列(从0开始)
               功能   : 在当前Sheet中读取对应行列的值
          */
          string getCellStr(int row,int col);

          /**************************************************************************/
          [DispId(10)]
          /*
               函数名 : getLastErrMsg
               参数   :
               功能   : 返回打开EXCEL时的错误
           */
          string getLastErrMsg();
          [DispId(11)]
          /*
          函数名 : GetTotalWorkSheets
          参数   : _xlshandle EXCEL文件句柄
          功能   : 得到当前EXCEL的Sheet个数
          */
          int GetTotalWorkSheets(int _xlshandle);
          [DispId(12)]
          /*
          函数名 : getSheetName
          参数   : _xlshandle EXCEL文件句柄 , _sheetindex Sheet序号,从0开始
          功能   : 得到sheet的名字
          */
          string getSheetName(int _xlshandle,int _sheetindex);
            [DispId(13)]
            /*
          函数名 : try_convert_datetime
          参数   : value 浮点数
          功能   : 将value转成日期
            */
            string try_convert_datetime(double value);
            [DispId(14)]
            /*
                函数名 : format_number
                参数   : value 字符串
               功能   : 将value转换成精度为nbits的浮点数,且以字符串输出
            */
            string format_number(string value,int nbits);   
     }

      (2)调用方法:  通过调用COM对象来实现,下面给出VC和BCB下读取EXCEL的调用方法.

          $1 VC中的使用
          Example:
                  第一步: 在文件头中加入  #import "XLSRW.tlb"

                  第二步: 调用方法: 
           CFileDialog dlg(TRUE, "xls;xlsx", "",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Excel File(*.xls;*.xlsx)");
           if (dlg.DoModal() == IDOK)
           {
            HRESULT hr;
            CoInitialize(NULL);
                          //创建XLSRW接口类实例
            XLSRW::XLSRW_InterfacePtr ptr;
            hr = ptr.CreateInstance(__uuidof(XLSRW::XLSRW_Class));
            if(hr == S_OK)
            {
                                  //初始化XLSRW环境
             ptr->InitXLSRW();
             BSTR bstrText = dlg.GetFileName().AllocSysString(); 
                                  //打开EXCEL文件
             int ret = ptr->OpenXLS(bstrText);
             if (ret >0)
             {
                                          //打开第一个sheet
              if (ptr->GetWorksheetByIndex(ret,0))
              {
                                                  //得到行,列数. 
               int maxRows = ptr->getSheetTotalRows() - 1;//通常第一行是标题行
               int maxCols = ptr->getSheetTotalCols();
               CString s;
               s.Format("(行:%d ,列: %d) ,下面显示前两行的数据",maxRows,maxCols - 1);
               AfxMessageBox(s);
               for (int r=0; r<2/*maxRows*/; ++r)
               {
                for (int c=1; c<=maxCols; ++c)
                {
          s = (LPCTSTR)ptr->getCellStr(r,c-1);
                                                                  //获取每个单元格的数据
          if (r >0)
          {
             if (c != 10)
         AfxMessageBox(s);
             else
         AfxMessageBox(ptr->try_convert_datetime(atof(s)));//将第10列按日期格式输出
                 }else
             AfxMessageBox(s);
                }
               }
              }else AfxMessageBox(ptr->getLastErrMsg());
                                          //关闭EXCEL
              ptr->CloseXLS(ret);
             }else AfxMessageBox(ptr->getLastErrMsg());
             SysFreeString(bstrText); // 用完释放
                                  //释放XLSRW环境
             ptr->ReleaseXLSRW();
            }
            CoUninitialize();  
           }        

          $2 BCB中的使用
          Example:
      //第一步: 在工程中加入  XLSRW.tlb文件,以便生成对应的 XLSRW_TLB.h文件 
                  //    (会造成类型冲突,解决办法有两种:
                  //                第一种:  直接使用生成好的XLSRW_TLB.h和XLSRW_TLB.cpp文件
                  //                第二种:  把生成的XLSRW_TLB.h中 #include "mscorlib_TLB.h" 注释掉,和mscorlib相关的文件都可以不要
                  //    )
                  //
                  第二步: 在文件头中加入  #include "XLSRW_TLB.h"
                                          #include   <objbase.h> //CoInitialize和CoUninitialize所在的头文件
                  第三步: 调用方法:  
          
             AnsiString xlsFileName;
             int maxRows,maxCols;
             int h = 0;
                  ::CoInitialize(NULL);
                  XLSRW_Interface*   pUnk   =   0;
             CoCreateInstance(CLSID_XLSRW_Class,   0,   CLSCTX_ALL,   __uuidof(XLSRW_Interface),   (void**)&pUnk);
             pUnk->InitXLSRW();
             OpenDialog1->Filter = "MicroSoft Excel files(*.xls;*.xlsx) |*.XLS;*.XLSX" ;
             if(OpenDialog1->Execute())
             {
            xlsFileName = OpenDialog1->FileName;
                       if (pUnk != 0)
                          {
           h = pUnk->OpenXLS(WideString(xlsFileName).c_bstr());
           if (h == -1)
            {
                StringGrid1->ColCount = 5;
                StringGrid1->RowCount = 5;
                for (int r=0; r<5; ++r)
                {
                    for (int c=0; c<5; ++c)
                    {
                         StringGrid1->Cells[c][r] = "";
                    }
                }
                ShowMessage( pUnk->getLastErrMsg());
           }else{
                //打开 Sheet1
                //pUnk->GetWorksheetByName(h,WideString("sheet1").c_bstr())
                if (pUnk->GetWorksheetByIndex(h,0))
                {
                    //得到 Sheet1的行列总数
                    maxRows = pUnk->getSheetTotalRows();
                    maxCols = pUnk->getSheetTotalCols();

                    StringGrid1->ColCount = maxCols + 1;
                    StringGrid1->RowCount = maxRows - 1;

                    for (int r=0; r<maxRows; ++r)
                    {
                            for (int c=0; c<=maxCols; ++c)
                            {
                            if (c != 0)
       {
                                 StringGrid1->Cells[c][r] = AnsiString(pUnk->getCellStr(r,c-1));
                                      if (r >0)
                                      {
                                                                //将第13列按日期格式输出
                                        if (c == 13)
                                        {
                                               try
                                               {
                                               StringGrid1->Cells[c][r] =  pUnk->try_convert_datetime(StrToFloat(StringGrid1->Cells[c][r]));
                                               }catch(...)
                                               {
                                               }
                                        }
                                       }
                                                         }
                                    else
                             {
                                   if (r != 0)
                                    StringGrid1->Cells[c][r] = IntToStr(r);
                             }
                            }
                    }
                    ShowMessage("StringGrid1读取完成! 共读取 行: " + IntToStr(maxRows -1) + ",  列: " + IntToStr(maxCols));
     }
                pUnk->CloseXLS(h);
    }
      }
      }
     pUnk->ReleaseXLSRW();
                   ::CoUninitialize(); 

(五) 参考文档
     (1) MicroSoft的<MICROSOFT OFFICE EXCEL 97-2007 BINARY FILE FORMAT SPECIFICATION> PDF
     (2) MicroSoft的<Windows Compound Binary File Format Specification> PDF
     (3) OpenOffice.org的<Microsoft Compound Doucument File Format> PDF 2007 Revison 1.5
     (4) OpenOffice.org的<Microsoft Excel File Format> PDF  2005 Revision 1.39

 

(六) 下载

     下载地址: http://download.csdn.net/source/3137514

(七)  未完成的功能

    1. 支持EXCEL的写功能

    2. 支持图像的读取和写入

    3. 某些不能读取的EXCEL文件的重新解读

(八) 开源

    情况许可的条件下,我会考虑将代码开源  

    v1.0.0.3 版本的开源代码下载地址(无需积分):http://download.csdn.net/source/3386509

    感兴趣的网友可以下载下来再上面增加新的功能。

   2011年6月22日 

  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值