HOWTO: Determine the Version of a Microsoft Excel WorkbookID: Q178605
|
This article demonstrates how to determine the version of a Microsoft Excel Workbook (.xls).
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.
#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;
}
iretVal = XLVersionFromFile("C:\\Test.xls");
Microsoft Visual C++ Help, version 5.0; search on "structured storage"
Microsoft Developers 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"
Additional query words: excel97 excel8 xl5en32 kbOle kbVC500 kbSDKExcel kbExcel kbDSupport kbdsd
Keywords : kbcode kbExcel kbVC500 kbVC600 kbExcel97
Version : Win95:5.0,5.0a,5.0c,7.0,7.0a,97; winnt:5.0
Platform : Win95 winnt
Issue type : kbhowto
Last Reviewed: July 20, 1999