Bonjour a tous
comme on me le demande souvent je vous donne un exemple du comment on associe l'affichage d'un userform a une plage dans une feuille et comment on gère les events de la feuille dans le userform
tout d'abords je redis avant tout un module userform est un module classe
en effet peu le savent et d'autres comprennent mal
une classe dans un module (quel qu’il soit) se déclare comme ceci
dim maclasse as classe1
et dans une sub ou event
set maclasse = new classe1 'classe1 étant le nom du module classe
et bien avec le userform c'est la même chose
voici un exemple
j'ajoute un userform dans mon classeur et je le nomme "menu"
je voudrais qu'il s'affiche au click droit dans la feuil1 en range B3:B10 dès que j'active cette feuille
je commence donc par instancier une classe de mon module userform dans ma feuil1
dans le module de la feuille en question
donc ici déclare un instance classe de mon userform menu
je déclare une variable public range ( la plage que je souhaite
elle peut être sous toute forme contiguë ou pas
et dans l'event activate (de la feuille)
je détermine la plage
j'instancie la classe déclarée
j'ajoute la possibilité de choisir si mon userform menu sera modal ou pas avec une variable déclaré dans le userform (nous allons voir après comment dans le module du userform)
voila la partie code de la feuille est terminé
passons a l'userform "menu"
je vais instancier un classe event feuille dans le userform
parti de la je peux gérer tout les events d'une feuille
je déclare aussi une variable pour le mode modal ou pas
maintenant il faut instancier la classe event feuille
et cela on va le faire dans le initialise userform( et pas ailleur!!!!!)
voila c'est pas bien compliqué
maintenant on va coder l'event feuille
les events feuille sont désormais implémentés dans la liste du module userform ( voir capture)
nous allons pour un menu choisir l'event click droit
voici l'event codé complètement
Remarque
1°j'utilise activesheet.rng au lieu de feuil1.rng( pour une réutilisation sur d'autres feuilles
2° je précise toujours le parent userform par son nom et non "Me" comme on le ferait normalement dans un userform(TRES IMPORTANT!!!!)
car en effet dans l'event feuille vous êtes dans la classe et pas dans l'instance du userform proprement dit
je met ensuite le userform en StartUpPosition 0 pour pouvoir le déplacer avant même de l'afficher
je le place avec ma fonction perso (voir plus bas)
je l'affiche avec la variable "umodal" que j'ai instruit dans le activate du module de la feuille
je cancel bien évidement pour ne pas avoir le menu contextuel que l'on a normalement au click droit dans une cellule
comme pour les menus j'ajoute l’effacement du menu au click ailleurs pendant son affichage
ATTENTION!! ne fonctionne qu'en mode non modal( comme les menu classique d'ailleurs )
je joint ma fonction perso pour l'emplacement qui gère toute les possibilités de l'affichage d'une feuille
voila maintenant votre userform s'affichera a droite de la cellule cliqué si elle se trouve dans la plage "RnG"
vous reste plus qu'a coder votre menu avec des boutons et autres controls dans le userform
comme on me le demande souvent je vous donne un exemple du comment on associe l'affichage d'un userform a une plage dans une feuille et comment on gère les events de la feuille dans le userform
tout d'abords je redis avant tout un module userform est un module classe
en effet peu le savent et d'autres comprennent mal
une classe dans un module (quel qu’il soit) se déclare comme ceci
dim maclasse as classe1
et dans une sub ou event
set maclasse = new classe1 'classe1 étant le nom du module classe
et bien avec le userform c'est la même chose
voici un exemple
j'ajoute un userform dans mon classeur et je le nomme "menu"
je voudrais qu'il s'affiche au click droit dans la feuil1 en range B3:B10 dès que j'active cette feuille
je commence donc par instancier une classe de mon module userform dans ma feuil1
dans le module de la feuille en question
VB:
Dim u As menu
Public RnG As Range
Private Sub Worksheet_Activate()
Set RnG = [B3:B10]
menu.Umodal = 0
Set u = New menu
End Sub
donc ici déclare un instance classe de mon userform menu
je déclare une variable public range ( la plage que je souhaite
elle peut être sous toute forme contiguë ou pas
et dans l'event activate (de la feuille)
je détermine la plage
j'instancie la classe déclarée
j'ajoute la possibilité de choisir si mon userform menu sera modal ou pas avec une variable déclaré dans le userform (nous allons voir après comment dans le module du userform)
voila la partie code de la feuille est terminé
passons a l'userform "menu"
je vais instancier un classe event feuille dans le userform
Code:
Public WithEvents feuille As Worksheet
je déclare aussi une variable pour le mode modal ou pas
Code:
Public Umodal As Boolean
et cela on va le faire dans le initialise userform( et pas ailleur!!!!!)
VB:
Private Sub UserForm_Initialize()
Set feuille = ActiveSheet
End Sub
maintenant on va coder l'event feuille
les events feuille sont désormais implémentés dans la liste du module userform ( voir capture)
nous allons pour un menu choisir l'event click droit
voici l'event codé complètement
VB:
Private Sub feuille_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(ActiveSheet.RnG, Target) Is Nothing Then
menu.StartUpPosition = 0
placementRange menu, ActiveCell
menu.Show menu.Umodal: Cancel = True
Else
Cancel = False
Unload menu
End If
End Sub
1°j'utilise activesheet.rng au lieu de feuil1.rng( pour une réutilisation sur d'autres feuilles
2° je précise toujours le parent userform par son nom et non "Me" comme on le ferait normalement dans un userform(TRES IMPORTANT!!!!)
car en effet dans l'event feuille vous êtes dans la classe et pas dans l'instance du userform proprement dit
je met ensuite le userform en StartUpPosition 0 pour pouvoir le déplacer avant même de l'afficher
je le place avec ma fonction perso (voir plus bas)
je l'affiche avec la variable "umodal" que j'ai instruit dans le activate du module de la feuille
je cancel bien évidement pour ne pas avoir le menu contextuel que l'on a normalement au click droit dans une cellule
comme pour les menus j'ajoute l’effacement du menu au click ailleurs pendant son affichage
ATTENTION!! ne fonctionne qu'en mode non modal( comme les menu classique d'ailleurs )
VB:
' ne fonctionne qu'en mode non modal
Private Sub feuille_SelectionChange(ByVal Target As Range)
If Intersect(ActiveSheet.RnG, Target) Is Nothing Then Unload menu
End Sub
je joint ma fonction perso pour l'emplacement qui gère toute les possibilités de l'affichage d'une feuille
VB:
'********************************************************************
'********************************************************************
'fonction placementrange issue de mon calendrier plus complet dans les ressources
'https://www.excel-downloads.com/resources/collection-fausse-boite-de-dialogue-patricktoulon-episode-1-un-vrai-faux-calendrier.1119/
Public Function placementRange(uf As Object, Obj As Object)
If Obj Is Nothing Then Exit Function
Dim z#, EcX#, L1#, T1#, C#, R#, Vr As Range, Hx#, Wx#, Ok As Boolean, Op&, PtoPx#, I&
With ActiveWindow
PtoPx = (.ActivePane.PointsToScreenPixelsX(72) - .ActivePane.PointsToScreenPixelsX(0)) / 72 'coeff point to pixel
Op = Int(Val(Mid(Application.OperatingSystem, InStrRev(Application.OperatingSystem, " ") + 1))) 'number version system
'exit si la cellule injecté n'est pas vible a l'ecran
For I = 1 To .Panes.Count: Ok = IIf(Not Intersect(.Panes(I).VisibleRange, Obj) Is Nothing, True, Ok): Next
If Ok = False Then Beep: MsgBox " cette cellule n'est pas visible a l'ecran": Exit Function
z = (ActiveWindow.Zoom / 100): Set Vr = .VisibleRange 'Coeff zoom , rangevisible partie mobile
EcX = 4 And Op = 6 And Int(Val(Application.Version)) < 16 'ecart cadre
L1 = (.ActivePane.PointsToScreenPixelsX(Int(Obj.Left)) / PtoPx) * z + EcX 'placement partie mobile
T1 = .ActivePane.PointsToScreenPixelsY(Int(Obj.Top)) / PtoPx * z + EcX
With .Panes(1).VisibleRange: C = .Cells(.Cells.Count).Column: R = .Cells(.Cells.Count).Row: End With 'limite splitrow et splitcolumn
If .SplitRow > 0 Then 'placement dans le splitrow
If Obj.Row < R + 1 And .ScrollRow > R Then T1 = ((.ActivePane.PointsToScreenPixelsY(Vr.Cells(1).Top) / PtoPx) * z) - (Range(Obj, Cells(R, 1)).Height * z) + EcX
End If
If .SplitColumn > 0 Then 'placement dans le splitcolumn
If Obj.Column < C + 1 And .ScrollColumn > C Then L1 = ((.ActivePane.PointsToScreenPixelsX(Vr.Cells(1).Left) / PtoPx) * z) - (Range(Obj, Cells(1, C)).Width * z) + EcX
End If
End With
L1 = L1 + Obj.Width '- 2
T1 = T1 '- 2
If L1 > Application.Left + Application.Width - Me.Width Then L1 = Application.Left + Application.Width - Me.Width - 15
If T1 > Application.Top + Application.Height - Me.Height Then T1 = Application.Top + Application.Height - Me.Height - 15
With uf: .Left = L1: .Top = T1: End With
End Function
voila maintenant votre userform s'affichera a droite de la cellule cliqué si elle se trouve dans la plage "RnG"
vous reste plus qu'a coder votre menu avec des boutons et autres controls dans le userform
- Auteur
- patricktoulon
- Version
- 1.0