Opérateur = (affectation pas test ;))

Résolu
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 - 9 mars 2011 à 17:54
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 - 21 mars 2011 à 10:41
Bonjour,

Je veut redéfinir l'opérateur (opérateur d'affectation pas de test, soit l'équivalent à en C++ et non l'équivalent à == en C++)
Comment faire svp ?
Pck Vs2010 me sort plusieurs erreurs sur ce code :
    Public Operator =(ByRef Valeur As Microsoft.Office.Interop.Excel.Workbook) As Microsoft.Office.Interop.Excel.Workbook
        P_Workbook = Valeur
        Return P_Workbook
    End Operator


Les erreurs :
- Les opérateurs doivent être déclarés 'Shared'.
- L'opérateur '=' doit avoir deux paramètres.
- Les paramètres operator ne peuvent pas être déclarés 'ByRef'.
- Impossible de faire référence à un membre instance d'une classe à partir d'une méthode partagée ou d'un initialiseur de membre partagé sans une instance explicite de la classe.
- Impossible de faire référence à un membre instance d'une classe à partir d'une méthode partagée ou d'un initialiseur de membre partagé sans une instance explicite de la classe.

Or la fonction que j'ai écrite devrais faire exactement ce que je veut. Soit charger dans mon objet privé le Workbook et retourner ce même objet (pour pouvoir faire a b c)

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo

19 réponses

foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
15 mars 2011 à 13:46
Désolé, je pouri un peut le thread mais le sujet m'interresse bien. Et ca apportera pas mal d'idées à celui qui passera par la

La classe :
Public Class CustomWorkbook

    Private _baseWorkbook As Workbook

    Public Sub New(ByVal source As Workbook)
        _baseWorkbook = source
    End Sub

    Public Shared Narrowing Operator CType(ByVal source As WorkbookClass) As CustomWorkbook
        Return New CustomWorkbook(source)
    End Operator

    Public Shared Widening Operator CType(ByVal source As CustomWorkbook) As WorkbookClass
        Return CType(source._baseWorkbook, WorkbookClass)
    End Operator

End Class


Utilisation :
'Option strict On
Dim monClasseur As CustomWorkbook = CType(CType(app.Workbooks.Add(), WorkbookClass), CustomWorkbook)

'Option strict Off
Dim monClasseur As CustomWorkbook = CType(app.Workbooks.Add(), WorkbookClass)


On y est presque ;)
3
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
15 mars 2011 à 16:05
En faite le double cast est du au fait que :

1) Microsoft.Office.Interop.Excel.Workbook est une interface

2) Microsoft.Office.Interop.Excel.WorkbookClass est la classe qui implémente l'interface Microsoft.Office.Interop.Excel.Workbook

Public Class WorkbookClass
    Implements Workbook


C'est la structure classique pour l'interoperabilité des objets COM.

Je sais que si on se base sur l'explorateur d'objet il essaie de nous faire croire de Workbook est une classe =D mais un petit F1 révèle le secret lol.

Donc en réalité lorsqu'on fait :
Dim monClasseur as Workbook = app.Workbooks.Add()

La fonction add cré un objet de type WorkbookClass et le cast en interface Workbook.

Du coup, ce qui est embétant, on ne peut pas redéfinir l'opérateur CType en utilisant une interface :
Public Shared Narrowing Operator CType(ByVal source As Workbook) As CustomWorkbook
    Return New CustomWorkbook(source)
End Operator

Provoque l'erreur de compilation
Les opérateurs de conversion ne peuvent pas convertir à partir d'un type interface


D'ou mon Cast CType(app.Workbooks.Add(), WorkbookClass) pour passer la classe et non l'interface.

Mais il doit bien y avoir une astuce.
3
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
12 mars 2011 à 15:04
Bonjour,

La méthode "Operator =" permet de redéfinir l'égalité entre deux objets et non l'affectation. D'ou les différentes erreurs :
- Les opérateurs doivent être déclarés 'Shared'.

