IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Référence DLL dans VBA


Sujet :

VB.NET

  1. #1
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Décembre 2018
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Décembre 2018
    Messages : 3
    Par défaut Référence DLL dans VBA
    Bonjour à tous,
    Avant toute chose je tiens à vous dire que je suis nouvel inscrit sur ce forum mais que j'ai déjà trouvé ici énormément de réponses à des problèmes que j'ai pu rencontrer lors de développements de diverses macros VBA, et que c'est bien la première fois que je ne trouve pas de sujet similaire à ce que je rencontre (ou la première fois que je cherche mal). J'espère donc que vous allez pouvoir m'aider
    Autre petite précision, je ne suis absolument pas développeur de formation. Je suis normalement plutôt rigoureux dans mes codes mais désolé par avance si je n'utilise pas les bons termes techniques.

    Tout d'abord un peu de contexte:
    J'ai développé une macro (complexe pour mon niveau) qui est assez longue en temps de calcul mais que j'ai déjà réussi à optimiser par rapport à mes débuts à l'aide de connaissance développeurs. Pour avoir un ordre d'idée pour traiter environ 35.000 lignes je suis passé de 1h30 à moins de 2 minutes. Maintenant j'aurais besoin d'aller encore plus loin dans l'optimisation (pour traiter au moins 5 fois plus de lignes), et une idée que j'ai eu a été de "convertir" la plupart de ma macro en fichier DLL pour accélérer le temps de traitement.
    J'utilise Windows 10, Microsoft Excel 2016 (64bits) et Microsoft Visual Studio 2015 (32 bits je pense).

    J'ai trouvé ici un tuto me détaillant toutes les étapes au préalable nécessaires pour rendre un fichier .dll reconnaissable par VBA:
    http://www.joseouin.fr/logiciels/cre...xcel-en-vb-net

    Avant de l'appliquer à mon code plus complexe que ses exemples, j'ai justement tenté de refaire ses exemples dans une feuille de calcul vide:
    Côté Visual Studio le code suivant (mon Assembly name est "ClassLibrary1", surnommée "ExempledeLibrairiedeClasse"):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Public Class Class1
        Public Function MaNorme(ByVal x As Double, ByVal y As Double) As Double
            Dim z As Double
            z = (x ^ 2 + y ^ 2) ^ 0.5
            Return z
        End Function
    End Class
    Côté VBA le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Public Sub test_liaison_dll()
     
    Dim MaClasse As New ClassLibrary1.Class1
    Dim x As Double
    Dim y As Double
    Dim z As Double
     
    z = MaClasse.MaNorme(x, y)
     
    Debug.Print z
     
    End Sub
    A l'exécution, j'obtiens cette erreur:
    "Erreur d'exécution 4029 - Un composant ActiveX ne peut pas créer d'objet" et VBA me surligne la ligne "z = MaClasse.MaNorme(x, y)"

    Pour information j'ai bien suivi le tuto dont le lien est ci-dessus, donc toutes les coches "Make assembly COM-Visible" et "Register for COM interop" sont cochées dans Visual Studio.
    Côté VBA, "ExempledeLibrairiedeClasse" apparaît bien dans les références disponibles, et la case est cochée.

    Je ne trouve pas d'information sur pourquoi est-ce que VBA ne reconnaît pas ma fonction "MaNorme". Pour information lorsque je déclare la variable "MaClasse" la saisie semi-automatique me propose bien tout ce qu'il y a ensuite.

    J'ai essayé de fouiller un peu plus et je suis allé dans l'explorateur d'objets de VBA:
    Nom : Capture.PNG
