OVH Cloud OVH Cloud

Affectation de procédure VB à plusieurs boutons

12 réponses
Avatar
Merlan
Bonjour,

En l'état actuel de mes connaissances, il n'existe qu'une relation 1-1 entre bouton de barre d'outil et "macro", créée par la fonction 'affectation de macro'.

Je souhaite utiliser des procédures VBE comme sous-programmes communs à plusieurs autres. Ces sous programmes ne seraient affectés à aucun bouton, mais appelables par plusieurs Sub.
Je suppose qu'il faudrait aussi déclarer les variables communes en Public et non par Dim.

Pour être plus clair, je souhaite faire comme dans Access où l'on peut écrire du code "générique" dans Modules et du code spécifique attaché à plusieurs contrôles de formulaire par exemple.

Merci d'avance

10 réponses

1 2
Avatar
MichD
Bonjour,

J'ai compris ce que tu veux, je vais te donner un petit exemple.

Ici c'est une procédure qui appelle une autre procédure. Les variables
sont passées en paramètre à la deuxième procédure. Tu peux appeler
la procédure "Bonjour" aussi souvent que tu veux par la ligne :
Call Bonjour("Le nom que tu désires")

Selon le travail à effectuer, au lieu de créer une procédure "Bonjour"
tu pourras créer une fonction.

Comme tu ne précises pas le travail que tu veux faire, il m'est difficile
de t'en dire plus.

IMPORTANT : Trouve un nom pour la procédure ou fonction qui
soit UNIQUE dans ton programme sinon Excel devient tout confus!

'-----------------------------------------
Sub Main()
Dim Nom As String
Nom = "MichD"
Call Bonjour("MichD")
End Sub

'-----------------------------------------
Sub Bonjour(Nom As String)

MsgBox "Dis bonjour à : " & Nom

End Sub
'-----------------------------------------

'-----------------------------------------
Function Bonjour(Nom As String)

MsgBox "Dis bonjour à : " & Nom

End Function
'-----------------------------------------

MichD
---------------------------------------------------------------
Avatar
merlan
Le mardi 27 Août 2013 à 21:08 par Merlan :
Bonjour,

En l'état actuel de mes connaissances, il n'existe qu'une relation 1-1
entre bouton de barre d'outil et "macro", créée par la
fonction 'affectation de macro'.

Je souhaite utiliser des procédures VBE comme sous-programmes communs
à plusieurs autres. Ces sous programmes ne seraient affectés
à aucun bouton, mais appelables par plusieurs Sub.
Je suppose qu'il faudrait aussi déclarer les variables communes en
Public et non par Dim.

Pour être plus clair, je souhaite faire comme dans Access où l'on
peut écrire du code "générique" dans Modules et
du code spécifique attaché à plusieurs contrôles de
formulaire par exemple.

Merci d'avance


Bonjour,

J'ai mal formulé ma demande.
Prenons des exemples.

Sub PROG1 (affecté à un bouton)
Classeur = 'NomDeClasseur'
CTLINIT (Nom de sous prog) qui effectue une série de contrôles, envoie les messages appropriés et positionne OK à Vrai ou Faux
If Not OK then Exit Sub
instructions spécifiques à PROG1
.
.

Sub PROG2 (affecté à un autre bouton)
Classeur = 'NomDeClasseur'
CTLINIT (Nom de sous prog)
If Not OK then Exit Sub
instructions spécifiques à PROG2
.
.
A ce jour, je dois écrire 2 fois CTLINIT, après PROG1 et après PROG2.

En fait, tout se passe à la création. Quand on demande une nouvelle macro, il propose
. Classeur de macros personnelles. Il l'appelle PERSO.XLS!Macro1 et je ne parviens pas à les récupérer.
. Nouveau classeur. Bien, pas intéressant.
. Ce classeur. C'est celui que je prends.

J'en déduis que créer une procédure passe obligatoirement par un classeur donné. Je ne sais pas créer CTLINIT ailleurs, dans un endroit 'générique' , non relié à un classeur spécifique.
Elle n'a pas besoin d'être reliée à un bouton pour être exécutée.
Elle doit être appelable à partir de plusieurs PROGn.
D'où ma comparaison avec Modules dans Access

