BeforeDoubleClick Event with multiple ranges - vba

Good afternoon,
I am trying to utilize the BeforeDoubleClick event within a worksheet that calls an input box for column L that prompts users to input their ID and another call for an input box that prompts users to enter the name of a team member that is giving a tour in column J. The code I had worked fine when it was just one event within column L, but the addition of the inputbox within column J keeps returning the "compile error: Argument not optional". My current code is:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
On Error Resume Next
enterUserName Target
GuideName Target
End Sub
Sub enterUserName(ByVal Target As Range, Cancel As Boolean)
Dim x As Range, Y As Range
Set x = Target
Set Y = Range("L3:L300")
If Intersect(x, Y) Is Nothing Then Exit Sub
Cancel = True
t.Offset(0, 0).Value = InputBox(Prompt:="Please enter your User ID.")
End Sub
Sub GuideName(ByVal Target As Range, Cancel As Boolean)
Dim t As Range, B As Range
Set t = Target
Set B = Range("J3:J300")
If Intersect(t, B) Is Nothing Then Exit Sub
Cancel = True
t.Offset(0, 0).Value = InputBox(Prompt:="Please enter ONLY the first name of the tour guide.")
End Sub
Any help is greatly appreciated! Thanks!

Thank you, Matt -
After some further research and troubleshooting, the code is working for both events utilizing the BeforeDoubleClick event. The most helpful information came from Tushar Mehta's website: http://www.tushar-mehta.com/publish_train/xl_vba_cases/1021_multiple_tasks_in_an_event_procedure.htm
I made minimal changes to the last example on the website, and changed my original sub to the following (and everything is working like I had hoped):
Private Sub GoBeforeDoubleClick1(ByVal Target As Range, Cancel As Boolean)
Dim t As Range, B As Range
Set t = Target
Set B = Range("L3:L300")
If Intersect(t, B) Is Nothing Then
Exit Sub
Else: t.Offset(0, 0).Value = InputBox(Prompt:="Please enter your User ID.")
Exit Sub
End If
End Sub
Private Sub GoBeforeDoubleClick2(ByVal Target As Range, Cancel As Boolean)
Dim x As Range, Y As Range
Set x = Target
Set Y = Range("J3:J300")
If Intersect(x, Y) Is Nothing Then
Exit Sub
Else: x.Offset(0, 0).Value = InputBox(Prompt:="Please enter ONLY the first name of the tour guide.")
Exit Sub
End If
Cancel = True
End Sub
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
On Error Resume Next
GoBeforeDoubleClick1 Target, Cancel
GoBeforeDoubleClick2 Target, Cancel
Application.EnableEvents = True
End Sub

Related

Unable to Activate Macro when Active Cell Changes Through formula

My aim is to trigger the advanced filter macro when cell B2 changes (a part of the filtering criteria). B2 is linked to another cell(in another worksheet) which dynamically gets data from external sources. The problem I am facing is that the macro does not activate automatically. Only when I manually change something in B2 is the macro activated. Otherwise the old criteria remains in place. A1 to G1 has the 7 categories and A2-G2 has the inputs for the filter. Only B2 changes effectively. I have not coded in VBA before so most of this code is copied from websites and modified for my workbook. Below is my code. Appreciate any help on this.
Option Explicit
'Create variable to hold values
Dim Monitored()
Sub Advanced_Filtering()
Range("A7:G730").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range("A1:G2"), CopyToRange:=Sheets("Sheet3").Range("L1:R1")
End Sub
Private Sub Worksheet_Activate()
Monitored = Range("B2:C2").Value 'Read in value prior to any changes
End Sub
Private Sub Worksheet_Calculate()
Dim Xrg As Range, c As Range, x As Integer
Set Xrg = Range("B2:C2")
If Not Intersect(Xrg, Range("B2:C2")) Is Nothing Then
Application.EnableEvents = False
'Compare monitored cell with initial value
x = 1
For Each c In Range("B2:C2")
If c.Value <> Monitored(x, 1) Then
Call Advanced_Filtering
Monitored(x, 1) = c.Value
End If
x = x + 1
Next c
'Reset events
Application.EnableEvents = True
End If
End Sub
Probably the easiest fix would be to place the Worksheet_Change event under the cells that generate the value on your cell B2, as changes in formula values don't trigger the Change event... or you can change it to Worksheet_Calculate event instead, this will pick up changes in formula results as below:
Option Explicit
'Create variable to hold values
Dim Monitored
Sub Advanced_Filtering()
Range("A7:G730").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range("A1:G2"), CopyToRange:=Sheets("Sheet3").Range("L1:R1")
End Sub
Private Sub Worksheet_Activate()
Monitored = Range("B2").Value 'Read in value prior to any changes
End Sub
Private Sub Worksheet_Calculate()
Dim Xrg As Range
Set Xrg = Range("B2")
If Not Intersect(Xrg, Range("B2")) Is Nothing Then
Application.EnableEvents = False
'Compare monitored cell with initial value
If Range("B2").Value <> Monitored Then
'Do things as a result of a change
Call Advanced_Filtering
'Reset Variable with new monitored value
Monitored = Range("B2").Value
End If
'Reset events
Application.EnableEvents = True
End If
End Sub
UPDATE:
To use a Range of cells instead of a single one, you should change the following:
Option Explicit
'Create variable to hold values
Dim Monitored()
Sub Advanced_Filtering()
Range("A7:G730").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range("A1:G2"), CopyToRange:=Sheets("Sheet3").Range("L1:R1")
End Sub
Private Sub Worksheet_Activate()
Monitored = Range("B2:C2").Value 'Read in value prior to any changes
End Sub
Private Sub Worksheet_Calculate()
Dim Xrg As Range, c As Range, x As Integer
Set Xrg = Range("B2:C2")
If Not Intersect(Xrg, Range("B2:C2")) Is Nothing Then
Application.EnableEvents = False
'Compare monitored cell with initial value
x = 1
For Each c In Range("B2:C2")
If c.Value <> Monitored(1, x) Then
Call Advanced_Filtering
Monitored(1, x) = c.Value
End If
x = x + 1
Next c
'Reset events
Application.EnableEvents = True
End If
End Sub

