以编程方式检索Excel库的版本

有没有一种方法来编程检索C#使用的Excel Interop库的版本?

我知道我大概可以在registry中找出已安装的Microsoft Office实例,但我很好奇,如果Excel库包含此信息。

我知道这个信息包含在Visual Studio中,当你引用这个库时,但是在运行时我看不到这些信息。

我问这是因为它指定文件扩展名,当您保存工作簿,并且如果您保存2007年工作簿与“.xls”,2007抱怨扩展是不正确的。

简短的答案是这样的:你不需要知道哪个PIA版本被加载来解决你的问题。 你想知道什么版本的Excel实际上正在运行。 尽pipe正在运行的Excel版本和PIA版本通常是相同的,但它们不一定是,在这种情况下,它是您关心的Excel版本,而不是PIA版本。

确定运行哪个Excel版本并不困难,但不像应该那样容易,因为Excel.Application.Version属性可以返回诸如“11.0”或“9.0a”之类的string,所以不一定直接parsing成一个整数值。 您可以依赖于小数点左侧(“。”)的所有内容都是版本号,所以下面的代码适用于所有版本:

 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. } 

至于PIA与Excel对象模型的问题,您的程序集在开发时所参考的主互操作程序集(PIA)与实际在目标机器上运行时加载哪个PIA可能不同。 例如,如果您引用Excel 2002 PIA并且目标机器正在使用Excel 2007,则(通常)将会加载Excel 2007 PIA。 规则是在目标机器上可用的最高版本的Office PIA在运行时被加载。

它变得更加复杂,因为目标机器可能(但绝对不可能),例如,Excel 2007加载到目标机器上,但是最高可用的PIA是Excel 2003。在这种情况下,Excel 2007年将加载,但您的代码将对Excel 2003 PIA工作。 也可以反过来:Excel 2007 PIA可用,但是机器上安装的最高实际版本是Excel 2003 – 在这种情况下,Excel 2003将加载,但是您的代码将与Excel 2007 PIA一起工作。

这些场景在标准设置中是不太可能的。 (1)同时在机器上存在多个Excel版本,或者(2)Excel版本已被添加或删除,但是PIA不会随其删除这本身也是不太可能的,因为我相信这些PIA是自动卸载的,但是我可能是错的)。

有关更多信息,请参阅Andrew Whitechapel的文章为什么VS开发不支持多个版本的Office?

虽然所有这些场景听起来有点可怕,Excel的对象模型中的接口是非常一致的,因此几乎100%向后兼容。 一般来说,如果你绑定到一个给定的Excel PIA版本,那么你的代码将成功运行在Excel或更高的版本上,几乎不pipe涉及到什么。 不过,你已经发现了一些怪癖,但关键是要知道哪个Excel版本实际运行。 了解哪个PIA运行并不重要 – 只要您开发的PIA版本(或更高版本)可用,那么PIA本身不应该引起任何问题。

编辑:跟进phsr的评论:

当我保存我生成的工作簿时,我确实需要知道我所针对的PIA,因为它将以这种格式保存。 如果我得到PIA的版本,我可以给文件名正确的扩展名(“xls”vs“xlsx”)。 即使2007年的工作簿保存为“xls”,也会给出与文件扩展名指定格式不同的警告。 我想通过使用正确的扩展名隐藏该警告。 你的观点是正确的,因为它最终并不重要(文件仍然会打开),但在某些情况下(比如这个)它确实没有关系。

我知道它可能“感觉”是PIA是问题,但它是Excel对象模型,实际上装载在这里很重要,而不是PIA。 此外,Excel应用程序版本号与PIA版本相同的可能性为99.9%。 他们会有所不同,这是非常罕见的。 而且它们的区别在于Excel的版本,而不是PIA(只要PIA与您开发的PIA版本相同或更高)。

为了澄清这一点,PIA仅指定涉及的接口,而不是function。 Excel 2003 SaveAs方法具有与Excel 2007 SaveAs方法完全相同的参数签名,因此这里的PIA不会有所不同。 但是,如何执行SaveAs方法取决于哪个版本的Excel对象模型实际上正在运行

要解决您的问题,我可以build议采取两种可能的行动之一:

(1)尝试我上面给出的代码来确定正在运行的Excel版本。 如果你这样做,并相应地调整你的代码,它将工作,我保证。 如果失败,请显示您的代码,我相信我们可以将其运行。

(2)不要在工作簿名称中指定扩展名。 让Excel应用程序为您添加默认扩展名。 如果您在Excel 2007中保存时指定了“.xls”扩展名,则说明该扩展名符合该扩展名,但不符合工作簿版本。 但是,最简单的方法是在保存工作簿时简单省略扩展名,Excel应用程序将根据当前正在运行的Excel版本自动将“.xls”或“.xlsx”附加到工作簿名称中:

 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); 

上面的结果是一个名为“MyWorkbook.xls”或“MyWorkbook.xlsx”,取决于哪个版本的Excel正在运行的工作簿。 简而言之,让Excel为您做好工作,让您不必担心。

我认为Windowsregistry是这方面的一个很好的信息来源。 识别相关的键并在运行时获取它们的值。

这个代码可能是鼓舞人心的:

获取办公室版本

试试这个(来自ExcelDna的源代码):

把这个代码放在类声明的某个地方:

 [DllImport("XLCALL32.DLL")] public static extern int XLCallVer(); 

在需要的地方调用这个函数:

 int version = XLCallVer() / 256; 

或者,如果您使用ExcelDna,则可以调用directry:

 double version = ExcelDnaUtil.ExcelVersion;