Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Utilisation d'une structure VB 2005 dans un module VBA/ Excel

6 réponses
Avatar
arundel
Bonjour,

J'ai installé un code de calcul matriciel dévelopé en vb.net qui définit une
structure "Matrice" comme suit :

Imports System.Runtime.InteropServices
<ComVisible(True)> <ComClass()> _
Public Class DLL_Matrix

Public Structure Matrice
Private A(,) As Long
Private mDim1 As Long, mDim2 As Long

#Region "Constructeurs et propriétés"

Public Sub New (ByVal dim1 As Long, ByVal dim2 As Long)
Dim longA(dim1, dim2) As Long
A = longA
mDim1 = dim1
mDim2 = dim2
End Sub
etc ...

J'ai généré sans pb la dll ActiveX sous le nom DLL_Matrix.dll (ainsi que le
fichier .tlb) et catalogué dans le GAC.

--------

Côté Excel, j'ai un petit module de test VBA qui se plante en compile pour
une raison qui m'échappe

Public Sub main()

Dim A As New matrice '=> message : "Type défini par l'utilisateur non défini"

ou bien

Dim A As New matrice (3,3) '=> message : "Erreur de syntaxe"

Pourtant DLL_Matrix est bien cochée dans les références disponibles du VBA
et le menu contextuel qui s'ouvre après le déclaration New le mentionne.

Que manque-t-il à votre avis ? Merci de votre aide.

6 réponses

Avatar
Fred
Dans : news:,
arundel disait :
Bonjour,



Bonjour,

J'ai installé un code de calcul matriciel dévelopé en vb.net qui
définit une structure "Matrice" comme suit :



Public Sub New (ByVal dim1 As Long, ByVal dim2 As Long)



Que manque-t-il à votre avis ? Merci de votre aide.



Il me semble que tu ne peux utiliser des constructeurs paramétrés en
vba.
Essaie avec un New sans paramètres ou alors avec une fonction Shared de
création d'instance.

--
Fred
http://www.cerber mail.com/?3kA6ftaCvT (enlever l'espace)
Avatar
Fred
Dans : news:,
Fred disait :

Essaie avec un New sans paramètres ou alors avec une fonction Shared
de création d'instance.



Ma mémoire me joue des tours. Le Shared est à oublier.
J'ai repris un de mes codes :

Imports Microsoft.Win32
<ComClass(Client.ClassId, Client.InterfaceId, Client.EventsId)> _
Public Class Client
#Region "COM GUIDs"
' These GUIDs provide the COM identity for this class
' and its COM interfaces. If you change them, existing
' clients will no longer be able to access the class.
Public Const ClassId As String = "0168e5f2-aa9e-436c-9af8-adcc5fe85126"
Public Const InterfaceId As String =
"92ce1319-e73a-4a6f-9df6-61c28dda3ed6"
Public Const EventsId As String = "05211c6c-e2b1-4811-9b5c-aa363fc7b7f4"
#End Region

' A creatable COM class must have a Public Sub New()
' with no parameters, otherwise, the class will not be
' registered in the COM registry and cannot be created
' via CreateObject.
Public Sub New()
MyBase.New()

'----
'----

End Sub

Lors de l'utilisation de ce procédé, j'avais créé une classe Client
(voir ci dessus).
De cette classe, qui est juste destinée à exposer toutes les
fonctionnalités dont j'avais besoin, je faisais ensuite appel à des
fonctions, essentiellement partagées (Shared) d'autres classes, non
visibles dans COM.

Dans ton cas, ce qu'il faut retenir, c'est effectivement l'obligation du
New sans paramètres et, à l'appel à MyBase.New
Mais tu peux sans doute appliquer ce que j'ai fait (pour des types
simples uniquement).
À savoir exposer une autre classe dans COM (sans constructeur public) et
implémenter dans ta classe de base (Client chez moi) une fonction du
style :

Public Function CréerMatrice(ByVal dim1 As Long, ByVal dim2 As Long) As
Matrice
Return New Matrice(ByVal dim1 As Long, ByVal dim2 As Long)
ENd Function


--
Fred
http://www.cerber mail.com/?3kA6ftaCvT (enlever l'espace)
Avatar
Fred
Dans : news:,
arundel disait :

Bonjour,



Re,

Finalement j'ai pris le temps de refaire un petit essai minimaliste car,
comme mentionné, je n'avais pas testé le retour d'objets par des
fonctions. Il n'y a effectivement pas grand chose à ajouter.
Au passage, le type Long n'est pas compatible avec COM. J'ai donc mis
des Int32.

<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
_
Public Class ComClass1
Public Const ClassId As String =
"0cd97217-6f9e-421b-ac54-f37e3e260c6d"
Public Const InterfaceId As String =
"4491f395-2a26-453d-bbb1-51b227047b17"
Public Const EventsId As String =
"b3ebb44b-927d-4549-972d-ca41693e067c"

Public Sub New()
MyBase.New()
End Sub

Public Function CreerMatrice(ByVal dim1 As Int32, ByVal dim2 As
Int32) As Matrice
Return New Matrice(dim1, dim2)
End Function
End Class

