直接读取Excel文件数据

来源:互联网 发布:淮南职业技术学院网络 编辑:程序博客网 时间:2024/05/29 14:36

http://www.vckbase.com/document/viewdoc/?id=815

前言
 
由于种种需要直接进行读取Excel文件数据,然而在网上Search多次也没有找到好的方法,
一般就通过ODBCOLE方式进行读取,但这两种方法都具有局限性...(我相信大家都很清楚)。
怎么办呢?没办法了,只好选择最艰难的路了--分析Excel文件格式。
介绍
  MS Excel
是众所周知的电子表格处理软件。Excel文件格式是特定的BIFF(Binary Interchange File Format)BIFF里存储了很多记录,第条记录包括记录头和记录体。记录头是4byte,前两位指定记录类型的代码(opcode),后两位指定记录长度;记录体是存储该记录的实际数据。
比如:

BOF record

           |  Record Header    |    Record Body    |

Byte       |  0    1    2    3 |  0    1    2    3 |

           -----------------------------------------

Contents   | 09 | 00 | 04 | 00 | 02 | 00 | 10 | 00 |

           -----------------------------------------

           | opcode  | length  | version |  file   |

           |         |         |  number |  type   |

记录头:

       opcode: 09h is BOF;

       length: 04h record body is 4 bytes long;

记录体:

       version number:02h is version number (2 for the initial version of Excel)

       file type:10h is a worksheet file;

具体可参考MS Excel File Format

描述
以下是对本文程序简单描述。

      第一步:打开文件

       CFile f;

       CFileException e;

 

       // 打开文件

       if (!f.Open("D://Book1.xls", CFile::modeRead, &e))

       {

              TCHAR szError[1024];

              e.GetErrorMessage(szError, 1024);

              AfxMessageBox(szError);

              return;

       }

       第二步:读取版本号

       // 读取版本

       while (dwPos < dwLen)

       {

              nRead = f.Read((void*)&RecNo, 2);

              if (RecNo == XL_BOF)

              {

                    WORD Ver, Type;

                    f.Read((void*)&RecLen, 2);

                    f.Read((void*)&Ver, 2);

                    f.Read((void*)&Type, 2);

                    f.Seek(RecLen, CFile::current);

 

                    int ver = 0;

                    switch (Ver)

                    {

                    case BIFF7:

                           ver = 7;

                           break;

                    case BIFF8:

                           ver = 8;

                           AfxMessageBox("Biff8");

                           break;

                    }

 

                    int type = 0;

                    switch (Type)

                    {

                    case WORKBOOK:

                           type = 5;

                           AfxMessageBox("Workbook");

                           break;

                    case WORKSHEET:

                           type = 16;

                           AfxMessageBox("Worksheet");

                           break;

                    case CHART:

                           type = 32;

                           AfxMessageBox("Chart");

                           break;

                    }

 

                    break;

              }

              dwPos = f.GetPosition();

       }     

       第三步:读其它数据

       f.SeekToBegin();

       dwPos = f.GetPosition();

       // 读表格数据

       while (dwPos < dwLen)

       {

              nRead = f.Read((void*)&RecNo, 2);

              switch (RecNo)

              {

              case XL_BOF:

                    {

                           f.Read((void*)&RecLen, 2);

                           AfxMessageBox("Bof");

                    }

                    break;

              case XL_BOUNDSHEET:

                    {

                           DWORD  temp;

                           BYTE   visi;

                           BYTE   type;

                           TCHAR  name;

                          

                           f.Read((void*)&RecLen, 2);

                           f.Read((void*)&temp, 4);

                           f.Read((void*)&visi, 1);

                           f.Read((void*)&type, 1);

                           f.Read((void*)&StrLen, 2);

                           f.Read((void*)&name, StrLen);

                          

                           char buf[128];

                           memset(buf, 0x0, 128);

                           strncpy(buf, &name, StrLen);

                          

                           AfxMessageBox(buf);

                    }

                    break;

              case XL_DIMENSION:

                    f.Read((void*)&RecLen, 2);

                    f.Seek(RecLen, CFile::current);

                    AfxMessageBox("Dimension");

                    break;

              case 0xE2:    // INTERFACED

                    f.Read((void*)&RecLen, 2);

                    AfxMessageBox("e2");

                    break;

              case XL_SST:

                    f.Read((void*)&RecLen, 2);

                    f.Seek(RecLen, CFile::current);

                    AfxMessageBox("SST");

                    break;

              case XL_NUMBER:

                    f.Read((void*)&RecLen, 2);

                    AfxMessageBox("Number");

                    break;

              case XL_STRING:

                    f.Read((void*)&RecLen, 2);

                    AfxMessageBox("String");

                    break;

              case XL_RK:

                    f.Read((void*)&RecLen, 2);

                    AfxMessageBox("RK");

                    break;

              case XL_LABEL:

                    {

                           f.Read((void*)&RecLen, 2);

                           AfxMessageBox("Label");

                    }

                    break;

              case 0xD6:

                    f.Read((void*)&RecLen, 2);

                    AfxMessageBox("RString");

                    break;

              case XL_EOF:

                    dwPos = dwLen;

                    AfxMessageBox("Eof");

                    break;

              default:

                    nRead = f.Read((void*)&RecLen, 2);

                    if (nRead == 0)

                           dwPos = dwLen;

                    break;

              }

       }

       第四步:关闭文件

       f.Close();  

结束
本方讲述的是独立于MS Office系统,分析Excel文件格式并读取其数据。上述程序只读取最基本的信息。若需应用还需更完整的分析(我也在进行中...),当然读取Excel文件方法有多种,在这里只讲述了我使用的方法,
希望与各们朋友多交流!

参考文选
1. Microsoft Excel File Format
2. MSDN Library