web-dev-qa-db-fra.com

OnClick dans Excel VBA

Est-il possible d'attraper un clic sur une cellule de VBA avec Excel? Je ne fais pas référence à l'événement Worksheet_SelectionChange, car cela ne déclenchera pas plusieurs fois si la cellule est cliquée plusieurs fois. BeforeDoubleClick ne résout pas mon problème non plus, car je ne veux pas demander à l'utilisateur de double-cliquer dessus régulièrement.

Ma solution actuelle fonctionne avec l'événement SelectionChange, mais elle semble nécessiter l'utilisation de variables globales et d'autres pratiques de codage non optimales. Cela semble aussi sujet aux erreurs.

20
haslo

De toute évidence, il n'y a pas de réponse parfaite. Toutefois, si vous souhaitez autoriser l'utilisateur à 

  1. sélectionner certaines cellules 
  2. leur permettre de changer ces cellules, et
  3. capturer chaque clic, même les clics répétés sur la même cellule,

le moyen le plus simple semble alors être de déplacer le focus de la cellule sélectionnée de sorte que cliquer dessus déclenchera un événement Select.

Une option consiste à déplacer le focus comme je l'ai suggéré ci-dessus, mais cela empêche la modification des cellules. Une autre option consiste à étendre la sélection d'une cellule (gauche/droite/haut/bas), car cela permet de modifier la cellule d'origine, mais déclenchera un événement de sélection si cette cellule est cliquée de nouveau. 

Si vous souhaitez uniquement intercepter la sélection d'une seule colonne de cellules, vous pouvez insérer une colonne masquée à droite, étendre la sélection pour inclure la cellule masquée à droite lorsque l'utilisateur clique dessus. Vous obtenez ainsi une cellule modifiable pouvant être pris au piège à chaque fois qu'il est cliqué. Le code est comme suit 

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  'prevent Select event triggering again when we extend the selection below
  Application.EnableEvents = False
  Target.Resize(1, 2).Select
  Application.EnableEvents = True
End Sub
20
dbb

Pour capturer des clics répétés sur la même cellule, vous devez déplacer le focus sur une cellule différente, de sorte que chaque fois que vous cliquez, vous déplacez la sélection. 

Le code ci-dessous sélectionnera la cellule en haut à gauche visible à l'écran lorsque vous cliquez sur une cellule. Évidemment, il a le défaut de ne pas coincer un clic dans la cellule en haut à gauche, mais cela peut être géré (par exemple en sélectionnant la cellule en haut à droite si la cellule active est en haut à gauche).

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  'put your code here to process the selection, then..
  ActiveWindow.VisibleRange.Cells(1, 1).Select
End Sub
7
dbb

SelectionChange est l'événement intégré au modèle d'objet Excel pour cela. Il convient de faire exactement ce que vous voulez, en tirant à tout moment lorsque l'utilisateur clique n'importe où ... 

Je ne suis pas sûr de comprendre vos objections aux variables globales, vous n’auriez besoin que de 1 si vous utilisez l’événement Application.SelectionChange. Cependant, vous n'en aurez pas besoin si vous utilisez le code de classe Workbook derrière (pour intercepter l'événement Workbook.SelectionChange) ou le code de classe Worksheet derrière (pour intercepter l'événement Worksheet.SelectionChange). (Sauf si votre problème est le problème de la "réinitialisation globale des variables" dans VBA, pour lequel il n'y a qu'une solution: la gestion des erreurs partout. N'autorisez aucune erreur non gérée, mais enregistrez-les et/ou "rapportez à la volée" une erreur sous forme de message. boîte à l'utilisateur.)

Vous devrez peut-être également piéger les événements Worksheet.Activate () et Worksheet.Deactivate () (ou l’équivalent dans la classe Workbook) et/ou les événements Workbook.Activate et Workbook.Deactivate () pour que vous sachiez quand changé de feuilles de travail et/ou de classeurs. Les événements d'activation et de désactivation de la fenêtre doivent compléter cette approche. Ils pourraient tous appeler la même procédure exacte, cependant, ils dénotent tous la même chose: l'utilisateur a changé le "focus", si vous voulez.

Si vous n'aimez pas VBA, vous pouvez faire de même avec VB.NET ou C #.

[Edit: Dbb insiste beaucoup sur le fait que l'événement SelectionChange ne capte pas un clic lorsque l'utilisateur clique dans la cellule actuellement sélectionnée. Si vous avez besoin de le relever, vous devez utiliser le sous-classement.]

1
Mike Rosenblum

Je ne pense pas. Mais vous pouvez créer un objet de forme (ou un wordart ou quelque chose de similaire), accrocher l'événement Click et placer l'objet à la position de la cellule spécifiée.

0
TcKs

Cela a fonctionné pour moi .....

Private Sub Worksheet_Change(ByVal Target As Range)

    If Mid(Target.Address, 3, 1) = "$" And Mid(Target.Address, 2, 1) < "E" Then
       ' The logic in the if condition will filter for a specific cell or block of cells
       Application.ScreenUpdating = False
       'MsgBox "You just changed " & Target.Address

       'all conditions are true .... DO THE FUNCTION NEEDED 
       Application.ScreenUpdating = True
    End If
    ' if clicked cell is not in the range then do nothing (if condttion is not run)  
End Sub

REMARQUE: cette fonction en cours d'utilisation recalculait un tableau croisé dynamique si un utilisateur ajoutait un élément dans une plage de données allant de A4 à D500. Il y avait des sections protégées et non protégées dans la feuille; le contrôle du clic est donc réel si la colonne est inférieure à "E" La logique peut devenir aussi complexe que vous le souhaitez, y compris inclure ou exclure un nombre illimité de zones

block1  = row > 3 and row < 5 and column column >"b" and < "d" 
block2  = row > 7 and row < 12 and column column >"b" and < "d" 
block3  = row > 10 and row < 15 and column column >"e" and < "g"

If block1 or block2 or block 3 then
  do function .....
end if  
0
Joe

J'ai eu un problème similaire, et j'ai corrigé en exécutant la macro "onTime" et en utilisant certaines variables globales à exécuter uniquement lorsque l'utilisateur a cessé de cliquer.

Public macroIsOnQueue As Boolean
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    macroIsOnQueue = False
    Application.OnTime (Now() + TimeValue("00:00:02")), "addBordersOnRow"
    macroIsOnQueue = True
End sub
Sub addBordersOnRow()
    If macroIsOnQueue Then        
       macroIsOnQueue = False
       ' add code here
    End if
End sub

Ainsi, chaque fois que l'utilisateur change de sélection dans les 2 secondes, la variable macroIsOnQueue est définie sur false, mais la dernière sélection est modifiée, macroIsOnQueue est défini sur true et la macro est exécutée.

J'espère que cela aide, Amusez-vous avec VBA !!

0
Dumitru Daniel