直接读取Excel文件数据

 

下载源代码

前言
  由于种种需要直接进行读取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();    

你可能感兴趣的:(直接读取Excel文件数据)