#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, Excel 2000, Excel 2002)
//*
//* 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;
}