使用Excel Interop检索单元格值

时间:2013-05-13 15:43:55

标签: c#-4.0 vsto excel-interop

我正在尝试使用Excel互操作从电子表格中检索单元格值,但我正在使用的以下代码正在生成编译器错误:

  

无法找到编译动态表达式所需的一种或多种类型。你错过了参考吗?

Range currentFind = sheet.Cells.Find("some string", Type.Missing,
                    XlFindLookIn.xlValues, XlLookAt.xlPart, 
                    XlSearchOrder.xlByRows, XlSearchDirection.xlNext,
                    false, Type.Missing, Type.Missing);

if (currentFind[1,1].Value != null)
{
    string CellValue = currentFind[1,1].Value.ToString();
}

知道这里发生了什么吗?我猜可能需要投出一些东西,但我不确定是什么。我尝试过投射currentFind[1,1].Value,但这似乎不起作用。

修改

我找到了一个解决方法,在引用上将Embed Interop Types设置为False,但我仍然想知道这里发生了什么以及如何处理这种情况。

2 个答案:

答案 0 :(得分:4)

您是否添加了对Microsoft.CSharp以及Microsoft.Office.Interop.Excel的引用?这在过去为我解决了这个问题 - 例外是说缺少解析dynamic属性Value类型所需的类型信息。该异常通常也会尝试建议缺少的引用。

Embed Interop类型发生了什么?

.NET(C#)4.0引入了dynamic和处理COM host return object values as the dynamic type的能力。这应该使我们在编写代码时更容易,因为我们不必在编写代码时将返回对象显式地转换为我们想要的类型。如果程序集中的“嵌入互操作类型”设置为true,则会发生这种情况;这也是您在VS中添加的引用的默认值。

本质上,VS在编译时为您在程序集中使用的类型嵌入了的PIA子集(请参阅"what is the advantage of .net4's new no pia feature [deploying PIA's]"的答案,了解为什么这样做很好)。但是,它需要访问参考树中的所有PIA才能执行此操作。

dynamic允许后期绑定。所以我猜你的情况Value已成为一个动态类型,它将在运行时解决,这是错误的,因为它无法获得正确的程序集和PIA引用。如果您将“嵌入互操作类型”转换为false,则Value会变为object类型,这可以防止出现问题(但您现在需要在某些时候转换为正确的类型)。< / p>

为什么要嵌入PIA信息?

它可以更轻松地部署和支持多个版本的Office(只要您在早期版本或更高版本中不使用不受支持的功能,而不是您测试的版本)。但这并不容易;很多都可能出错。

MSDN - Walkthrough: Office Programming (C# and Visual Basic)提到了这一点,但除了说它是一件好事外,并没有做太多其他事情。

举个例子:如果我在VS2010中启动项目并引用位于

的VSTO Excel 2010互操作
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office12\Microsoft.Office.Interop.Excel.dll

然后我没有将嵌入互操作类型设置为true的问题,因为它会自动添加

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client\Microsoft.CSharp.dll

也作为参考。如果我然后删除Microsoft.CSharp引用,我得到编译器错误,但它指出以下错误,这是我最初找到我的解决方案的方式:

  

无法找到编译动态表达式所需的一种或多种类型。您是否缺少对Microsoft.CSharp.dll和System.Core.dll的引用?

答案 1 :(得分:0)

您似乎需要为项目添加一些参考。不确定您拥有的其他代码,但如果是这样,您需要将interop程序集添加到项目中。检查编辑器是否标记了任何有错误的行,并检查在该行中使用的对象的类型。

另一方面,我看到以下一行存在潜在问题:

if (currentFind[1,1].Value != null)

如果未找到该值,则currentFind为null,并且您尝试像数组一样访问null。尝试检查currentFind是否为空:

if (currentFind != null)