MsgBox SelectionChange define range

I have written the following code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim myValue As Variant
If Range("B22") = "Yes" Then
myValue = InputBox("InsertInitialDetach")
Range("C22").Value = myValue
End If
End Sub
This code is meant to do the following thing: If I select Yes from a Yes/No drop down list, a message box appears and asks me to fill in a date.
The problem is that even after I fill the date, whatever I do afterwards, the box keeps on appearing and asking for the date. If I move two cells down, for example, the popup will continue to ask me for a date.
Please tell me what should I do to fix this error?
Would this be ok:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim myValue As Variant
If (Not Intersect(Range("B22"), Target) Is Nothing) And (Range("B22") = "Yes") Then
myValue = InputBox("InsertInitialDetach")
Range("C22").Value = myValue
End If
End Sub
It checks every time whether you are changing Range("B22") and whether Range("B22") "Yes".
You are using the selectionChange event which triggers after any change in the area selected, if want to trigger on value changes use the change event
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myValue As Variant
On Error GoTo ErrorOccured
If Target.Address = "$B$1" And Target.Value = "Yes" Then
myValue = InputBox("Insert initialDetach")
Range("B2").Value = myValue
End If
ErrorOccured:
'Do when value is not valid
End Sub

Vba msgbox show only once

Is it possible to make the msgbox of this code to appear only once? My problem is that if the user inserts data i.e. from row 501 until 510 the message box will appear 9 times, and I want to have it only once. The reason of this is because the code looks in each cell to verify if something is inserted, and then the content is deleted and the msg appears. If it is possible I would like to keep the format of the code below, but only to show the msgbox once. If not, any suggestions would be welcomed.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell22 As Range
Application.EnableEvents = False
For Each cell22 In Target
If Not Application.Intersect(cell22, Range("a501:z6000")) Is Nothing Then
If cell22.Value <> "" Then
cell22.ClearContents
MsgBox "You cannot insert more than 500 rows", vbInformation, "Important:"
End If
End If
Next cell22
Application.EnableEvents = True
End Sub
I would suggest another way.
The tasks which access the worksheet, such as ClearContents takes the longer to process.
So instead of clearing the contents each time inside the loop for a single cell, and repeat it a few hundred times, use ClrRng as a Range object. Every time the If criteria is met, you add it to ClrRng using the Application.Union function.
Once you finish looping through all your cells, clear the entire cells in ClrRng at the same time.
Code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell22 As Range, b As Boolean
Dim ClrRng As Range ' define a range to add all cells that will be cleared
Application.EnableEvents = False
For Each cell22 In Target
If Not Application.Intersect(cell22, Range("A501:Z6000")) Is Nothing Then
If cell22.Value <> "" Then
If Not ClrRng Is Nothing Then
Set ClrRng = Application.Union(ClrRng, cell22)
Else
Set ClrRng = cell22
End If
End If
End If
Next cell22
If Not ClrRng Is Nothing Then ' make sure there is at least 1 cell that passed the If criteria
ClrRng.ClearContents ' clear all cell's contents at once
MsgBox "You cannot insert more than 500 rows", vbInformation, "Important:"
End If
Application.EnableEvents = True
End Sub
Try this:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell22 As Range
Application.EnableEvents = False
For Each cell22 In Target
If Not Application.Intersect(cell22, Range("a501:z6000")) Is Nothing Then
If cell22.Value <> "" Then
cell22.ClearContents
GoTo displayMsg
End If
End If
Next cell22
Application.EnableEvents = True
Exit Sub
displayMsg:
MsgBox "You cannot insert more than 500 rows", vbInformation, "Important:"
Application.EnableEvents = True
End Sub
This will only show it once but clear each cell which is non-blank.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell22 As Range, b As Boolean
Application.EnableEvents = False
For Each cell22 In Target
If Not Application.Intersect(cell22, Range("a501:z6000")) Is Nothing Then
If cell22.Value <> "" Then
cell22.ClearContents
b = True
End If
End If
Next cell22
If b Then MsgBox "You cannot insert more than 500 rows", vbInformation, "Important:"
Application.EnableEvents = True
End Sub

