前言
由于种种需要直接进行读取Excel文件数据,然而在网上Search多次也没有找到好的方法,一般就通过ODBC或OLE方式进行读取,但这两种方法都具有局限性...(我相信大家都很清楚)。 介绍 MS Excel是众所周知的电子表格处理软件。Excel文件格式是特定的BIFF(Binary Interchange File Format),BIFF里存储了很多记录,第条记录包括记录头和记录体。记录头是4byte,前两位指定记录类型的代码(opcode),后两位指定记录长度;记录体是存储该记录的实际数据。 比如: 1. BOF
record 2. |
Record Header | Record Body | 3. Byte
| 0 1 2 3 | 0 1 2 3 | 4. ----------------------------------------- 5. Contents
| 09 | 00 | 04 | 00 | 02 | 00 | 10 | 00 | 6. ----------------------------------------- 7. |
opcode | length | version | file | 8. |
| | 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。 描述 以下是对本文程序简单描述。 第一步:打开文件 01. CFile
f; 02. CFileException
e; 03. 04. //
打开文件 05. if (!f.Open( "D:\\Book1.xls" ,
CFile::modeRead, &e)) 06. { 07. TCHAR szError[1024]; 08. e.GetErrorMessage(szError,
1024); 09. AfxMessageBox(szError); 10. return ; 11. } 12. 第二步:读取版本号 13. //
读取版本 14. while (dwPos
< dwLen) 15. { 16. nRead
= f.Read(( void *)&RecNo,
2); 17. if (RecNo
== XL_BOF) 18. { 19. WORD Ver,
Type; 20. f.Read(( void *)&RecLen,
2); 21. f.Read(( void *)&Ver,
2); 22. f.Read(( void *)&Type,
2); 23. f.Seek(RecLen,
CFile::current); 24. 25. int ver
= 0; 26. switch (Ver) 27. { 28. case BIFF7: 29. ver
= 7; 30. break ; 31. case BIFF8: 32. ver
= 8; 33. AfxMessageBox( "Biff8" ); 34. break ; 35. } 36. 37. int type
= 0; 38. switch (Type) 39. { 40. case WORKBOOK: 41. type
= 5; 42. AfxMessageBox( "Workbook" ); 43. break ; 44. case WORKSHEET: 45. type
= 16; 46. AfxMessageBox( "Worksheet" ); 47. break ; 48. case CHART: 49. type
= 32; 50. AfxMessageBox( "Chart" ); 51. break ; 52. } 53. 54. break ; 55. } 56. dwPos
= f.GetPosition(); 57. } 第三步:读其它数据 01. f.SeekToBegin(); 02. dwPos
= f.GetPosition(); 03. //
读表格数据 04. while (dwPos
< dwLen) 05. { 06. nRead
= f.Read(( void *)&RecNo,
2); 07. switch (RecNo) 08. { 09. case XL_BOF: 10. { 11. f.Read(( void *)&RecLen,
2); 12. AfxMessageBox( "Bof" ); 13. } 14. break ; 15. case XL_BOUNDSHEET: 16. { 17. DWORD temp; 18. BYTE visi; 19. BYTE type; 20. TCHAR name; 21. 22. f.Read(( void *)&RecLen,
2); 23. f.Read(( void *)&temp,
4); 24. f.Read(( void *)&visi,
1); 25. f.Read(( void *)&type,
1); 26. f.Read(( void *)&StrLen,
2); 27. f.Read(( void *)&name,
StrLen); 28. 29. char buf[128]; 30. memset (buf,
0x0, 128); 31. strncpy (buf,
&name, StrLen); 32. 33. AfxMessageBox(buf); 34. } 35. break ; 36. case XL_DIMENSION: 37. f.Read(( void *)&RecLen,
2); 38. f.Seek(RecLen,
CFile::current); 39. AfxMessageBox( "Dimension" ); 40. break ; 41. case 0xE2: //
INTERFACED 42. f.Read(( void *)&RecLen,
2); 43. AfxMessageBox( "e2" ); 44. break ; 45. case XL_SST: 46. f.Read(( void *)&RecLen,
2); 47. f.Seek(RecLen,
CFile::current); 48. AfxMessageBox( "SST" ); 49. break ; 50. case XL_NUMBER: 51. f.Read(( void *)&RecLen,
2); 52. AfxMessageBox( "Number" ); 53. break ; 54. case XL_STRING: 55. f.Read(( void *)&RecLen,
2); 56. AfxMessageBox( "String" ); 57. break ; 58. case XL_RK: 59. f.Read(( void *)&RecLen,
2); 60. AfxMessageBox( "RK" ); 61. break ; 62. case XL_LABEL: 63. { 64. f.Read(( void *)&RecLen,
2); 65. AfxMessageBox( "Label" ); 66. } 67. break ; 68. case 0xD6: 69. f.Read(( void *)&RecLen,
2); 70. AfxMessageBox( "RString" ); 71. break ; 72. case XL_EOF: 73. dwPos
= dwLen; 74. AfxMessageBox( "Eof" ); 75. break ; 76. default : 77. nRead
= f.Read(( void *)&RecLen,
2); 78. if (nRead
== 0) 79. dwPos
= dwLen; 80. break ; 81. } 82. } 第四步:关闭文件 1. f.Close(); 结束 本方讲述的是独立于MS Office系统,分析Excel文件格式并读取其数据。上述程序只读取最基本的信息。若需应用还需更完整的分析(我也在进行中...),当然读取Excel文件方法有多种,在这里只讲述了我使用的方法,希望与各们朋友多交流! 参考文选 1. Microsoft Excel File Format 2. MSDN Library |