Est du au fait que la méthode est appelée sans instance d'objet.
- L'opérateur '=' doit avoir deux paramètres.

Est du au fait qu'on écrit toujours "A = B".
- Les paramètres operator ne peuvent pas être déclarés 'ByRef'.

Est du au fait que les paramètres n'ont pas à etre modifiés car l'opérateur ne fait que renvoyer un booléen.
- Impossible de faire référence à un membre instance d'une classe à partir d'une méthode partagée ou d'un initialiseur de membre partagé sans une instance explicite de la classe.

Est du au fait que dans une méthode Shared on ne peut pas faire référence à une variable d'instance étant donnée que la méthode est appelée sans instance de l'objet. Ex :
Class MaClass
  Private a as integer
  Public Shared Sub Toto()
    Me.a = 12 'L'erreur est provoquée par cette ligne car a est un membre d'instance
  End Sub
End Class


Donc pour rédéfinir l'opérateur = (qui malheureusement n'est pas ce que vous cherchez à faire) il faudra une écriture comme celle-ci :
Public Shared Operator =(ByVal A MonType, ByVal B as MonType) As Boolean
  Return (A.Quelquechose = B.QuelqueChose)
End Operator


Je ne vois pas très bien ce que vous voulez exactement faire.

Si le but est juste de définir P_Workbook qui est un membre privé de votre classe, pourquoi ne pas utiliser une Property :
Public Property MonWorkBook as Microsoft.Office.Interop.Excel.Workbook
  Get
    Return P_Workbook 
  End Get
  Set (value as Microsoft.Office.Interop.Excel.Workbook)
    P_Workbook = value
  End Set
End Property


Pour pouvoir faire :
a.MonWorkBook = b.MonWorkBook


Dans tous les cas, faire a b c en vb.net veux dire que a est un booléen et que b = c est la comparaison d'égalité de b et de c.

Sinon il faudra utiliser une méthode:
Public Function Copy(wb as Microsoft.Office.Interop.Excel.Workbook) as Microsoft.Office.Interop.Excel.Workbook
  Me.P_Workbook  = wb
  Return wb
End Sub


Pour pouvoir faire a.Copy(b.Copy(c.Copy(MonWorkbook)))
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
14 mars 2011 à 10:27
Arf

La méthode "Operator =" permet de redéfinir l'égalité entre deux objets et non l'affectation. D'ou les différentes erreurs

Oui sa j'avais compris

Je ne vois pas très bien ce que vous voulez exactement faire.

Un opérateur d'affectation

Donc si je comprend bien votre réponse : pas d'opérateur d'affectation en VB.NET
GROSSE régression comparer au C++ !

Mon objectif étais de recréer en partie la classe Workbook (pour ajouter des fonctionnalités) et continuer à être compatible aux Workbook Dot.Net "classique"
Soit pourvoir faire :
Dim ObjWbExcel as Microsoft.Office.Interop.Excel.Workbook
Dim MonObj as MaClass
[...]
MonObj = ObjWbExcel

Ou encore
Dim ObjApExcel as Microsoft.Office.Interop.Excel.Application
dim MonObj as MaClass
[...]
MonObj = ObjApExcel.Workbooks.Add(1)

Bon bà je pense que je vais devoir faire une fonction et/ou une property

Merci pour ces infos en tout cas

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
14 mars 2011 à 15:53
Ok, je comprends mieux.

Dans ce cas je dirai ceci :
Imports Microsoft.Office.Interop.Excel

Public Class CustomWorkbook

    Private _baseWorkbook As Workbook
    Private _customProperty As String

    Public Sub New(ByVal source As Workbook)
        _baseWorkbook = source
    End Sub

    Public ReadOnly Property BaseWorkbook As Workbook
        Get
            Return _baseWorkbook
        End Get
    End Property

    Public Property CustomProperty As String
        Get
            Return _customProperty
        End Get
        Set(ByVal value As String)
            _customProperty = value
        End Set
    End Property

End Class


