Excel взаимодействие: _Worksheet или Worksheet? - PullRequest
72 голосов
/ 27 июня 2009

В настоящее время я пишу о динамической типизации, и я привожу пример взаимодействия с Excel. Я почти не делал взаимодействия с Office раньше, и это видно. В учебнике MSDN Office Interop для C # 4 используется интерфейс _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, и почему?

Ответы [ 5 ]

75 голосов
/ 27 июня 2009

Если я правильно помню - и моя память об этом немного размыта, прошло много времени с тех пор, как я разбирал Excel PIA - это так.

Событие - это, по сути, метод, который объект вызывает, когда что-то происходит. В .NET события являются делегатами, простыми и понятными. Но в COM очень часто можно организовать целую кучу обратных вызовов событий в интерфейсах. Таким образом, у вас есть два интерфейса для данного объекта - «входящий» интерфейс, методы, которые вы ожидаете, что другие люди будут вызывать вас, и «исходящий» интерфейс, методы, которые вы ожидаете вызывать для других людей, когда происходят события.

В неуправляемых метаданных - библиотеке типов - для создаваемого объекта есть определения для трех вещей: входящий интерфейс, исходящий интерфейс и кокласс, который говорит: «Я - создаваемый объект, который реализует этот входящий интерфейс и этот исходящий интерфейс ".

Теперь, когда библиотека типов автоматически переводится в метаданные, эти отношения, к сожалению, сохраняются. Было бы лучше иметь созданную вручную PIA, которая бы соответствовала классам и интерфейсам в большей степени, чем мы ожидали в управляемом мире, но, к сожалению, этого не произошло. Поэтому в Office PIA полно этих, казалось бы, странных дубликатов, где каждый создаваемый объект, похоже, имеет два интерфейса, связанных с ним, с одинаковыми элементами на них. Один из интерфейсов представляет интерфейс к коклассу, а один из них представляет входящий интерфейс к этому коклассу.

Интерфейс _Workbook является входящим интерфейсом в классе рабочих книг. Интерфейс Workbook - это интерфейс, который представляет сам Coclass и, следовательно, наследуется от _Workbook.

Короче говоря, я бы использовал Workbook, если вы можете сделать это удобно; _Workbook - это немного деталей реализации.

24 голосов
/ 27 июня 2009

Если вы посмотрите на сборку PIA (Microsoft.Office.Interop.Excel) в Reflector, интерфейс 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 голосов
/ 27 июня 2009

Классы и интерфейсы для внутренних Используйте только

Избегайте прямого использования любого из следующие классы и интерфейсы, которые используются внутри и являются обычно не используется напрямую.

Класс / Интерфейс: Примеры

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

edit: (переформатирование этого ответа) не может правильно отформатировать экранированный знак подчеркивания, за которым сразу следует курсив. Правильно отображается в окне предварительного просмотра, но не отображается при публикации

edit2: работает, если вы сделаете подчеркивание курсивом, который концептуально ужасен, но выглядит так же, как я полагаю

7 голосов
/ 27 июня 2009

За последние несколько лет я видел и написал довольно много кода C # / Excel COM Interop, и я видел, что Worksheet используется почти во всех случаях. Я никогда не видел ничего определенного от Microsoft по этому вопросу.

6 голосов
/ 27 июня 2009

MSDN показывает, что интерфейс Worksheet просто наследуется от интерфейсов _Worksheet и DocEvents_Event. Казалось бы, можно просто предоставить события, которые объект рабочего листа может вызвать в дополнение ко всему остальному. Насколько я вижу, Worksheet не предоставляет никаких других собственных членов. Так что да, вы могли бы также просто использовать интерфейс Worksheet во всех случаях, так как вы ничего не теряете из-за этого и потенциально можете нуждаться в событиях, которые он выставляет.

...