Affichages : 719
Taille : 5,8 Ko
    De ce que j'en comprends VBA reconnaît bien ma classe "Class1" mais n'arrive pas à aller plus loin et voir la fonction qui est à l'intérieur.

    Je sais que la compatibilité Excel 64bits/Visual Studio 32bits va me poser problème à un moment, mais il ne me semble pas que cela me donnerait ce genre de message. Dans le doute j'ai essayé de déclarer la fonction dans VBA grâce à cette commande (en ayant copié la dll dans system32
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Declare PtrSafe Function norme Lib "ClassLibrary1.dll" Alias "Class1.MaNorme" (x As Double, y As Double) As Double
    Lorsque j'essaie de lancer le Sub (en appelant bien la fonction "norme"), j'obtiens le message d'erreur suivant:
    "Point d'entrée Class1.MaNorme" d'une DLL introuvable dans ClassLibrary1.dll".

    Tout cela me fait penser que j'ai mal fait quelque chose côté Visual Studio, mais je ne trouve pas...
    Est-ce que vous auriez des idées pour m'aider à résoudre ce problème svp ? Cela me paraît simple mais en même temps je ne trouve aucune info supplémentaire sur internet...

    Merci d'avance à tous ceux qui pourront me lire et me répondre, et bonne journée.

  2. #2
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Bonsoir, bienvenu sur dvp.com.

    J'ai l'impression que ça ressemble fort à une partie de cette discussion : https://www.developpez.net/forums/d1...ers-excel-vba/

  3. #3
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour

    Ta as loupe un attribut de visibilité COM qui doit "décorer"(précéder immédiatement la déclaration ) toute Prop ou Sub exposée à COM dans ton Class1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Public Class Class1
        <ComVisible(True)>
        Public Function MaNorme(ByVal x As Double, ByVal y As Double) As Double
            Dim z As Double
            z = (x ^ 2 + y ^ 2) ^ 0.5
            Return z
        End Function
    End Class
    Bon code ...

  4. #4
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Décembre 2018
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Décembre 2018
    Messages : 3
    Par défaut
    Bonjour MABROUKI, et merci pour ta réponse.

    Je ne sais pas si c'est à cause de ma version de Visual Studio, mais celui-ci ne reconnaît pas ce code à l'intérieur d'une classe:
    Par contre en cherchant un peu plus dans l'aide VS, j'ai pu rajouter ce code au début de ma classe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
    Public Class ComClass1
     
    #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 = "fdddf30d-cd36-475c-86bf-a06b23f440f4"
        Public Const InterfaceId As String = "3b8f9e2f-4863-4ebb-abdb-06e9d1fdc08c"
        Public Const EventsId As String = "548af240-bfee-41f3-8b02-3d503b11f16d"
    #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
    ...
    Maintenant Visual Basic reconnaît bien chacune de mes fonctions et "m'aide" à les écrire via la saisie semi-automatique.
    Je tente alors de lancer cette macro:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Sub test()
    Dim a As Double
    Dim b As Double
    Dim c As Double
     
    Dim MaClasse As New Vide_colis.ComClass1
     
    a = 1
    b = 2
     
    c = MaClasse.MaNorme(a, b)
     
    Debug.Print d
     
    End Sub
    Seulement j'ai toujours le message d'erreur "Erreur d'exécution '429': Un composant ActiveX ne peut pas créer d'objet".

  5. #5
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Chez moi, le code de la classe commencé par (à noter qu'il s'agit d'un code livré sur ce forum par Mabrouki en 2011) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Imports System.Runtime.InteropServices
    <ClassInterface(ClassInterfaceType.AutoDual), ComVisible(True)>
    suffit. Il ne faut pas oublier, dans les propriétés du projet de la DLL, de cocher "Inscire pour Com Interop".

    Nom : Com.jpg
Affichages : 1025
Taille : 20,7 Ko

    J'espère que ça aidera ...

  6. #6
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Décembre 2018
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Décembre 2018
    Messages : 3
    Par défaut
    Citation Envoyé par Phil Rob Voir le message
    Chez moi, le code de la classe commencé par (à noter qu'il s'agit d'un code livré sur ce forum par Mabrouki en 2011) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Imports System.Runtime.InteropServices
    <ClassInterface(ClassInterfaceType.AutoDual), ComVisible(True)>
    suffit. Il ne faut pas oublier, dans les propriétés du projet de la DLL, de cocher "Inscire pour Com Interop".

    Nom : Com.jpg
Affichages : 1025
Taille : 20,7 Ko

    J'espère que ça aidera ...
    Je suis sur Visual studio 2015, et si j'essaie d'écrire tes 2 lignes de code: la première est marquée comme inutile par VS, tandis que pour la seconde aucun mot-clé n'est reconnu.
    C'est pour cela que j'ai écrit ce que j'ai mis dans mon message plus haut:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
    Ensuite oui la case "Inscrire pour COM Interop" est bien cochée.

    Merci quand même.

  7. #7
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Je suis sur Visual studio 2015, et si j'essaie d'écrire tes 2 lignes de code: la première est marquée comme inutile par VS, tandis que pour la seconde aucun mot-clé n'est reconnu.

    <ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
    Oui, mais cette formule ne te satisfait pas.
    Le problème par rapport à mes 2 lignes, c'est Vs Express (je suppose que tu as VB2015 Express) : chez moi, je peux utiliser ces lignes en 2010, 2015 et 2017 (version Pro) mais pas en 2010 Express. Pour que la 2ème ligne soit reconnue, il faut que la 1ère soit reconnue (et sans message déplaisant).

    Mais attention, en poussant un peu plus loin les tests, et en utilisant la syntaxe de ton exemple (ton message du 10/12 à 11h18), j'obtiens le même message que toi : erreur 429.

    Par contre, si je n’essaie pas d’instancier un objet dans la Sub VBA, je peux passer des objets créés sous VB à une macro dans VBA, appelée par VB :

    Sous VB :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AppliXLS.Run(AutreMacro(UnObjetDeTypeMaClasseUnNombre))
    et sous VBA, la macro :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Public Sub AutreMacro(ByRef Msg As MaClasseUnNombre.UnNombre)
     
     MsgBox (Msg.DonneNombre())
     
    End Sub
    Désolé, je n'ai rien de mieux ...

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo