Open UserForm upon selecting any cell in a table - excel

I am using the following code to open a userform upon cell selection in a table by user, where each table has 30 rows with multiple tables in one sheet. I will have to write 100s of lines again and again.
I know this is not an efficient way to do so. How do I make this code simpler and shorter without affecting functionality?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address = "$D$31:$E$31" Then
Open_Text_Form
End If
If Target.Address = "$D$32:$E$32" Then
Open_Text_Form
End If
If Target.Address = "$D$33:$E$33" Then
Open_Text_Form
End If
If Target.Address = "$D$34:$E$34" Then
Open_Text_Form
End If
If Target.Address = "$D$35:$E$35" Then
Open_Text_Form
End If
If Target.Address = "$D$36:$E$36" Then
Open_Text_Form
End If
If Target.Address = "$D$37:$E$37" Then
Open_Text_Form
End If
End Sub

You can use the Intersect function to find if a range (cell) is inside of a given range. Without knowing how the data is setup in the sheet, I can't say what the best way to check is. If the multiple "tables" on your sheet are actually Excel tables, you can do something like this to have it check if you have clicked inside of one of them.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim tableRange As Range
For i = 1 To ListObjects.Count
If i = 1 Then
Set tableRange = ListObjects(i).DataBodyRange
Else
Set tableRange = Application.Union(tableRange, ListObjects(i).DataBodyRange)
End If
Next
If tableRange Is Nothing Then Exit Sub
If Not Application.Intersect(Target, tableRange) Is Nothing Then
Open_Text_Form
End If
End Sub
However if the "tables" in your sheet are just normal data ranges you could define them in a named range and all you would need to do is
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("MyNamedRange")) Is Nothing Then
Open_Text_Form
End If
End Sub

Related

Merging multiple Worksheet_SelectionChange

I have got no problem in running one Private Sub Worksheet_SelectionChange , but when i add multiple Worksheet_SelectionChange events it is not running. Later, i came to know that it is not possible running different worksheet selection change events in the same sheet.
I am having four different Private Sub Worksheet_SelectionChange events, trying to merge them with the help of various sites but none worked to me, as per my understanding.
Could i get some help,
1.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells1 As Range
Set cells1 = ActiveSheet.Range("B1:B27")
If Not (Intersect(Target, cells1) Is Nothing) Then
ActiveSheet.Range("B30").Value = Target.Value
End If
End Sub
2.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells2 As Range
Set cells2 = ActiveSheet.Range("C1:C27")
If Not (Intersect(Target, cells2) Is Nothing) Then
ActiveSheet.Range("C30").Value = Target.Value
End If
End Sub
3.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells3 As Range
Set cells3 = ActiveSheet.Range("S1:S27")
If Not (Intersect(Target, cells3) Is Nothing) Then
ActiveSheet.Range("S30").Value = Target.Value
End If
End Sub
4.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells4 As Range
Set cells4 = ActiveSheet.Range("T1:T27")
If Not (Intersect(Target, cells4) Is Nothing) Then
ActiveSheet.Range("T30").Value = Target.Value
End If
End Sub
I appreciate your help.
Thank you.
You can use a switch (select case) within your change event to allow options for which will occur.
Mock-up:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Row > 27 then Exit Sub
Select Case Target.Column
Case 2, 3, 19, 20
Cells(30,Target.Column).Value = Target.Value
End Select
End Sub
I have added the Exit Sub check for if the row > 27, as your ranges are 1:27, for each of the Columns. This replaces the Intersect() check.
You perform the same action based on the Target.Column, so that is the only other parameter to verify and utilize.

Copy paste values triggered by worksheet change event is not working

I am using worksheet change event to trigger copy paste values. Worksheet change code is in the sheet2
Sub worksheet_change(ByVal Target As Range)
Application.EnableEvents = True
Set Target = Range("AB2")
If Target.Value = "OK" Then
Call myTR1
End If
Please note AB2 cell takes it's value from another sheet
Copy paste code is in a Module
Sub myTR1()
Sheets("BA1").Range("AR6:AS8").Value = Sheets("BA1").Range("AL17:AM19").Value
End Sub
When target range changes to "OK", my copy paste macro is not triggering. What am I doing wrong?
Using your eaxct code worked, although you didnt have end sub in your example?
EDIT:
Bear in mind the 'OK' is case sensitive so it will have to be in uppercase to fire, if you want it to fire either on lower or upper you can use the second code.
Sub worksheet_change(ByVal Target As Range)
Application.EnableEvents = True
Set Target = Range("AB2")
If Target.Value = "OK" Then
Call myTR1
End If
End Sub
Sub worksheet_change(ByVal Target As Range)
Application.EnableEvents = True
Set Target = Range("AB2")
If Target.Value = "OK" Or Target.Value = "ok" Then
Call myTR1
End If
End Sub

How to simplify; dozens of Excel Tabs with the same underlying VBA Code