Pour pouvoir faire cela :
Dim MonObj As New CustomWorkbook(ObjApExcel.Workbooks.Add(1))
MonObj.CustomProperty = "Toto"
Console.WriteLine("Nombre d'onglets {0} ; Custom {1}", MonObj.BaseWorkbook.Worksheets.Count, MonObj.CustomProperty)
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
14 mars 2011 à 18:40
Okkkk
Mais avec sa j'ai juste un constructeur en faire pas d'opérateur désaffectation (enfin si je suis pas trop nulle )
C'est déjà pas mal Merci

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
14 mars 2011 à 22:03
Maintenant, si vous avez besoin d'une compatibilité entre votre classe Custom et la classe Standard et ainsi pourvoir utiliser de facon transparente un Workbook ou/et un CustomWorkbook (du coup de pouvoir aussi faire des affectations), il reste une solution ultime mais un peut longue à implémenter.

Pour cela il faut implémenter l'interface Microsoft.Office.Interop.Excel.Workbook dans votre classe.
Public Class CustomWorkBook
    Implements Microsoft.Office.Interop.Excel.Workbook


De cette facon vous pourez faire ce genre de chose :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim app As New Application

        Dim wbStandard As Workbook = app.Workbooks.Add()
        Dim wbCustom As Workbook = New CustomWorkBook(app.Workbooks.Add())

        Dim wbCustomCast As CustomWorkBook = CType(wbCustom, CustomWorkBook)
        wbCustomCast.CustomProperty = "Toto"

        Dim wbCopie As Workbook = wbCustom

        Me.Test(wbStandard)
        Me.Test(wbCustom)
        Me.Test(wbCopie)

        app.Quit()

    End Sub

    Private Sub Test(ByVal wb As Workbook)
        If (TypeOf wb Is CustomWorkBook) Then
            Dim cust As CustomWorkBook = CType(wb, CustomWorkBook)
            Console.WriteLine("Nombre d'onglets {0} ; Custom = {1}", _
                   cust.Worksheets.Count, _ 
                   cust.CustomProperty)
        Else
            Console.WriteLine("Nombre d'onglets {0}", wb.Worksheets.Count)
        End If
End Sub


Bien entendu, il faut quand même différencier les deux type lors de la construction :
Dim wbStandard As Workbook = app.Workbooks.Add()
Dim wbCustom As Workbook = New CustomWorkBook(app.Workbooks.Add())


Le seul inconvénient c'est qu'il y a pas mal de méthodes à implémenter pour l'interface WorkBook.

Et une petite astuce, si vous vous lancez dans cette solution, toutes les méthodes sont bien présentes dans votre membre privé _baseWorkbook, mais certaines sont juste masquées dans l'intellisense. Exemple :
Public Sub _PrintOut(....) Implements Excel._Workbook._PrintOut
      _baseWorkBook._PrintOut(....)
End Sub


_PrintOut existe bien, mais la sub est masquée.

Voila, je pense qu'on a fait le tour de toutes les solutions possibles.

Par contre si par :
pas d'opérateur désaffectation


Vous voulez parler du destructeur, il vous suffit d'implémenter l'interface IDisposable et d'utiliser la méthose Dispose pour libérer les ressources du classeur.