Ai-je été plus clair ?
Avatar
MichD
Il y a plusieurs façons de passer une (des) variable à une procédure
appelée.

Dans le haut du module on définit les variables comme ceci :
A -
'-------------------------------
Dim MyVar As (le type approprié) si l'étendue de la variable se limite aux
procédures du module

Public MyVar As (le type approprié) si l'étendue de la variable est
utilisée dans plusieurs modules
'-------------------------------

B - On peut définir les variables au niveau de la procédure principale et
on passe ces variables comme paramètre à la procédure appelée, comme
dans l'exemple que je t'ai donné. Tu peux avoir plusieurs variables que
tu
passes comme paramètre. Chaque paramètre correspond à une variable.

Exemple :


Dans la procédure principale,

'-----------------------------------------
Sub Main()
Dim PréNom As String, Nom As String
PréNom = "MichD"
Nom = "Pépito"
Call Bonjour(PréNom, Nom)
End Sub

'-----------------------------------------
Sub Bonjour(PréNom As String, Nom As String)
MsgBox "Dis bonjour à : " & PréNom & " " & Nom
End Sub
'-----------------------------------------

à chaque fois que tu appelles cette procédure,
Call Bonjour(PréNom, Nom)
Les variables Prénom et Nom peuvent avoir des valeurs différentes
qui vont être traitées par la procédure "bonjour"


MichD
---------------------------------------------------------------
Avatar
merlan
Le mardi 27 Août 2013 à 21:08 par Merlan :
Bonjour,

En l'état actuel de mes connaissances, il n'existe qu'une relation 1-1
entre bouton de barre d'outil et "macro", créée par la
fonction 'affectation de macro'.

Je souhaite utiliser des procédures VBE comme sous-programmes communs
à plusieurs autres. Ces sous programmes ne seraient affectés
à aucun bouton, mais appelables par plusieurs Sub.
Je suppose qu'il faudrait aussi déclarer les variables communes en
Public et non par Dim.

Pour être plus clair, je souhaite faire comme dans Access où l'on
peut écrire du code "générique" dans Modules et
du code spécifique attaché à plusieurs contrôles de
formulaire par exemple.

Merci d'avance


Bonjour MichD

Merci pour tout cela : j’en sais désormais plus sur le passage de paramètres.
Je reviens à ma demande initiale que j’ai mal formulée.

2 prog principaux :
PROG 1, créé dans le Classeur C1
PROG 2, créé dans le Classeur C2

Ces 2 programmes contiennent des parties identiques dans les macros de C1 et celles de C2. Appelons ces lignes de code communes CTLINIT.
A ce jour, elles résident chacune sous chaque classeur. Elles sont donc dupliquées.
Je pourrais les laisser ainsi, sans sous-programme. Telle est la situation actuelle.

Mais je n’en fais pas une simple question d’esthétique.

Stocker CTLINIT dans un endroit indépendant des classeurs C1 et C2 mais accessible depuis ces derniers
• Est beaucoup plus facile pour la maintenance.
• Simplifie la présentation et la compréhension de l’ensemble : il y a évidemment plus de 2 programmes concernés. Environ une dizaine de classeurs différents sont concernés à ce jour, et ça va évoluer.
• Accroît la standardisation.

EN VB, les procédures commenceraient donc par :

Sub PROG(1)
Classeur = "C1"
CTLINIT
If Not CtlOK Then Exit Sub
Bla bla

Sub PROG(2)
Classeur = "C2"
CTLINIT
If Not CtlOK Then Exit Sub
Blo blo

Sub CTLINIT () 'Contrôles initiaux communs aux classeurs Ci.
If ActiveWorkbook.Name <> Classeur Then
msg = MsgBox("Il faut être sur " & Classeur & " pour utiliser ce programme.", , "Contrôle de classeur")
CtlOK = False
Exit Sub
End If
Bli bli

Votre réponse précédente va me permettre de transmettre Classeur et CtlOK dans les 2 sens : Merci

