I would like to handle single click and double click events separately for an ActiveX button in VBA. My issue is that the single click event is called for both single and double clicks. Is there a way to supress/bypass the single click procedure when a double click event occurs? I'm sure there's a simple answer for this, but can't find anything on the web...
From Help
If there is code in the Click event, the DblClick event will never trigger, because the Click event is the first event to trigger between the two. As a result, the mouse click is intercepted by the Click event, so the DblClick event doesn't occur.
Try capturing Mouse Down and Mouse Up, wait 500 ms, if no Mouse Down, then it's a single click, if there is wait the time for a mouse down.
DoubleClickSpeed
HKCU\Control Panel\Mouse
Data type Range Default value
REG_SZ 100 - 900 (milliseconds in decimal) 500
Brad Yundt provides this clever workaround at Experts-Exchange in this post.
I have assumed you have asked this wrt Excel- pls let me know if I am mistaken
You might try using Application.OnTime to schedule a response to a
leftclick after say a 1 second delay. If a doubleclick or rightclick
occurs in the meantime, then the leftclick event in the OnTime sub
will not occur.
The following code goes in the code pane for the worksheet being watched. Note that it uses the code name for that worksheet, not the tab name.
As written, the code watches A1:A10 for either a leftclick, rightclick or doubleclick on a single cell. It then displays a message box naming the cell that was clicked and the type of click.
worksheet event code
Dim bTrapped As Boolean
Dim cel As Range, rgWatch As Range
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(cel, Target) Is Nothing Then
MsgBox "Doubleclick at " & cel.Address
bTrapped = True
Cancel = True
End If
End Sub
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(cel, Target) Is Nothing Then
MsgBox "Rightclick at " & cel.Address
bTrapped = True
Cancel = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim targ As Range
Set rgWatch = Range("A1:A10")
Set targ = Intersect(Target, rgWatch)
If Not targ Is Nothing Then
If targ.Cells.Count = 1 Then
bTrapped = False
Set cel = targ.Cells(1, 1)
'Allow 1 second for user to complete a rightclick or doubleclick before trapping leftclick
Application.OnTime Now + 1 / 86400, "Sheet1.DelayedWatch" 'Note that Sheet1 is codename for worksheet (not tabname)
End If
End If
End Sub
Private Sub DelayedWatch()
If bTrapped = False Then
MsgBox "Leftclick at " & cel.Address
End If
End Sub
I know this reply is years late but to cancel an event, so as to prevent another event happening (on the same event) (ie. prevent single click for happening when you act on the double click) do the following;
Private Sub CheckBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
'Do your stuff in here to handle the doubleClick event
Cancel = True 'send back a true boolean to cancel the singleClick
End Sub
Related
I want a MsgBox to appear when cell A1 is clicked. I want it to appear even if A1 is already active when it is clicked:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
If Target.Row = 1 And Target.Column = 1 Then
MsgBox ("message")
End If
Application.EnableEvents = True
End Sub
This code works only if cell A1 is not already selected when I click on it. Currently the message box does not appear in this case.
Is there a way to fix this?
Your code is using Worksheet_SelectionChange which only fires when a different cell is selected (hence the name Selection Change).
Alternatively, if it's okay if your [unknown] goal is attained using double click or right click then there are other worksheet events that will help:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
MsgBox Target.Address & " was double clicked"
Cancel = True 'don't edit cell
End Sub
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
MsgBox Target.Address & " was right clicked"
Cancel = True 'don't open context menu
End Sub
Note that the code for these event procedures need to be placed in the worksheet module.
Edit: More creative ways
Click Event via PeekMessage API
If it must be a single click, there are "sneakier" ways to accomplish this, such as adding a Click event. This is not a built-in feature of Excel VBA, and thus, this method is not generally recommended.
It involves checking for the WM_MOUSEMOVE message when a cell is mouse-clicked, which is accomplished by calling the PeekMessage API inside the Worksheet_SelectionChange event. More info and examples here.
Transparent command button
There could also be a round-about way to accomplish this using an ActiveX Command Button with no caption, with the BackStyle property set to frmBackStyleTransparent.
Neither of these methods have been tested and you might need to do some fancy coding to get them to work. Depending on how often the same cell will be clicked that is already selected (and therefore how that functionality is to you), you may want to simply re-think the layout of your worksheet.
For example, you could add an extra column and have the user click the cell next to the one with the value to activate your message box.
More Information:
MSDN : Worksheet.BeforeDoubleClick Event (Excel)
MSDN : Worksheet.BeforeRightClick Event (Excel)
Chip Pearson : Events in Excel VBA
I have an Excel sheet that has a doubleclick event in cell "P1" (runs a macro).
I may have cell "J30" (or any other cell) selected before I doubleclick "P1"
How can I remember, and return to the cell "J30" after the "P1" doubleclick?
Storing the active cell doesn't work because the first click in the doubleclick sequence, selects "P1".
I also tried rightclick on "P1", but it also selects "P1" before running the event.
Well, it's a bit more complicated than the "duplicate thread" because the SelectionChange event is invoked prior to the BeforeDoubleClick event, so the former will update the last selection to the new one before the latter gets hand.
What you need is to go "one step further" in saving the selections, by actually saving both:
The current selection
The previous selection
Something like this should work
' Code module of your worksheet
Option Explicit
Private lastSelection As Range, beforeLastSelection As Range
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' Your Code for this event, i.e.
If Target.Address = "$P$1" Then
' Some code ...
Cancel = True
If Not beforeLastSelection Is Nothing Then beforeLastSelection.Select
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Set beforeLastSelection = lastSelection
Set lastSelection = Target
End Sub
Using the method here you can do as follows
Public PreviousActiveCell As Range
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
MsgBox ("Previous selection: " & PreviousActiveCell.Value & vbNewLine & _
"Double clicked selection: " & Target.Value)
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Static pPrevious As Range
Set PreviousActiveCell = pPrevious
Set pPrevious = ActiveCell
End Sub
Need your help on modifying the code or code that will help me do complete my task.
Its a protected workbook with VBA. I have a drop down on sheet1 in B18,D20,K11 and M46 and list of values in each drop down's.
When user changes the values in drop-down B18 and D20, I want to throw a prompt with "ok" and "cancel". User selects "ok" it should run a Module 1 ( which renames sheet).
Two things I am failing to achieve.
1. I don't want to throw prompt if user changes any other drop down values apart from 2 cells mentioned above,.
2. When clicked "OK" it should run module 1.
Please suggest if you have better code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rNg As Range
Set rNg = Range("B18", "D20")
MsgBox "Please click Calculate Button", vbOKOnly, "Calculate button"
End Sub
Try the code below.
(don't understand why you want to check if the user pressed "OK" since you are using a MsgBox with vbOKOnly and he has no other option)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rNg As Range
Dim IntersectRange As Range
Dim message As Integer
' modify here to the Range you need monitored
Set rNg = Range("B18", "D20")
Set IntersectRange = Intersect(Target, rNg)
If Not IntersectRange Is Nothing Then
message = MsgBox("Please click Calculate Button", vbOKOnly, "Calculate button")
If message = vbOK Then
Call Module1 ' or your Module / Function name
End If
Else
'Do Nothing if outside range
End If
End Sub
I am not saying this is the wright method, but you could use a UserForm to create custom prompts. And this is the way i do it, because for me it gives a better control on what i need to do.
Suppose if you create a userform with ok and cancel button, then you trigger the userform on the dropdown value change,
Sub DropDown1_Change()
UserForm1.Show
End Sub
Then write the codes for ok and cancel button clicks
Private Sub Ok_Click()
UserForm1.Hide
MsgBox "clicked ok"
End Sub
Private Sub cancel_Click()
UserForm1.Hide
MsgBox "clicked cancel"
End Sub
I have a form that appears on a double click event of a specific cell.
The form contains a list box with a bunch of checkboxes in it and in my _Activate() sub, the checkboxes are set to true or false based on values on the active sheet.
The trouble is that when the form opens up behind the cursor, the second click of the double click that opens the form is also checking/unchecking a checkbox in the form.
I've tried sticking "DoEvents" in the activate sub before the code sets the checkbox values but it hasn't made a difference - The checkbox behind my cursor where the form opens will be checked/unchecked.
I don't expect that the code will help much but it is essentially as below:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target = Range("aParticularRangeName") Then
frmSelectStuff.Show
End If
End Sub
Public Sub UserForm_Activate()
Dim iRegions As Integer
Dim sRecheck As Variant
Dim sRecheckList() As String
sRecheckList = Split(ActiveCell.Value, "; ")
For Each sRecheck In sRecheckList
For iRegions = 0 To lbRegionsTemp.ListCount - 1
If sRecheck = lbRegionsTemp.List(iRegions) Then lbRegionsTemp.Selected(iRegions) = True
Next
Next
End Sub
What about using Cancel = True?
If Target = Range("aParticularRangeName") Then
Cancel = True
frmSelectStuff.Show
End If
I've got a code in a dropdown box on my userform. Every time the user moves away from the drop down box, the code checks whether the value put by the user is correct (i.e. matches a list). If it doesn't, it triggers a message box. Here is my code:
Private Sub CmboxModifyRoute_Exit(ByVal Cancel As MSForms.ReturnBoolean)
UserValue = CmboxModifyRoute.Value
counter = 0
Cell = Range("C15").Value
If UserValue = "" Then Exit Sub
Do While (counter < 35 And Cell <> UserValue) 'checking if UserValue is valid
counter = counter + 1
Cell = Range("C15").Offset(counter, 0).Value
Loop
If counter > 34 Then 'if invalid, then display message box
MsgBox "Invalid", vbExclamation
End If
End Sub
The problem occurs when I quit the userform with the "X" button or "Cancel" button. If the UserValue is invalid, it still shows me the "Invalid" message box after I have already quit the userform. I don't want it, I just want the userform to unload. How can I deal with this? Many thanks!
Change your condition to this:
If Me.Visible And counter > 34 Then
MsgBox "Invalid", vbExclamation
End If
Then the message will not be displayed if the form isn't visible.
Data Validation should go in the BeforeUpdate event of the combo box. Before Update won't trigger prior to the User Form's Terminate event. Add UserForm_Terminate and CmboxModifyRoute_BeforeUpdate events to your code, set breakpoints on the declaration of each, and watch the order of events happen in debug mode.
Private Sub CmboxModifyRoute_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
'data validation goes here
'doesn't fire when the form is closed
End Sub
Private Sub CmboxModifyRoute_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'this triggers before Terminate
End Sub
Private Sub UserForm_Terminate()
End Sub