VBA - Type mismatch on declaration of Excel.Range

I am trying to declare a range of cells as an Excel.Range variable in the BeforeSave() event of my excel workbook.
The background is, that the values in this range are mandatory inputs and I want to validate that they are all filled on saving.
If I want to execute the function I get the error message
Runtime Error "13": Type Mismatch
Here's the code I tried.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim r1 As Range
Set r1 = Range("G11:G14")
If Cells(10, 1).Value = "" Then
MsgBox "Cell requires user input", vbInformation, "Please filled up the mandatory cells"
Cancel = True
Exit Sub
ElseIf r1.Value = "" Then // runtime error "13": Type Mismatch
MsgBox "Please make sure you had filled in all the Questionnire Answers.", vbInformation, "Missing Answer"
Cancel = True
Exit Sub
End If
Cancel = False
End Sub
I am relatively new to VBA so please feel free to point out my mistake.
Thanks in advance!
You will get this error:
Runtime Error "13": Type Mismatch
Because r1 is defined as a Range of multiple cells and you cannot check if a multiple-cell Range is simply empty string. You need to check each cell in the range.
Try this code - it is a Function that checks to see if any cell, in a group of cells, is "" and returns True if that is so:
Option Explicit
Function TestMultipleCellsAnyAreEmpty(rng As Range) As Boolean
Dim rngCell As Range
Dim blnAnyRangeIsEmpty
blnAnyRangeIsEmpty = False
For Each rngCell In rng
If rngCell.Value = "" Then
blnRangeIsEmpty = True
Exit For
End If
Next rngCell
TestMultipleCellsAreEmpty = blnRangeIsEmpty
End Function
Combining this technique with your workbook event you can have this complete code:
Option Explicit
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim r1 As Range
Set r1 = ThisWorkbook.Worksheets("YOUR_SHEET").Range("G11:G14") '<-- specify the worksheet
If ThisWorkbook.Worksheets("YOUR_SHEET").Cells(10, 1).Value = "" Then '<-- specify the worksheet
MsgBox "Cell requires user input", vbInformation, "Please filled up the mandatory cells"
Cancel = True
Exit Sub
ElseIf TestMultipleCellsAnyAreEmpty(r1) Then
MsgBox "Please make sure you had filled in all the Questionnire Answers.", vbInformation, "Missing Answer"
Cancel = True
Exit Sub
End If
Cancel = False
End Sub
Function TestMultipleCellsAnyAreEmpty(rng As Range) As Boolean
Dim rngCell As Range
Dim blnAnyRangeIsEmpty
blnAnyRangeIsEmpty = False
For Each rngCell In rng
If rngCell.Value = "" Then
blnRangeIsEmpty = True
Exit For
End If
Next rngCell
TestMultipleCellsAreEmpty = blnRangeIsEmpty
End Function
I suspect it's because you need to qualify your range definition to say Set r1 = ThisWorkbook.Range("G11:G14"). Also, I believe that the .Value property of a multi-cell range will return the value in the top leftmost cell.

Change userform textbox value with cell double-click event

I have been searching for a answer all morning and have not come up with a solution. I want to change the value of a textbox1 on userform1 after a double click event. I keep getting the method or data member not found error. How do I complete this from the double click event?
Public Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Worksheets("Offense").Range("A:A")) Is Nothing Then
Cancel = True
DataCollectionFormValid.Show
Me.RowNumber.Value = ActiveCell.Row ' error here
End If
End Sub
Me refers to the object running the code, which in this case is the worksheet, not the userform. You need:
Public Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Worksheets("Offense").Range("A:A")) Is Nothing Then
Cancel = True
With DataCollectionFormValid
.RowNumber.Value = ActiveCell.Row
.Show
End With
End If
End Sub