Mais où écrire CTLINIT sans qu’il soit attaché à un classeur spécifique ?
(Je n’aurais pas du évoquer les boutons, c’était hors sujet)

Merci beaucoup pour votre aide
Avatar
MichD
Ta question n'est pas claire.

Ce que tu veux mettre en commun, ce sont des procédures?

Le plus simple est d'employer un fichier de macros personnelles.
Si tu n'en as pas déjà un, pour le créer tu n'as qu'à créer une
macro. Lorsque tu appelles la commande "Enregistrer une macro"
dans la fenêtre qui s'ouvre, tu peux donner un nom à la macro et
aussi choisir dans la liste déroulante de la même fenêtre, l'emplacement
où tu veux enregistrer la macro. Tu choisis dans la liste "Classeur de
macros personnelles"
Le classeur de macros personnelles sera créé dans ce répertoire :
C:Documents and SettingsUSERNAMEApplication DataMicrosoftExcelXlStart

toutes les macros que tu créées dans des modules standard de ce classeur
seront disponibles pour l'ensemble des classeurs que tu ouvres comme si
elles étaient directement enregistrées dans le classeur lui-même. Tu n'as
qu'à les appeler en utilisant le type de syntaxe que je t'ai déjà donné dans
mes exemples.

Le classeur de macros personnelles s'ouvre automatiquement dès que tu
ouvres Excel.

Il y a une autre alternative, l'utilisation d'un fichier de macros
complémentaires.
On en reparlera au besoin!


MichD
---------------------------------------------------------------
Avatar
merlan
Le mardi 27 Août 2013 à 21:08 par Merlan :
Bonjour,

En l'état actuel de mes connaissances, il n'existe qu'une relation 1-1
entre bouton de barre d'outil et "macro", créée par la
fonction 'affectation de macro'.

Je souhaite utiliser des procédures VBE comme sous-programmes communs
à plusieurs autres. Ces sous programmes ne seraient affectés
à aucun bouton, mais appelables par plusieurs Sub.
Je suppose qu'il faudrait aussi déclarer les variables communes en
Public et non par Dim.

Pour être plus clair, je souhaite faire comme dans Access où l'on
peut écrire du code "générique" dans Modules et
du code spécifique attaché à plusieurs contrôles de
formulaire par exemple.

Merci d'avance


Bonjour MichD

Oui, je veux mettre en commun des procédures.

J'ai trouvé le XLSTART et stocké CTLINIT dans le classeur PERSO.XLS dans le dossier XLSTART.

J'ai déclaré mes variables Public dans le module1 de PERSO, solution plus souple que de les passer en paramètres dans les instructions :
Call CTLINIT dans le prog appelant
Sub CTLINT.

L'exécution du prog appelant génère une erreur de compilation "e;Sub ou Function non définie"e;.

Le texte d'aide raconte :
erreur 35

vérifier le nom de procédure : c'est fait.

Puis il évoque la boite de dialogue Références : je ne la vois pas.
L'erreur vient probablement de là car CTLINIT est dans VBAProject(PERSO.XLS) et PROG1 dans VBAProject(C1), C1 étant le nom du classeur.

Comment corriger ça SVP ?
Avatar
MichD
À partir de l'interface de la feuille de calcul, lorsque tu
affiches la boîte de dialogue des macros existantes, les
macros du classeur sont affichées et peuvent être
appelées directement.

En VBA : Exemple général pour appeler une macro
située dans un autre classeur.

'------------------------------------------
Sub toto()

Dim MaMacro As String
'------------------------
'L'utilisation des apostrophes "'" permet d'utiliser
'un nom de classeur contenant des espaces. Cette syntaxe
'suppose que la macro est dans un module standard.
MaMacro = "'" & Workbooks("Personal.xlsb").Name & "'!" & "MaMacro"
Application.Run MaMacro
'------------------------

'Si la macro appelée est dans un module "feuille" du classeur de macros
'personnelles, la syntaxe :
MaMacro = "'" & Workbooks("Personal.xlsb").Name & "'!" & "Feuil1.MaMacro"
Application.Run MaMacro
'------------------------

