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

C# 以编程方式检索Excel库的版本,c#,excel,C#,Excel,有没有一种方法可以通过编程检索与C#一起使用的Excel互操作库的版本 我知道我可能会在注册表中查找已安装的Microsoft Office实例,但我很好奇Excel库是否包含此信息 我知道当您引用库时,这些信息包含在VisualStudio中,但在运行时我看不到这些信息 我问这个问题是因为在保存工作簿时,它指定了文件扩展名,如果使用“.xls”保存2007工作簿,2007会抱怨扩展名不正确。我认为windows注册表在这方面是一个很好的信息来源。 识别相关键并在运行时获取它们的值 这段代码可能

有没有一种方法可以通过编程检索与C#一起使用的Excel互操作库的版本

我知道我可能会在注册表中查找已安装的Microsoft Office实例,但我很好奇Excel库是否包含此信息

我知道当您引用库时,这些信息包含在VisualStudio中,但在运行时我看不到这些信息


我问这个问题是因为在保存工作簿时,它指定了文件扩展名,如果使用“.xls”保存2007工作簿,2007会抱怨扩展名不正确。

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

这段代码可能很有启发性:


简单的回答是:您不需要知道加载了哪个PIA版本就可以解决您的问题。您想知道的是Excel的实际运行版本。尽管正在运行的Excel版本和PIA版本通常是相同的,但它们不一定是相同的,在本例中,您关心的是Excel版本,而不是PIA版本

确定哪个Excel版本正在运行并不困难,但这并不像应该的那么容易,因为
Excel.Application.version
属性可以返回字符串,如“11.0”或“9.0a”或类似的字符串,因此不必直接将其解析为整数值。但是,您可以相信小数点(“.”)左侧的所有内容都是版本号,因此以下代码适用于所有版本:

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可能有所不同。例如,如果您引用Excel2002PIA,并且目标计算机正在使用Excel2007,则(通常)将加载Excel2007PIA。规则是在运行时加载目标计算机上可用的最高版本的Office PIA

它变得更加复杂,因为目标机器可能(尽管,绝对不可能)在目标机器上加载Excel 2007,但可用的最高PIA是Excel 2003。在本例中,将加载Excel2007,但您的代码将针对Excel2003PIA工作。相反的情况也可能发生:Excel 2007 PIA可用,但计算机上实际安装的最高版本是Excel 2003——在本例中,将加载Excel 2003,但您的代码将针对Excel 2007 PIA工作

这些场景在标准设置中不太可能出现。这很可能发生在开发人员的计算机上,其中(1)计算机上同时存在多个Excel版本,或者(2)添加和删除了Excel版本,但没有删除PIA(这本身也不太可能,因为我相信PIA是自动卸载的,但我可能错了)

有关这方面的更多信息,请参阅Andrew Whitechapel的文章

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

编辑:phsr评论的后续行动:


当我保存工作簿时,我 生成,我确实需要知道我的PIA是什么 我反对,因为它会 以那种格式保存。如果我得到 PIA的版本,我可以给出 将文件名改为正确的扩展名(“xls” vs“xlsx”)。即使2007工作簿是 保存为“xls”,它将提供 关于使用不同格式的警告 而不是由文件扩展名指定的。 我想把这个警告隐藏起来 使用正确的扩展名。你的 这一点是正确的,因为它确实 最后没关系(文件 仍将打开)但在某些情况下 实例(如本例)确实如此

我知道可能“感觉”问题出在PIA上,但实际上加载的Excel对象模型才是关键,而不是PIA。此外,Excel应用程序版本号与PIA版本相同的可能性为99.9%。这是极为罕见的,他们会有所不同。如果它们存在差异,那么重要的是Excel版本,而不是PIA(只要PIA与您开发的PIA版本相同或更高)

为了澄清这一点,PIA只指定了涉及的接口,而不是功能。的参数签名与的完全相同,因此PIA在这里没有区别。然而,
SaveAs
方法的执行方式取决于Excel对象模型的实际运行版本

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

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

(2) 不要在您指定的工作簿名称中指定扩展名。让Excel应用程序为您添加默认扩展名。如果在Excel 2007中保存时指定“.xls”扩展名,则它将尊重该扩展名,而不是工作簿版本,这是正确的。然而,这里最简单的方法是在保存工作簿和Excel应用程序时忽略扩展名
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);
[DllImport("XLCALL32.DLL")]
public static extern int XLCallVer();
int version = XLCallVer() / 256;
double version = ExcelDnaUtil.ExcelVersion;