Bonne prog ;)
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 mars 2011 à 10:46
Ok...
Mais si je comprend bien le code j'ai une compatibilité "descendante" (soit de Custom -> Standard) et non "montante" (soit Standard -> Custom)
Par exemple (toujours en C++ désolé de toujours prendre ce langage en référence mais je suis de formation C++ à l'origine )
Je peut faire un truc du genre de (enfin sauf erreur de ma part) :
Cl_Custom Cl_Custom::operator= (Cl_Custom &Source)
{
[...]
return *this;
}
Cl_Custom Cl_Custom::operator=(Cl_Standrad &Source)
{
[...]
return *this;
}

Puis ajouter la compatibilité descendante avec une fonction (style GET_StandardWorkbook) ou peut être même qu'en utilisant l'héritage sa fonctionnerais directement (j'avoue que je ne suis pas super au point vis à vis de l'héritage)

Et donc en final pourvoir faire :
Obj_Custom = Obj_Standrad; //C'est surtout ça que je voulais pouvoir faire
Obj_Standard = Obj_Custom;
//Ou Obj_Standard =  Obj_Custom.GET_StandardWorkbook();


Mais bon avec tout ce que tu m'a montré je devrais réussir à faire a peut près ce genre de chose.

Encore MERCI pour toute ces précisions

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 mars 2011 à 10:47
pas d'opérateur désaffectation

Étais une erreur de frape :
Il faut lire "pas d'opérateur d'affectation"

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
15 mars 2011 à 11:22
Étais une erreur de frape :
Il faut lire "pas d'opérateur d'affectation"


Je me disais bien, ca me paraissait hors context lol =D.

Mais si je comprend bien le code j'ai une compatibilité "descendante" (soit de Custom -> Standard) et non "montante" (soit Standard -> Custom)


Oui c'est exacte.

C'est vrai que sur l'opérateur d'affectation le C++ à l'avantage. Même si, de mon point de vue (et j'éspère d'autres programmeurs aussi :)), le fait de pouvoir affecter une variable de type B à une variable de type A fait froid dans le dos sur le plan de la rigueur d'écriture.

Déjà qu'en VB.NET on peut faire des choses assez horribles du genre :
Dim a as Integer = 10
Dim b as String = a

