tags:

views:

261

answers:

2

Is there a way to programatically retrieve the version of the Excel Interop Libraries being utilized with C#?

I know I could probably look in the registry to figure out the installed instance of Microsoft Office, but I was curious if the Excel Libraries contain this information.

I know this information is contained in Visual Studio when you reference the library, but I can't see that information at runtime.

I am asking this because it dictates the file extension when you save the workbook, and if you save a 2007 workbook with '.xls', 2007 complains about the extension being incorrect.

+1  A: 

Hi,

I think the windows registry is a good source of information in this respect. Identify the relevant keys and get their values at runtime.

This code might be inspiring:

Getting the office version

KB22
I know that I could get it from the registry, but I was looking for another way. +1 for the example code, thanks.
phsr
+2  A: 

The short answer is this: you do not need to know which PIA version is loaded to solve your problem. What you want to know is which version of Excel is actually running. Although the running Excel version and the PIA version are usually the same, they do not have to be, and, in this case, it is the Excel version that you care about, not the PIA version.

Determining which Excel version is running is not hard, but it is not quite as easy as it should be because the Excel.Application.Version property can return strings such as "11.0" or "9.0a" or the like, so one cannot necessarily directly parse it into an integer value. You can rely on the fact that everything to the left of the decimal point (".") is the version number, however, so the following code works for all versions:

Excel.Application excelApp = new Excel.Application();

string versionName = excelApp.Version;
int length = versionName.IndexOf('.');
versionName = versionName.Substring(0, length);

// int.parse needs to be done using US Culture.
int versionNumber = int.Parse(versionName, CultureInfo.GetCultureInfo("en-US"));

if (versionNumber >= 12)
{
    // Excel 2007 or above.
}
else
{
    // Excel 2003 or below.
}

As for the PIA vs. Excel object model issue, which Primary Interop Assembly (PIA) your assembly references when developing versus which PIA is actually loaded at runtime on the target machine can be different. For example, if you reference the Excel 2002 PIAs and the target machine is using Excel 2007, then (generally) the Excel 2007 PIAs will get loaded. The rule is that the highest-versioned Office PIA available on the target machine gets loaded at runtime.

It gets even more complicated in that it is possible (although, definitely not likely) for the target machine to have, say, Excel 2007 loaded on the target machine, but the highest-available PIAs be for Excel 2003. In this case, Excel 2007 would load, but your code would be working against the Excel 2003 PIAs. The reverse can occur as well: the Excel 2007 PIAs are available, but the highest actual version installed on the machine is Excel 2003 -- in this case Excel 2003 will load, but your code will be working against the Excel 2007 PIAs.

These scenarios are very unlikely in a standard setup. It is most likely to occur on a developer's machine where either (1) more than one Excel version is present on the machine at the same time, or (2) Excel versions have been added and removed, but the PIAs not removed with it (which, in itself, is also unlikely, as I believe the PIAs are uninstalled automatically, but I could be wrong about this).

For more on this, see Andrew Whitechapel's article Why is VS development not supported with multiple versions of Office?

While all these scenarios sound a bit scary, the interfaces in Excel's object model are extremely consistent and therefore are nearly 100% backward-compatible. In general, if you bind to a given Excel PIA version, then your code will run successfully against that version of Excel or higher, pretty much regardless of the scenio involved. There are a few quirks though, as you have discovered, but the key is to know which Excel version is actually running. Knowing which PIA is running is not generally important -- as long as the PIA version you developed against (or higher) is available, then the PIA itself should not cause any issues.

Edit: Follow up to phsr's comment:

When I am saving the Workbook I generate, I do need to know what PIA I am working against, because it will be saved in that format. If I get the version of the PIA, I can give the file name to correct extension ("xls" vs "xlsx"). Even if a 2007 workbook is saved as 'xls', it will give the warning about being a different format than specified by the file extension. I would like to hide that warning by using the correct extension. Your point is correct in that it really doesn't matter in the end (the file will still open) but at in some instances (like this one) it does.

I know that it might "feel like" it is the PIA that is the issue, but it is Excel object model that is actually loaded that matters here, not the PIA. In addition, there is a 99.9% chance that the Excel application version number is the SAME as the PIA version. It is extremely rare that they would differ. And where they do differ, it would be the Excel version that matters, not the PIA (so long as the PIA is the same version as the PIA you developed against, or higher).

To try to clarify this, the PIAs only specify the interfaces involved, not the functionality. The Excel 2003 SaveAs method has exactly the same parameter signature as the Excel 2007 SaveAs method, so the PIAs do not differ here. How the SaveAs method is executed, however, depends on which version of the Excel object model is actually running.

To fix your problem, I can suggest taking one of two possible courses of action:

(1) Try the code I gave above to determine the Excel version that is running. If you do this and adjust your code accordingly it will work, I promise. If it fails, show your code and I'm sure we can get it to work.

(2) Don't specify the extension in the workbook name that you give it. Let the Excel application add the default extension for you. You are correct in that if you specify a ".xls" extension when saving in Excel 2007, it will respect that extension, but not the workbook version. Easiest here, however, is to simply omit the extension when saving your workbook and the Excel application will automatically append ".xls" or ".xlsx" to the workbook name, depending on which Excel version is currently running:

Excel.Application excelApp = new Excel.Application();    
Excel.Workbook workbook = excelApp.Workbooks.Add(Type.Missing);

workbook.SaveAs(
    "MyWorkbook", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
     Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, 
     Type.Missing, Type.Missing);

The result of the above is a workbook named either "MyWorkbook.xls" or "MyWorkbook.xlsx", depending on which version of Excel is running. In short, let Excel do the work for you so that you don't have to worry about it.

Mike Rosenblum
When I am saving the Workbook I generate, I do need to know what PIA I am working against, because it will be saved in that format. If I get the version of the PIA, I can give the file name to correct extension ("xls" vs "xlsx"). Even if a 2007 workbook is saved as 'xls', it will give the warning about being a different format than specified by the file extension. I would like to hide that warning by using the correct extension. Your point is correct in that it really doesn't matter in the end (the file will still open) but at in some instances (like this one) it does.
phsr
It really is the Excel version that is running that you need to worry about here, not the PIA version, honest. I promise. See my update, above, under the section "Edit: Follow up to phsr's comment".
Mike Rosenblum