The information in this article applies to:
- Microsoft Visual C++, 32-bit Editions, version 5.0
- Microsoft Excel 97 for Windows
- Microsoft Excel for Windows 95, versions 7.0, 7.0a
- Microsoft Excel for Windows, versions 5.0, 5.0a, 5.0c
SUMMARY
This article demonstrates how to determine the version of a Microsoft Excel
Workbook (.xls).
MORE INFORMATION
Microsoft Excel saves data using structured storage. In particular, it
creates a data stream called "Workbook" (previously just "Book") where
it saves the contents starting with a BOF (beginning of file) record. This
record contains useful attributes of the workbook, as well as the version.
The following Microsoft Visual C++ code demonstrates how to open the file,
read it, and return the version number based on the BOF.
- Create a new "Win32 Console Application" in Microsoft Developer Studio.
- Add a C++ Source File (.cpp) to the project and add the following code
to the source file:
#include <windows.h>
#include <iostream.h> // My additions
// BOF record from Microsoft Excel
typedef struct _xlbof
{
char bofMarker; // Should be 0x09
char vers; // Version indicator for biff2, biff3, and biff4
// = 0x00 -> Biff2
// = 0x02 -> Biff3
// = 0x04 -> Biff4
// = 0x08 -> Biff5/Biff7/Biff8
char skip[2]; // Unspecified
short int vers2; // Version number
// 0x0500 -> Biff5/Biff7
// 0x0600 -> Biff8
short int dt; // Substream type (not used in this example)
short int rupBuild; // Internal build identifier
short int rupYear; // Internal Build year
} XLBOF;
//* XLVersionFromFile() ******************************************
//* Returns
//* n for BiffN
//* i.e. 8 for Biff8 (Microsoft Excel 97)
//*
//* Negative if an error occurs
//****************************************************************
int XLVersionFromFile(char *filename) {
// Translate filename to Unicode
WCHAR wcFilename[1024];
int i = mbstowcs(wcFilename, filename, strlen(filename));
wcFilename[i] = 0;
IStorage *pStorage;
HRESULT hr;
XLBOF xlbof;
// Open the document as an OLE compound document
hr = ::StgOpenStorage(wcFilename, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
if(!FAILED(hr)) {
// Open the data-stream where Microsoft Excel stores the data
IStream *pStream;
hr = pStorage->OpenStream(L"Workbook", NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
// If "Workbook" does not exist, try "Book"
if(FAILED(hr)) {
hr = pStorage->OpenStream(L"Book", NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
}
if(!FAILED(hr)) {
// Read the relevant BOF information
DWORD dwCount; // bytes read
pStream->Read(&xlbof, sizeof(XLBOF), &dwCount);
// Let go of the IStream pointer
pStream->Release();
}
else return -2;
// Let go of the IStorage pointer
pStorage->Release();
}
else return -1;
// Determine which version to return
if(xlbof.vers != 0x08) return (xlbof.vers + 4) / 2;
else {
switch(xlbof.vers2) {
case 0x0500: // Either Biff5 or Biff7
// Biff7's rupYear is at least 1994
if(xlbof.rupYear < 1994) return 5;
// Check for specific builds of Microsoft Excel 5
switch(xlbof.rupBuild) {
case 2412: // XL5a
case 3218: // XL5c
case 3321: // NT XL5
return 5;
default:
return 7;
}
case 0x0600: return 8;
}
}
// Version not recognized. Perhaps there is a newer version.
return -3;
}
void main()
{
int iretVal = 0;
iretVal = XLVersionFromFile("C:\\Test.xls");
//Adapt the filename to your example
cout << "The Excel Version is " << iretVal << "\n\n\r";
return;
}
- In the main()function, you may need to modify the path and filename of
the Microsoft Excel workbook in the following line of code:
iretVal = XLVersionFromFile("C:\\Test.xls");
REFERENCES
Microsoft Visual C++ Help, version 5.0; search on “structured storage”
Microsoft Developer’s Network (MSDN); search on “structured storage”,
“Microsoft Excel file format”, BOF”, “beginning of file”
Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2); search on
“Microsoft Excel file format”, BOF”, “beginning of file”
|