1

我正在使用后期绑定(在 C# 中,使用反射等)通过 COM 访问 Excel。换句话说,我首先使用获取 Excel.Application 对象

Type excelType = Type.GetTypeFromProgId("Excel.Application");
object excelApplication = Activator.CreateInstance(excelType);

(实际上,它比这更通用,但这给出了这个想法)。

正如许多人在 StackOverflow 中所指出的,了解如何使用 Office 的 COM 接口的一种好方法是在 Excel 中记录一个宏,然后查看 VBA 代码以查看要调用哪些类成员。

当我这样做时,我看到如果您有对活动单元格的引用(从 Excel.Application 对象的 ActiveCell 属性获得),则 VBA 引用 ActiveCell.Offset(x,y) 以引用相对于该 ActiveCell 的单元格(x 和 y 是行和列索引)。但是,如果我尝试访问具有后期绑定的 Cell 的 Offset 方法,则 InvokeMember 方法将失败,并出现“未找到成员”的异常。

如果我使用 Visual Studio 对象浏览器检查 Microsoft.Office.Interop.Excel 命名空间和 ApplicationClass 类(我假设它可以很好地查看上述 C# 代码通过 ProgId 获取的 COM 接口),它显示该ApplicationClass 具有Microsoft.Office.Interop.Excel.Range 类型的ActiveCell 属性。并且检查该类表明它确实没有名为“Offset”的成员,因此当我尝试调用它时“找不到成员”。

这似乎意味着 VBA 宏使用的 Excel 对象模型与通过 COM 公开的对象模型不同!是这样吗,还是我错过了什么?如果是这样,我如何通过 COM 中的后期绑定获得相同的 VBA 对象模型?

或者,是否有某种方法,使用 Offset 以外的方法,能够将 ActiveCell 移动到下一行的开头,这真的是我想要的吗?

4

2 回答 2

0

你可以试试这个:

dim i as integer

i = ActiveCell.Row + 1

Excel.ActiveSheet.Cells(i,1).value = "Whatever your value is."
于 2012-12-27T20:08:42.787 回答
0

像往常一样,当您知道如何操作时,答案很容易。

我的代码比我的问题中的示例稍远一点,看起来有点像这样:

object activeCell;
object result;
// in here code to get the correct value into activeCell
if(activeCell.GetType().GetProperty("Offset") == null){
  result = activeCell.GetType().InvokeMember("Offset", BindingFlags.InvokeMethod, null, activeCell, new object[] {1, 0});
}

正是 InvokeMember 引发了异常,并显示消息“未找到成员”。

当我将参数更改为 InvokeMember 时,如下所示:

result = activeCell.GetType().InvokeMember("Offset", BindingFlags.InvokeMethod | BindingFlags.GetProperty, null, activeCell, new object[] {1, 0});

然后它起作用了。

它为什么起作用仍然是一个谜,如果他们回答它,我相信他们会赢得一些声誉。

于 2012-12-28T11:45:14.320 回答