I have 51 unique tabs in a workbook. Each tab has a bit of code that will update the 52nd tab when certain cells are changed on the 51. Bottom line, it's an audit history of the 2 cells on each of the 51 tabs.
I've pieced together the following code that I drop onto each worsheets VBA section. The problem is that I have to do this for every single sheet in the workbook. I'd think that I should be able to have just a single common call to the meat of the VBA...
Dim PreVal
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address = "$D$1" Or Target.Address = "$D$2" Then
PreVal = Target.Value
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$D$1" Then
If Target.Value <> PreVal Then
SomethingSomewhere = Value
PreVal = Target.Value
End If
End If
If Target.Address = "$D$2" Then
If Target.Value <> PreVal Then
SomethingSomewhere = Value
PreVal = Target.Value
End If
End If
End Sub
It works wonderfully, just managing any changes needs to be done on every single sheet..
BTW, the SomethingSomewhere equals Value sets the app user name, sheet name, preval, target value, and date time into columns on the logging page
Create a subroutine that contains the logic and then create the application you drop on to each sheet. This application will call the subroutine. Now, when you change the subroutine, all of the sheets will pickup the same modification.
Instead of using the Worksheet events, use their corresponding Workbook events: Workbook.SheetSelectionChange and Workbook.SheetChange. These fire whenever any worksheet has a selection change or cell change.
Add these to the ThisWorkbook code module.
Dim PreVal
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Address = "$D$1" Or Target.Address = "$D$2" Then
PreVal = Target.Value
End If
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo SafeExit
Application.EnableEvents = False
If Target.Address = "$D$1" Or Target.Address = "$D$2" Then
If Target.Value <> PreVal Then
SomethingSomewhere = Value
PreVal = Target.Value
End If
End If
SafeExit:
Application.EnableEvents = True
End Sub
You can modify these to ignore the logging page by checking Sh.Name, for example.

How do I fix non target cells from activating the sub Worksheet_Change(ByVal Target As Range)

My spread sheet has target cells and cells that I want to be able to enter manual data without the Worksheet Change to activate or run. How do I allow these open user cells to be populated without the private sub running??
More information sample code. There are many code sections like this in the same format.
Private sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = True
If Intersect(Target, Range("$B$8:$k$9")) Is Nothing Then
GoTo NEXT10
'Application.EnableEvents = False
End If
Application.EnableEvents = True
MsgBox Target.Address
'-------------------------------------------------------------------
'Application.EnableEvents = True
Application.EnableEvents = False
If Target.Address = "$B$8" Then
If Target.Value >= 0 Then
Range("B9") = Range("B8").Value * 42
End If
ElseIf Target.Address = "$B$9" Then
Range("B8") = Range("B9").Value / 42
End If
Application.EnableEvents = True
End Sub
The problem is if I enter, delete value or text in any empty cells on the worksheet, it activates the Worksheet_Change (ByVal Target ....).I use the If Intersect(Target,Range($B8$:$k$8) Is Nothing to bypass the target if no change. This format is used for other target ranges of important. But I do not understand why when any cell is changed the program runs?? Can this be avoid so various manual entries can be performed? For example text notes, labels, etc.
The Next10 is the start of another section of code but with diferent target address. If the target addess indicated is not intersected, it goes the check the next intersection.

Hide commandbutton based on cell value excel vba

I am trying to hide a commandbutton based on a specific cell value. I have looked up several codes and pasted them in excel (in the vba form when right clicking the sheet and selecting "view code").
What am I doing wrong?
Here's one of the codes I've tried:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("A1") = 0 Then ActiveSheet.CommandButton1.Visible = False
If Range("A1") = 1 Then ActiveSheet.CommandButton1.Visible = True
End Sub
Make sure you enable events before using your code. Also, you must place your code in Worksheet module, not in regular module. To enable events, use this simple sub.
Sub Enable_events()
Application.EnableEvents = True
End Sub
please run this first:
Sub enable_()
Application.EnableEvents = True
End Sub
and then your Code will run perfectly:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("A1") = 0 Then ActiveSheet.CommandButton1.Visible = False
If Range("A1") = 1 Then ActiveSheet.CommandButton1.Visible = True
End Sub
Your code is confusing, for a number of reasons.
Range, when it's not qualified with a Worksheet object, implicitly refers to the ActiveSheet, i.e. ActiveSheet.Range... but when it's in a worksheet's code-behind, it implicitly refers to that worksheet's Range property, i.e. Me.Range. Because the meaning of an unqualified Range call depends on context, it's best to always qualify it with an explicit Worksheet object.
So if you're in the code-behind module for Sheet1, then Range("A1") is equivalent to Sheet1.Range("A1"), or even better, Me.Range("A1").
The two conditions will be evaluated every time, but only one of them needs to be: it's inefficient.
Truth is, you don't need to assign a Boolean literal - a Boolean expression is much cleaner.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Me.CommandButton1.Visible = (Me.Range("A1") = 1)
End Sub
Now, assuming Application.EnableEvents returns True, that code will run every time the selection changes, which is rather overkill.
Handle the Worksheet.Change event instead, and only act when the modified cell is A1:
Private Sub Worksheet_Change(ByVal Target As Range)
If Application.Intersect(Target, Me.Range("A1")) Is Nothing And Target.Count <> 1 Then
' we don't care about that cell: bail out
Exit Sub
End If
Me.CommandButton1.Visible = (Me.Range("A1") = 1)
End Sub
Please try this code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1")) Is Nothing Then
If Selection.Cells.Count = 1 Then
If Range("A1") = 0 Then ActiveSheet.CommandButton1.Visible = False
If Range("A1") = 1 Then ActiveSheet.CommandButton1.Visible = True
End If
End If
End Sub
Hope this help.

Resources