2008年(909)
分类:
2008-05-06 21:51:54
下载源代码
前言
由于种种需要直接进行读取Excel文件数据,然而在网上Search多次也没有找到好的方法,
一般就通过ODBC或OLE方式进行读取,但这两种方法都具有局限性...(我相信大家都很清楚)。
怎么办呢?没办法了,只好选择最艰难的路了--分析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();结束