Excel互操作:_Worksheet还是Worksheet?

81

我目前正在写有关动态类型的内容,并给出了Excel互操作的示例。我几乎没有做过任何Office互操作,并且这表现出来了。C# 4的MSDN Office Interop教程使用_Worksheet接口,但也有一个Worksheet接口。我不知道它们之间的区别。

在我可笑简单的演示应用程序(如下所示)中,两者都可以很好地工作-但是如果最佳实践规定其中之一,则我宁愿适当使用它。

using System;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;

class DynamicExcel
{
    static void Main()
    {
        var app = new Excel.Application { Visible = true };
        app.Workbooks.Add();

        // Can use Excel._Worksheet instead here. Which is better?
        Excel.Worksheet workSheet = app.ActiveSheet;

        Excel.Range start = workSheet.Cells[1, 1];
        Excel.Range end = workSheet.Cells[1, 20];
        workSheet.get_Range(start, end).Value2 = Enumerable.Range(1, 20)
                                                           .ToArray();
    }
}

我试图避免完全深入研究COM或Office互操作性,只是强调C# 4的新功能 - 但我不想做任何真正愚蠢的事情。

(上面的代码中也可能有一些非常愚蠢的东西,请让我知道。使用单独的开始/结束单元格而不是仅使用“ A1:T1”是故意的 - 这样更容易看到它确实是20个单元格的范围。其他任何内容可能是偶然的。)

那么,我应该使用_Worksheet还是Worksheet,为什么?


6
除了这里提供的优秀答案外,我想补充一点,在使用Interop与Excel进行编程时,通常应该使用在Excel中正常出现的类名。这意味着要使用“Worksheet”而不是“_Worksheet”,使用“Application”而不是“ApplicationClass”。如果您对公开给COM的Excel对象模型不熟悉,那可能会有些棘手,但大多数情况下应该相当清晰。关于为什么不使用“ApplicationClass”的讨论可以在此处找到:http://blogs.msdn.com/ptorr/archive/2004/02/05/67872.aspx。 - Mike Rosenblum
幸运的是,我在使用Office方面做得非常少 - 实际上只是尝试展示新功能。不过还是非常感谢您提供的链接 - 非常有帮助! - Jon Skeet
很抱歉,但我必须问一下 - 你所强调的C# 4的新功能是什么? - Oskar
对于这个特定的案例,它是动态类型 - 各种方法调用/属性的返回类型实际上是“动态”的,因此缺少否则需要的转换。 - Jon Skeet
5个回答

77

如果我记得清楚——我的记忆有点模糊,毕竟我已经很久没有拆解Excel PIA了——它就像这样。

事件本质上是一个对象在发生某些事情时调用的方法。 在.NET中,事件是委托,简单明了。 但是在COM中,将一堆事件回调组织到接口中非常普遍。 因此,在给定对象上有两个接口——“传入”接口,您期望其他人调用您的方法,和“传出”接口,您期望在事件发生时调用其他人的方法。

在可创建对象的未管理元数据(类型库)中,有三个东西的定义:传入接口,传出接口和coclass,它表示“我是一个可创建的对象,实现了这个传入接口和这个传出接口”。

现在,当类型库自动翻译为元数据时,这些关系被保留下来了,不幸的是。更好的做法是手动生成PIA,使类和接口更符合我们在托管环境中所期望的,但不幸的是,这并没有发生。 因此,Office PIA充满了这些看似奇怪的重复,每个可创建对象似乎都与两个相关联的接口具有相同的内容。其中一个接口代表coclass的接口,另一个代表该coclass的传入接口。

_Workbook接口是工作簿coclass上的传入接口。 Workbook接口是表示coclass本身的接口,因此从_Workbook继承。

长话短说,如果方便的话,我会使用Workbook; _Workbook是一些实现细节。


我们在谈论的是工作表/ _Worksheet...你和JP犯了同样的阅读错误,但正如他所指出的那样,情况基本上是等价的。;) - Noldorin

25

如果您在Reflector中查看PIA程序集(Microsoft.Office.Interop.Excel),则Workbook接口具有以下定义...

public interface Workbook : _Workbook, WorkbookEvents_Event

Workbook_Workbook 的扩展,它添加了事件。对于 Worksheet 也是如此(抱歉,刚刚注意到您没有谈论 Workbooks )...

public interface Worksheet : _Worksheet, DocEvents_Event

DocEvents_Event ...

[ComVisible(false), TypeLibType((short) 0x10), ComEventInterface(typeof(DocEvents),
                     typeof(DocEvents_EventProvider))]
public interface DocEvents_Event
{
    // Events
    event DocEvents_ActivateEventHandler Activate;
    event DocEvents_BeforeDoubleClickEventHandler BeforeDoubleClick;
    event DocEvents_BeforeRightClickEventHandler BeforeRightClick;
    event DocEvents_CalculateEventHandler Calculate;
    event DocEvents_ChangeEventHandler Change;
    event DocEvents_DeactivateEventHandler Deactivate;
    event DocEvents_FollowHyperlinkEventHandler FollowHyperlink;
    event DocEvents_PivotTableUpdateEventHandler PivotTableUpdate;
    event DocEvents_SelectionChangeEventHandler SelectionChange;
}

我认为最好使用Worksheet,但这是有区别的。


8

仅供内部使用的类和接口

避免直接使用以下任何类和接口,它们是内部使用的,通常不会直接使用。

类/接口: 示例

classid 类: ApplicationClass (Word 或 Excel), WorksheetClass (Excel)

classid 事件 x _SinkHelper: ApplicationEvents4_SinkHelper (Word), WorkbookEvents_SinkHelper (Excel)

_classid: _Application (Word 或 Excel), _Worksheet (Excel)

classid 事件 x: ApplicationEvents4 (Word), AppEvents (Excel)

I classid 事件 x: IApplicationEvents4 (Word), IAppEvents (Excel)

http://msdn.microsoft.com/en-gb/library/ms247299(office.11).aspx

编辑:(关于此答案的格式)无法正确格式化紧接着斜体文本的转义下划线。在预览中显示正确,但发布后会出现问题。

编辑2:如果将下划线本身设置为斜体,则可以正常工作,尽管在概念上很糟糕,但看起来相同。


7

在过去的几年里,我看到并编写了相当多的C# / Excel COM互操作代码,几乎每种情况下都使用了Worksheet。我从未见过来自Microsoft的任何明确说明。


谢谢。顺便问一下,你有跟上 C# 4 的改进吗?听起来它们似乎会在 Office 互操作方面产生很大的影响,但没有经验我只是在猜测(也就是说,写书时在虚张声势...)。 - Jon Skeet
动态/COM互操作改进在使用COM时非常有用,但我相信我不会将动态特性用于更多的事情。我真正期待的是C# 4 / .NET 4中的代码合同和任务并行库。 - Joe Erickson

6

MSDN显示,Worksheet接口仅继承自_WorksheetDocEvents_Event接口。似乎仅为工作表对象提供可能引发的事件,除此之外没有提供任何其他成员。据我所见,Worksheet没有提供任何它自己的成员。因此,在所有情况下都使用Worksheet接口可能是最好的选择,因为您不会失去任何东西,并且可能需要公开的事件。


5
Jon Skeet在提问?我必须抓住这个难得的机会回应! :) - Noldorin
此外,我可能会选择使用工作表,因为那个下划线看起来非常丑...但说真的,没有理由不这样做。 - Noldorin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接