web-dev-qa-db-fra.com

Interopérabilité Excel: _Worksheet ou Worksheet?

J'écris actuellement sur la frappe dynamique et je donne un exemple d'interopérabilité Excel. Je n'ai pratiquement jamais fait d'interopérabilité avec Office, et cela se voit. Le tutoriel MSDN Office Interop pour C # 4 utilise le _Worksheet interface, mais il y a aussi une interface Worksheet. Je n'ai aucune idée de la différence.

Dans mon application de démonstration absurdement simple (illustrée ci-dessous), cela fonctionne bien - mais si les meilleures pratiques dictent l'une ou l'autre, je préfère l'utiliser de manière appropriée.

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();
    }
}

J'essaie d'éviter de plonger profondément dans l'interopérabilité COM ou Office, en soulignant simplement les nouvelles fonctionnalités de C # 4 - mais je ne veux rien faire de vraiment, vraiment stupide.

(Il peut également y avoir quelque chose de vraiment, vraiment stupide dans le code ci-dessus, auquel cas veuillez me le faire savoir. L'utilisation de cellules de début/fin distinctes au lieu de simplement "A1: T1" est délibérée - il est plus facile de voir qu'il s'agit véritablement d'une plage de 20 cellules. Tout le reste est probablement accidentel.)

Alors, dois-je utiliser _Worksheet ou Worksheet, et pourquoi?

72
Jon Skeet

Si je me souviens bien - et ma mémoire à ce sujet est un peu floue, cela fait longtemps que je n'ai pas démonté l'Excel PIA - c'est comme ça.

Un événement est essentiellement une méthode qu'un objet appelle lorsqu'un événement se produit. Dans .NET, les événements sont des délégués, clairs et simples. Mais dans COM, il est très courant d'organiser tout un tas de rappels d'événements en interfaces. Vous avez donc deux interfaces sur un objet donné - l'interface "entrante", les méthodes auxquelles vous vous attendez à ce que d'autres personnes vous appellent, et l'interface "sortante", les méthodes que vous vous attendez à appeler d'autres personnes lorsque des événements se produisent.

Dans les métadonnées non gérées - la bibliothèque de types - pour un objet créable, il existe des définitions pour trois choses: l'interface entrante, l'interface sortante et la coclasse, qui dit "Je suis un objet créable qui implémente cette interface entrante et ceci interface sortante ".

Désormais, lorsque la bibliothèque de types est automatiquement traduite en métadonnées, ces relations sont malheureusement préservées. Il aurait été plus agréable d'avoir un PIA généré à la main qui rendrait les classes et les interfaces plus conformes à ce à quoi nous nous attendions dans le monde géré, mais malheureusement, cela ne s'est pas produit. Par conséquent, Office PIA est plein de ces duplications apparemment étranges, où chaque objet pouvant être créé semble avoir deux interfaces associées, avec les mêmes éléments. L'une des interfaces représente l'interface avec la coclasse, et l'une d'entre elles représente l'interface entrante avec cette coclasse.

L'interface _Workbook est l'interface entrante sur la coclasse du classeur. L'interface du classeur est l'interface qui représente la coclasse elle-même et hérite donc de _Workbook.

Pour faire court, j'utiliserais Workbook si vous pouvez le faire facilement; _Workbook est un peu un détail d'implémentation.

75
Eric Lippert

Si vous regardez l'assembly PIA (Microsoft.Office.Interop.Excel) dans Reflector , l'interface Workbook a cette définition ...

public interface Workbook : _Workbook, WorkbookEvents_Event

Workbook est _Workbook mais ajoute des événements. Idem pour Worksheet (désolé, je viens de remarquer que vous ne parliez pas de 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;
}

Je dirais qu'il vaut mieux utiliser Worksheet, mais c'est la différence.

24
JP Alioto

Classes et interfaces à usage interne uniquement

Évitez d'utiliser directement l'une des classes et interfaces suivantes, qui sont utilisées en interne et ne sont généralement pas utilisées directement.

Classe/Interface: Exemples

classid Classe: ApplicationClass (Word ou Excel), WorksheetClass (Excel)

classid Événements x _SinkHelper: ApplicationEvents4_SinkHelper (Word), WorkbookEvents_SinkHelper (Excel)

_ classid: _ Application (Word ou Excel), _Worksheet (Excel)

classid Événements x: ApplicationEvents4 (Word), AppEvents (Excel)

I classid Événements x: IApplicationEvents4 (Word), IAppEvents (Excel)

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

edit: (re: formatage de cette réponse) ne peut pas formater correctement un trait de soulignement échappé suivi immédiatement par du texte en italique. Affiche correctement dans l'aperçu mais cassé lors de la publication

edit2: fonctionne si vous mettez le trait de soulignement lui-même en italique, ce qui est horrible sur le plan conceptuel mais a la même apparence, je suppose

8
barrowc

J'ai vu et écrit pas mal de code C #/Excel COM Interop au cours des dernières années et j'ai vu Worksheet utilisé dans presque tous les cas. Je n'ai jamais rien vu de définitif de Microsoft sur le sujet.

7
Joe Erickson

MSDN montre que l'interface Worksheet hérite simplement de _Worksheet et DocEvents_Event interfaces. Il semblerait que l'on fournit simplement les événements qu'un objet de feuille de calcul peut déclencher en plus de tout le reste. Pour autant que je sache, Worksheet ne fournit aucun autre membre. Donc oui, vous pouvez tout aussi bien utiliser l'interface Worksheet dans tous les cas, puisque vous ne perdez rien par elle, et pourriez éventuellement avoir besoin des événements qu'elle expose.

6
Noldorin