Résoudre en VBA "L'accès par programme au projet VB n'est pas fiable"

Bonjour,

Je cherche une manière de passer outre l'erreur " L'accès par programme au projet VB n'est pas fiable" sans avoir à changer les paramètres de Excel à la main.

Je développe une application qui génère des commandButton de manière automatique, je cherche donc à donner du code onClick automatiquement à ces boutons, cependant la seule solution que j'ai trouvé est de passer par :

With ThisWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
                .InsertLines .CountOfLines + 1, "Private Sub boutonA_Click:" _
                 & "export_fichier:End Sub"
 End With

Sauf que pour que ce genre de ligne fonctionne il faut avoir changé certains réglages de Excel, sauf que cette application est censée être utilisée par plusieurs personnes (une centaine) auxquelles je ne peux demander d'effectuer ces changements. Y'a t'il une manière de contourner la sécurité en VBA sans avoir à changer manuellement les réglages ?

KiraWashi

Bonjour,

Ce ne serait pas plus simple de dupliquer un onglet modèle qui contiendrait déjà tous vos contrôles et les procédures qui vont avec ?

Merci pour ta réponse Eric,

C'est peut-être la solution mais je n'ai pas réussi à lier un contrôle de clique à un bouton de manière automatique (le nombre de boutons est trop important).

J'ai déjà les fonctions que je veux lancer je n'arrive juste pas à les lier aux boutons.

Tu peux m'expliquer comment je peux faire pour que plusieurs boutons ai le même contrôleur(avec des paramètres qui changent) ?

KiraWashi

Bonjour,

Connais-tu un minimum le principe des modules de classe?

Voici un exemple, très simpliste de ce que l'on peut faire :

1- Nouveau fichier Excel

Bascule en mode Visual Basic (ALT+F11)

2- Insertion/Module de classe (nommé par défaut Classe1) , voici le code à insérer :

Option Explicit

Public WithEvents Cmd As MSForms.CommandButton

Private Sub Cmd_Click()
    MsgBox Cmd.Name
End Sub

3- Insertion/Userform (nommé UserForm1 par défaut) :

3a- Dans cet UserForm, dessiner 2 boutons de commande (CommandButton1 & CommandButton2), voici le code :

Option Explicit

Dim Cl(1) As Classe1

Private Sub UserForm_Activate()
    Set Cl(0) = New Classe1
    Set Cl(0).Cmd = Me.CommandButton1
    Set Cl(1) = New Classe1
    Set Cl(1).Cmd = Me.CommandButton2
End Sub

A partir de cet exemple simplissime, tout peut être construit dynamiquement et être exploité sur tous types de poste sans altérer les options utilisateurs...

PS (EDITH) : je parle ici de UserForm mais le principe est le même dans une feuille... Identique également pour le cas de boutons créés dynamiquement...

Bonjour,

Je ne savait pas si c'était adapté à ce que je voulais faire mais merci de me l'avoir confirmé.

Je commence juste VBA mais je me suis documenté sur les modules de classe aujourd'hui même.

Je continuerais à coder ma classe alors. Juste une question par rapport à la commande Cmd_Click(), est elle bien appelée peu importe le nom du bouton?

KiraWashi

Elle sera appelée, si le bouton a bien été "inscrit" comme une instance de cette classe.

Ce que je fais dans :

Private Sub UserForm_Activate()
    Set Cl(0) = New Classe1
    Set Cl(0).Cmd = Me.CommandButton1
    Set Cl(1) = New Classe1
    Set Cl(1).Cmd = Me.CommandButton2
End Sub

N'oublie pas que chaque instance de Classe est juste un "calque" qui ne contient que les "données" de cette instance. Il est donc essentiel d'utiliser une collection (ou variable tableau) qui stocke toutes les instances de cette classe. D'où mon :

Dim Cl(1) As Classe1

Bonjour,

D'accord merci pour l'astuce. Je vais essayer d'adapter mon code.

KiraWashi

Bonjour

J'ai un petit soucis de type lors de l'ajout d'instance de la classe1 dans la collection OLEobject de ma feuille.

Sub testTrois()
Dim CUn(1) As Classe1
    Set CUn(0) = New Classe1

    Set CUn(0).Cmd = ActiveWorkbook.Worksheets("Test").OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False, DisplayAsIcon:=False, Left:=i, Top:=i, Width:=i, Height:=i)

    With CUn(0).Cmd
            .name = "test" 'btnType + TexteSansEspaces(title) le nom du bouton lui même en tant qu'objet"
            .Object.caption = "test" 'title 'ce qui est afficher sur le bouton
            .Visible = True
    End With
     With CUn(0).Cmd.Object
         .BackColor = StringToRgb("255, 255, 255")
         .FontSize = "15"
         .FontName = "Arial"
         .ForeColor = StringToRgb("0, 0, 0")
    End With

End Sub

Voila comment je l'ajoute et voici le code de classe1 :

Option Explicit

Public WithEvents Cmd As MSForms.CommandButton