Si l'option Strict est sur Off.
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 mars 2011 à 11:38
Oui en effet niveau rigueur d'écriture ce que je voulais faire n'est pas top top (mais par moment c'est quand même bien pratique)
Mais dans notre cas je parlerais plutôt de type A et de type A' et dit comme ça, sa parait moins horribles

J'aurais du faire de la politique pas du développement moi

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 mars 2011 à 11:43
Juste une dernière précision : Je veut uniquement ajouter des procédures et/ou des fonctions je ne touche pas aux propriétés ni aux données contenu dans la classe (voila pourquoi je parle de classe de type A' et non de classe de type B)

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
15 mars 2011 à 12:04
Mon dernier post ma mis la puce à l'oreille.

Il est possible de redéfinir CType :
Public Class digit
    Private dig As Byte

    Public Sub New(ByVal b As Byte)
        Me.dig = b
    End Sub

    'CType de digit => Byte
    Public Shared Widening Operator CType(ByVal d As digit) As Byte
        Return d.dig
    End Operator

    'CType de Byte => digit
    Public Shared Narrowing Operator CType(ByVal b As Byte) As digit
        Return New digit(b)
    End Operator
End Class


pour pouvoir faire ceci :
'Option strict On
Dim a As Byte = 10
Dim b As digit = CType(a, digit)
Dim c As Byte = CType(b, Byte)

'Option strict Off
Dim a As Byte = 10
Dim b As digit = a
Dim c As Byte = b


Malheureusement dans votre cas Workbook est une interface. La class est WorkbookClass. J'ai fait un essai et vu que c'est un composant COM je n'ai pas réussi à trouver une parade pour le CAST.

A voir.
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 mars 2011 à 14:49
Haaaaaaaaa oui pas mal
On approche même de l'idéale (faire des castes n'est pas bien méchant)

Dzl ma hiérarchie m'a donner autre choses à faire en urgence donc je ne fait plus de test aujourd'hui (mais d'ici jeudi je me remet sur le sujet )

Par contre je ne comprend pas le double CType sur ces lignes :
'Option strict On
Dim monClasseur As CustomWorkbook = CType(CType(app.Workbooks.Add(), WorkbookClass), CustomWorkbook)


Vue que (sauf erreur de ma part) app.Workbooks.Add() retourne un workbook pourquoi doit on le "caster" (je pense que c'est le même mot en VB ) deux fois ?

A moins que WorkbookClass soit une classe que tu à créer Dans ce cas oui je comprend

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 mars 2011 à 16:19
Ha oui tien
Il me semblais que "_Workbook" étais l'interface et que Workbook étais la classe
Mais il me semble aussi que durant mes tests quand j'avais voulut hérité de cette classe (Workbook) VS me retournais une erreur de ce genre.
Donc si je veut hériter de Workbook il faut en réalité que j'hérite de WorkbookClass

Hé bà... Au moins une interface qui à la même nom qu'une classe, c'est clair et facile à réutiliser bravo CrimoSoft (ha moins que comme le UAC sa soit fait juste pour faire chier. Le chef de projet de l'UAC avais déclarer durant une conférence de presse que sa avais été développer pour faire chier l'utilisateur... Non mais franchement... Le but étais de le sensibilisé sur la sécurité informatique)

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
15 mars 2011 à 17:27
Il me semblais que "_Workbook" étais l'interface et que Workbook étais la classe


En réalité elle implémente les deux :
Public Class WorkbookClass
Implements _Workbook, Workbook, WorkbookEvents_Event


J'immagine qu'ils ont utilisé cette syntaxe pour ne pas perturber les habitudes des développeurs VBA.

S'ils avaient nommé l'interface 'IWorkbook' et la classe 'Workbook', il faudrait faire :
Dim monClasseur as IWorkbook = app.Workbooks.Add()


Et parfois ... rien qu'un petit 'I' ... ca peut déstabiliser ...

De plus, ca permet de maintenir une certaine compatibilité. Les développeurs peuvent presque faire un copier coller de leurs code VBA ou VB6.

Donc si je veut hériter de Workbook il faut en réalité que j'hérite de WorkbookClass

Oui, c'est bien ca. C'était ma première idée, mais elle est vite tombé à l'eau étant donné qu'il n'existe pas de constructeur permettant d'initialiser notre BaseType.
Il n'y a qu'un pauvre New sans paramètres, qui en plus génère une erreur à l'exécution.
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
21 mars 2011 à 09:56
Salut,

J'ai un peut regarder sa ce week end, et je fait le choix du "CType" (qui me parais être le plus propre, même si le double CType est un peut perturbant je trouve, mais bon la perfection sera pour une prochaine fois )

En tout cas MERCI de t'être autant intéressé à mon problème

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
21 mars 2011 à 10:06
S'ils avaient nommé l'interface 'IWorkbook' et la classe 'Workbook', il faudrait faire :
Code Visual Basic :

Dim monClasseur as IWorkbook = app.Workbooks.Add()

Heeeee bà non... Si Workbook est une classe et IWorkbook est un interface on aurais très bien pu faire :
Dim monClasseur as Workbook = app.Workbooks.Add()


Voir même :
Dim monClasseur as New Workbook(MonExcelApplication, NombreDeFeuille)

Ce qui aurais crée un workbook dans une Excel application donnée. Et sa n'aurais perturbé personne (enfin je pense ^^).
Mais ce n'est que ma façon de voir les choses

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
21 mars 2011 à 10:41
Heeeee bà non... Si Workbook est une classe et IWorkbook est un interface on aurais très bien pu faire :

Dim monClasseur as Workbook = app.Workbooks.Add()


Oui dans du code managé. Le problème est que Workbook est un objet COM. Il faut donc travailler avec son interface.

Donc si workbook était la classe, il faudrait quand même faire :
Dim monClasseur as Workbook = CType(app.Workbooks.Add(), Workbook)


Car la fonction Add renvoie une interface.

Voir même :

Dim monClasseur as New Workbook(MonExcelApplication, NombreDeFeuille)


Par contre la, c'est sur que s'ils avaient pensé à nous mettre un petit constructeur de ce genre, voir un :
Dim monClasseur as New Workbook(classeurACopier)


On aurait pas eu besoin de se casser la tête ;)

J'ai fait des essais en créant un CustomWorkbook visible par COM avec son interface pour pouvoir caster directement le résultat de app.Workbooks.Add(), mais je me chope des erreurs que je n'arrive pas à éradiquer. Il faudrait que je mette la main sur un spécialiste Interop.
0
Rejoignez-nous