Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

How To Determine the Version of a Microsoft Excel Workbook


View products that this article applies to.

Summary

This article demonstrates how to determine the version of a Microsoft Excel Workbook (.xls).

↑ Back to the top


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.
  1. Create a new "Win32 Console Application" in Microsoft Developer Studio.
  2. 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, 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;
    }
    					
  3. 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");
    					

↑ Back to the top


References

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"

↑ Back to the top


Keywords: kbhowto, KB178605

↑ Back to the top

Article Info
Article ID : 178605
Revision : 10
Created on : 1/22/2007
Published on : 1/22/2007
Exists online : False
Views : 475