Private Sub Cmd_Click()
    MsgBox Cmd.name
End Sub

Je n'ai pas trouvé l'équivalent du :

ClassType:="Forms.CommandButton.1"

pour typer classe1.

Merci d'avance.

KiraWashi

Bonjour,

Désolé du retard, je n'ai pas vu ta demande...
En fait, il te faut séparer les procédures :

1- ajout du contrôle dynamiquement,

2- Ajout du contrôle à la classe :

Option Explicit

Dim oCl(3) As New Classe1

Sub ajout()
Dim mybutton As OLEObject
    Set mybutton = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", _
    Left:=100, Top:=100, Width:=120, Height:=24)
End Sub

Sub PutInClass()
Dim o As OLEObject, i As Integer
    For Each o In ActiveSheet.OLEObjects
        Set oCl(i).Butt = o.Object
        i = i + 1
    Next
End Sub
Option Explicit

Public WithEvents Butt As MSForms.CommandButton

Private Sub Butt_Click()
MsgBox Butt.Name
End Sub

Bonjour Pijaku

Merci pour ta réponse, je ne comprends pas j'ai l'impression d'avoir appliqué mon code cependant lorsque je clique sur le bouton créée avec :Sub testTrois()

    Dim mybutton As OLEObject
    Dim oCl(3) As New BtnClasse

    Set mybutton = ActiveWorkbook.Worksheets("Test").OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False, DisplayAsIcon:=False, Left:=100, Top:=100, Width:=100, Height:=100)

    With mybutton
            .name = "test" 'btnType + TexteSansEspaces(title) le nom du bouton lui même en tant qu'objet"
            .Object.caption = "test" 'title 'ce qui est afficher sur le bouton
            .Visible = True
    End With
     With mybutton.Object
         .BackColor = StringToRgb("255, 255, 255")
         .FontSize = "15"
         .FontName = "Arial"
         .ForeColor = StringToRgb("0, 0, 0")
    End With

     Set oCl(i).Butt = mybutton.Object
End Sub

Et la classe BtnClasse:

Option Explicit

Public WithEvents Butt As MSForms.CommandButton

Private Sub Butt_Click()
MsgBox Butt.name
End Sub

Il ne se passe rien quand je clique sur le bouton test de la feuille test, est ce que tu sais à quoi ça peut être lié ?

Merci pour ton aide,

KiraWashi

Je ne sais pas pourquoi, mais il te faut séparer tes deux procédures : la création du bouton d'une part et l'affectation à la classe d'autre part.

Cette ligne de code doit être dans une autre Sub :

Set oCl(i).Butt = mybutton.Object

Comme indiqué dans mon précédent message.

Bonjour,

Je suis bien d'accord que cette question peut-être résolue de bien d'autres manières... Je ne vois aucun intérêt à créer une avalanche de contrôles sur une feuille quand le problème peut être résolu simplement par des évènements Change ou SélectionChange... Mébon ce qui m'intéresse ici c'est uniquement la manière de traiter ces Objets avec une classe le cas échéant.

Si je lis et j'applique bien ce que tu dis, ça revient à dire qu'on ne peut pas créer et activer les boutons dans le même processus : Je reviens à la charge avec mon exemple antérieur, dans l'exemple joint les Events ne sont traités que parce que je laisse la main à une autre feuille et j'utilise l'évènement Activate de la Feuille1 pour charger la Classe.

Mais je n'ai pas réussi à créer par exemple un jeu de boutons sur différentes lignes ou colonnes puis à les activer dans une même enchainement de macros. Il faut nécessairement laisser la main au moins une fois à Excel pour "charger" la classe ensuite.

C'est bien ce qu'il faut comprendre ?

A+

11wsclbtn.xlsm (28.91 Ko)

Bonjour Galopin,

C'est exactement cela. L'enchainement des deux (création + affectation) semble impossible. Même en rendant la main au système entre 2 grâce à un DoEvents ne change rien.

D'où le fait que j'ai 2 Sub. Si tu les lances l'une après l'autre ça fonctionne, si tu les lances ensemble (à partir d'une 3ème Sub par exemple) cela ne fonctionne pas...

C'est très curieux...

Merci de ce retour.

"C'est très curieux..." Je dirai même frustrant !

A+

Une autre "solution" est d'utiliser OnTime :

Option Explicit

Dim oCl(3) As New Classe1

Sub ajout()
Dim mybutton As OLEObject
    Set mybutton = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", _
    Left:=100, Top:=100, Width:=120, Height:=24)
    Application.OnTime Now + TimeValue("00:00:01"), "PutInClass"
End Sub

Sub PutInClass()
Dim o As OLEObject, i As Integer
    For Each o In ActiveSheet.OLEObjects
        Set oCl(i).Butt = o.Object
        i = i + 1
    Next
End Sub

"Une autre "solution" est d'utiliser OnTime"

Testé et approuvé !

Bravo !

18wsclbtn-ontime.xlsm (29.51 Ko)
Rechercher des sujets similaires à "resoudre vba acces programme projet pas fiable"