'Si tu veux passer un paramètre, utilise ceci
Application.Run MaMacro, "toto"

Dans l'exemple que tu donnes, tu peux te contenter de ceci, car
le nom du classeur ne contient pas d'espace.
Application.Run "Personal.xlsb!MaMacro"

Si tu veux passer un paramètre :
Application.Run "Personal.xlsb!MaMacro", "toto"
"toto" est le paramètre

Et si la procédure est dans le module "feuille" de ton classeur de macros
personnelles
Application.Run "Personal.xlsb!Feuil1.MaMacro"
Feuil1 n'est pas le nom de l'onglet, mais le nom de l'objet "Feuille"
visible
seulement en VBA.

End Sub
'------------------------------------------

MichD
--------------------------------------------------------------
Avatar
merlan
Le mardi 27 Août 2013 à 21:08 par Merlan :
Bonjour,

En l'état actuel de mes connaissances, il n'existe qu'une relation 1-1
entre bouton de barre d'outil et "macro", créée par la
fonction 'affectation de macro'.

Je souhaite utiliser des procédures VBE comme sous-programmes communs
à plusieurs autres. Ces sous programmes ne seraient affectés
à aucun bouton, mais appelables par plusieurs Sub.
Je suppose qu'il faudrait aussi déclarer les variables communes en
Public et non par Dim.

Pour être plus clair, je souhaite faire comme dans Access où l'on
peut écrire du code "générique" dans Modules et
du code spécifique attaché à plusieurs contrôles de
formulaire par exemple.

Merci d'avance


OK, on avance

Application.Run "PERSO.XLS!MaMacro" fonctionne.

Je fais suivre de paramètres (je croyais que les déclarer Public était suffisant, mais apparemment non)
Les paramètres qui 'descendent' vers MaMacro sont bien utilisés.

Je souhaite aussi en faire 'remonter d'autres' :
MaMacro calcule la valeur de CtlOK qui est ensuite testée dans le Prog appelant.
C'est là que ça coince.


CtlOK vaut Vrai en sortie de MaMacro
Il vaut Faux juste quand il revient dans le prog appelant.

Donc : Comment remonter la valeur d'une variable modidiée par le sous prog?
Avatar
MichD
Si tu veux que ta macro dans le fichier de macros personnelles
retourne une valeur à la procédure appelante, utilise une
fonction personnalisée à la plage d'une procédure.

Voici un exemple :

Dans un module de ton classeur
'---------------------------------
Sub test()
Dim X As Long
X = 25
X = Application.Run("Personal.xlsb!MyFunction", 25)
MsgBox X
End Sub


Dans un module de ton fichier de macros personnelles
(le code de la fonction peut-être beaucoup plus complexe
ce n'est qu’aux fins de l'exemple).
'---------------------------------
Function MyFunction(MyVar As Long)

MyFunction = MyVar + 10

End Function
'---------------------------------



MichD
---------------------------------------------------------------
Avatar
merlan
Le mardi 27 Août 2013 à 21:08 par Merlan :
Bonjour,

En l'état actuel de mes connaissances, il n'existe qu'une relation 1-1
entre bouton de barre d'outil et "macro", créée par la
fonction 'affectation de macro'.

Je souhaite utiliser des procédures VBE comme sous-programmes communs
à plusieurs autres. Ces sous programmes ne seraient affectés
à aucun bouton, mais appelables par plusieurs Sub.
Je suppose qu'il faudrait aussi déclarer les variables communes en
Public et non par Dim.

Pour être plus clair, je souhaite faire comme dans Access où l'on
peut écrire du code "générique" dans Modules et
du code spécifique attaché à plusieurs contrôles de
formulaire par exemple.

Merci d'avance


Bonjour

Votre réponse conviendrait si je n'avais qu'un paramètre à remonter.
Mais la procédure appelée est assez longue et calcule un nombre important de variables.

Peut-on faire autrement ?

Comment se fait-il que la déclaration de ces variables en Public (que j'ai essayée dans le prog appelant et/ou dans l'appelé) ne réponde pas au besoin ?
Public me semblait fait pour ça.
1 2