<ComClass(Matrice.ClassId, Matrice.InterfaceId, Matrice.EventsId)> _
Public Class Matrice
Public Const ClassId As String =
"9d052d9e-3a79-4eb6-bfbd-5e8d84ec915c"
Public Const InterfaceId As String =
"c4ccb2b8-27ba-45cd-a2a4-5ab12f880c41"
Public Const EventsId As String =
"114a8e69-1441-48ad-8882-a448b7153214"

Private A(,) As Int32

Friend Sub New(ByVal dim1 As Int32, ByVal dim2 As Int32)
MyBase.New()
Dim tmpA(dim1, dim2) As Int32
A = tmpA
End Sub

Default Public Property Item(ByVal i As Int32, ByVal j As Int32) As
Int32
Get
Return Me.A(i, j)
End Get
Set(ByVal value As Int32)
Me.A(i, j) = value
End Set
End Property
End Class

--
Fred
http://www.cerber mail.com/?3kA6ftaCvT (enlever l'espace)
Avatar
arundel
Merci Fred, ton post est très riche et m'a permis de progresser mais pas
encore suffisamment pour aboutir.

Effectivement la littérature web indique qu'un constructeur public de classe
COM ne doit pas avoir de paramètres. En revanche un constructeur interne à
une structure doit en avoir.

J'ai donc réécrit le code suivant pour la classe COM (épuré des détails) :

Imports System.Runtime.InteropServices
<ComVisible(True)> <ComClass(ComClass2.ClassId, ComClass2.InterfaceId,
ComClass2.EventsId)> _
Public Class ComClass2

#Region "COM GUIDs"
#End Region

Public Structure Matrice

Private A(,) As Long
Private mDim1 As Long, mDim2 As Long

#Region "Constructeurs et propriétés"

Public Sub New (ByVal dim1 As Long, ByVal dim2 As Long)
Dim longA(dim1, dim2) As Long
A = longA
mDim1 = dim1
mDim2 = dim2
End Sub

---

#End Region

End Structure


Public Sub New()
MyBase.New()
End Sub

Public Function CréerMatrice(ByVal dim1 As Long, ByVal dim2 As Long)
Return New Matrice(dim1, dim2)
End Function

End Class

Côté VBA :

Sub Test()

Dim myObject As DLL_Matrix.ComClass2
Set myObject = New DLL_Matrix.ComClass2

Dim aMat As Variant

aMat = myObject.CréerMatrice(2, 2)

End Sub

L'explorateur d'objets voit bien la classe et la fonction CréerMatrice.

Le pb c'est que le compilateur envoie le message suivant :
"Fonction ou interface mentionné avec restrictions, ou la fonction utilise
un type Automation non géré par Visual Basic"

Dans VBA/Excel les 4 références cochées sont les suivantes (dans l'ordre) :
Visual Basic for Applications
Microsoft Excel 11.0 Object Library
OLE Automation
DLL_Matrix

Ton avis stp ?

Merci d'avance.
Avatar
arundel
Bonsoir Fred,

J'ai mis en oeuvre ton code et l'ai testé à partir de VBA comme suit :

Sub Test()

Dim myObject As DLL_Matrix.ComClass1
Set myObject = New DLL_Matrix.ComClass1

Dim aMat As Variant
Dim t As Long
t = CLng(2)

aMat = myObject.CreerMatrice(t, t)

End Sub
Résultat : "Le cast spécifié n'est pas valide" signalé sur la ligne aMat = ...

Par acquis de conscience j'ai fait un test en passant tout en Integer : même
résultat.

Qu'en penses-tu ?

Par la même occasion j'aurais une question de débutant que je suis en .net :
comment récupères-tu les 3 GUID qui sont dans les classes ? Je n'ai rien
trouvé dans VB Express.

A+
Avatar
Fred
Dans : news:,
arundel écrivait :
Bonsoir Fred,



Bonsoir,

J'ai mis en oeuvre ton code et l'ai testé à partir de VBA comme suit :

Sub Test()

Dim myObject As DLL_Matrix.ComClass1
Set myObject = New DLL_Matrix.ComClass1

Dim aMat As Variant
Dim t As Long
t = CLng(2)

aMat = myObject.CreerMatrice(t, t)



Plutôt :
Dim aMat As Matrice
Set aMat = myObject.CreerMatrice(t, t)


Par la même occasion j'aurais une question de débutant que je suis en
.net : comment récupères-tu les 3 GUID qui sont dans les classes ? Je
n'ai rien trouvé dans VB Express.



Ah ! J'utilise Visual Studio et j'ajoute un élément de type Com Class.
C'est ce qui me génère les GUIDs et les commentaires en anglais que tu
as pu voir sur mon premier post.
Je pense qu'il s'agit de 3 GUID auto-générés. Donc tu peux les créer toi
même.
As-tu «Création de Guid» dans le menu «Outils» ?

Sinon rien de plus simple à faire en vb :

Dim g as Guid = Guid.NewGuid
Debug.Print g.ToString



--
Fred
http://www.cerber mail.com/?3kA6ftaCvT (enlever l'espace)