vba Change event when data validation selected - excel

Hi I have a workbook that in Column C there is data validation drop down list. I'm tryinto code so that when a specific status is selected in the drown down (i.e. "Verification") Column I will automatically enter "Verification Unprocessed". Column I also has data validation and a drop down list. I've searched all over and can't seem to find a code that identifies a worksheet change event from a data validation drop down list. Thanks!

You fact that you have a drop-down list is not important. The Worksheet Change event will fire regardless of how the cell is changed. All you need to do is check if the Target variable in the event is in the right column, then do what you need to do. Sample code:
Private Sub Worksheet_Change(ByVal Target As Range)
With Target
If .Count = 1 Then
If .Row > 1 And .Column = 3 Then
If .Value = "specific status" Then
.Offset(0, 6).Value = "Verification Unprocessed"
Else
.Offset(0, 6).ClearContents
End If
ElseIf .Column = 5 Then
If .Value = Date Then
Call Lilly
End If
End If
End If
End With
End Sub
Let me know if you need further information.
EDIT: Incorperated your original code.

Related

VBA - Exiting out of MsgBox() [duplicate]

This question already has answers here:
Why MS Excel crashes and closes during Worksheet_Change Sub procedure?
(3 answers)
Closed 1 year ago.
I haven't worked with VBA for a while, so my skills are a bit rusty. I've managed to put together a small script that will update the Date Contacted and Date Modified column I have in my excel sheet If I were to change the respective cell in column A. For all cells in column A, I set up a List by using the Data Validation tool. List = A, B, C, D.
The script should input the current date in Date Contacted (column H) when one of the list items is selected. If the cell is changed to a new item a message box will ask if the user wants to commit the changes. If yes, the Date Modified (column I) will be updated. If no, Column A should revert back to it's original self and neither one of the Date columns should be updated.
There are no bugs in the code, but when prompted to answer yes or no, clicking "no" continues to loop back to the message box. I am stuck in the loop and unsure how to escape.
Private Sub Worksheet_Change(ByVal Target As Range)
' Auto Date
Dim Cell As Range
Dim Answer As Integer
For Each Cell In Target
If Cell.Column = Range("A:A").Column Then
If Cells(Cell.Row, "H").Value <> "" And Cell.Value <> "" Then
Answer = MsgBox("Are you sure you want to make these changes?", vbYesNo)
If Answer = vbYes Then
Cells(Cell.Row, "I").Value = Int(Now)
Else
Application.Undo
End If
Else
Cells(Cell.Row, "H").Value = Int(Now)
End If
End If
Next Cell
End Sub
You need to turn off events before making any changes to the worksheet via the macro. Changes trigger the event and when your event makes changes, it re-triggers the event resulting in a loop, or in your case, a conditional loop.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
'Any code that makes changes to worksheet nested inside
Application.EnableEvents = True
End Sub

Userform and Selecting Cell values

Just playing around with userform. Pretty new to using them . Created a pretty simple userform that find me the percentage change between two values that I enter. (see image below). I'm just interested in going one step further, I want to know how to enter the values based on excel cells that I select. So in this example, if I select K6, the value 15 enters in current year and if I subsequently click on K8, the value 10 enters in base year). Hope that makes sense, let me know if that is possible. Thanks.
current code....
TextBox3_Change()
TextBox3.Value = Format((Val(TextBox1.Value) - Val(TextBox2.Value)) / Val(TextBox2.Value), "#0.00%")
Rather than clicking, why not load the values in those textboxes in the UserForm_Initialize() event? Something like
Private Sub UserForm_Initialize()
TextBox1.Value = Sheets("Sheet1").Range("K6").Value2
End Sub
If you really want to select a cell (after the userform is shown) and then populate the textboxes, then yes that is also possible. Here is an example
For demonstration purpose, I am going to populate 1 textbox. Let's say our userform looks like this. Note, I added a CommandButton1 next to the textbox. I changed the caption to .... We will use Application.InputBox with Type:=8 so that user can select a range.
Next paste this code in the userform code area
Option Explicit
Private Sub CommandButton1_Click()
Dim rng As Range
On Error Resume Next
'~~> Prompt user to select range
Set rng = Application.InputBox(Prompt:="Select the range", Type:=8)
On Error GoTo 0
'~~> Check if the user selected a range
If Not rng Is Nothing Then
'~~> Check if the range is single cell or not
If rng.Columns.Count > 1 Or rng.Rows.Count > 1 Then
MsgBox "Select single cell"
Exit Sub
End If
TextBox1.Text = rng.Value2
End If
End Sub
Demonstration
This isn't a built-in functionality for userforms (unlock the create a graph dialogue box).
One option would be to have the user start by selecting two cells, and then your code runs and calculates the percentage change in those two cells selected and returns the answer in a pop-up. Another option would be to have the userform automatically populate from preselected cells in your workbook (example below).
Private Sub UserForm_Activate()
Dim ActiveR As Long
ActiveR = ActiveCell.Row
TextBox1.Value = Cells(ActiveR, 1).Value
TextBox2.Value = Cells(ActiveR, 2).Value
TextBox3.Value = Cells(ActiveR, 3).Value
TextBox4.Value = Cells(ActiveR, 4).Value
End Sub

Populate textboxes based on Combobox value

I am trying to populate a textbox based on the selection i made on the combobox. It would basically look up the combobox value and return the assigned value from the column (the 3rd) I chose. I have some code done but it returns a type mismatch error
Private Sub UserForm_Initialize()
ComboBox1.List = Sheets(1).Range("C15:C39").Value
End Sub
Private Sub ComboBox1_Change()
TextBox1.Text = Application.VLookup(ComboBox1.Value, Worksheets("sheet1").Range("A15:K39"), 3, False)
End Sub
Can anyone let me know what's wrong and if there is a better way to go about this?
Assuming your combo is not multiselect then load it with all of your range and just show the columns you are interested in. Make the number of columns in the ComboBox the same number of columns in your range.
ComboBox1.List = Sheets(1).Range("A15:K39").Value
ComboBox1.ColumnCount=11
ComboBox.ColumnWidths="0,0,100,0,0,0,0,0,0,0,0"
TextBox1.Value=ComboBox1.List(ComboBox.ListIndex,2) 'the columns are zero-based
Try maybe this:
TextBox1.Text = Application.WorksheetFunction.VLookup(ComboBox1.List(ComboBox1.ListIndex, 0), Range("C15:K39"), 1, False)
Thank you guys,
I ended up going with this
Private Sub ComboBox1_Change()
Dim myRange As Range, f As Range
Set myRange = Worksheets("Sheet2").Range("A2:B26")
Set f = myRange.Find(What:=ComboBox1.Value, LookIn:=xlValues, Lookat:=xlWhole, MatchCase:=False) '<--| try and find combobox selected value
If f Is Nothing Then
TextBox1.Value = ""
Else '<--| ... otherwise...
TextBox1.Value = f.Offset(, 1)
TextBox2.Value = f.Offset(, 2)
TextBox3.Value = f.Offset(, 3)
End If
End Sub
I had 3 textboxes that i populated with three different columns once an option is chosen from the Combobox.
What i am trying to do is have two last textboxes that I would eventually write numbers in and that would automatically update the corresponding cells.
The Problem I face is updating the cell that relates to the value entered on the combobox.
The code below is very rudimentary and i am wondering if i should do the same manually. First part of the code populates three first textboxes, second part is supposed to populate corresponding cells with value I enter depending on the combobox selection. Please let me know if i am not clear enough.
Private Sub OK_Click()
Sheets("Sheet1").Range("C9") = TextBox4.value
Sheets("Sheet1").Range("D9") = TextBox5.value
End Sub

Combining 2 vba codes over 2 different ranges into one statement

I can make one or the other of the below codes work, but need them both. The first locks cells in range upon data entry, the second inserts a date stamp when the final data entry in column D of each row is completed.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim xRg As Range
On Error Resume Next
Set xRg = Intersect(Range("A8:D5005"), Target)
If xRg Is Nothing Then Exit Sub
Target.Worksheet.Unprotect Password:="Midnight"
xRg.Locked = True
Target.Worksheet.Protect Password:="Midnight"
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Set rng = Range("D8:D5005")
If Not Intersect(Target, rng) Is Nothing Then
Target.Offset(0, 1) = Now
Target.Offset.NumberFormat = "dd/mm/yyyy hh:mm:ss"
End If
End Sub
I'm still guessing a bit exactly what you're trying to do … but here is way to allow your users enter four data points ... and then to press button to add the data points to a protected list … and includes a time stamp.
First setup 4 data entry cells in A4 through to D4 by using the Format Cell option, make sure for these cells that Locked is unchecked on the Protection tab.
Next create a button and link the button to the following code:
Sub ButtonCode()
ActiveSheet.Unprotect Password:="A"
Range("A7:E7").Insert xlShiftDown
Range("A4:D4").Copy Range("A7:D7")
Range("E7") = Now()
Range("A7:E7").Interior.Color = rgbLightBlue
Range("A7:E7").Font.Color = rgbBlack
ActiveSheet.Protect Password:="A"
End Sub
As a once only step, protect the worksheet; my example consistently uses a password of "A". Note that your users will not need to enter the password at any time.
Once the sheet is setup, when the button is clicked, the code unlocks the sheet (allowing it to make edits), it move the existing data data down, copy the new data points to the top of the list, adds timestamp and some minimal formatting. It then re-enables protection so that the user can't overwrite the existing entries.
The screenshot below gives you an idea of what it might look like, including showing that A4:D4 need to be unlocked.
Maybe not the implementation direction you were thinking of … but the principles included in this example might work for you. All the best.
I'm not 100% sure of the structure of your worksheet, so here are the assumptions for my response. You only want the user to modify cells in the range "A8:D5005" … and somewhere on the sheet you want to record date/timestamp changes for cells changed.
So I would start by protecting the sheet by going to the Excel "Review" ribbon (not in VBA), and setting up an editable range as follows.
Before you close the dialog box, click on Protect Sheet so that the rest of the sheet is password protected.
Once you've done this … you can use something like the code below to record the date/timestamps. In this example … I record them in columns to the right of your editable range (given your editable data is only to Column D).
Private Sub Worksheet_Change(ByVal Target As Range)
Dim vIntersect As Variant
Set vIntersect = Application.Intersect(Target, Range("A8:D5005"))
If Not vIntersect Is Nothing Then
Application.EnableEvents = False
Target.Worksheet.Unprotect Password:="Midnight"
Target.Offset(0, 5) = Now
Target.Offset(0, 5).NumberFormat = "dd/mm/yyyy hh:mm:ss"
Target.Worksheet.Protect Password:="Midnight"
Application.EnableEvents = True
End If
End Sub

Automatically Fetch Current Time in Excel

I am trying to build out a task tracker for my job that aggregates the amount of time I spend on various assignments.
Example rows of task tracker
Currently I am entering the start and finish times for each task manually with Ctrl + ;, Space, Ctrl + Shift +;. What I would like to do, if possible, is to have the start time column populate with the current time at whatever moment I set the drop down option to "Work in Progress," and then the end time column to do the same for whatever moment I change it to "Closed."
Drop Down Menu
Any ideas?
If the Drop Down is a Form Control (as opposed to an ActiveX control) then you could right-click it and choose Assign Macro.
It should default to something like DropDown1_Change, and you can click New.
Then paste in code "something like" this:
Sub DropDown1_Change()
If Range("A4") = 1 Then Range("A1") = Now()
End Sub
The first & last lines should already be populated for you.
You'd need to adjust the code to your needs. In this example:
The Drop Down is named Drop Down 1.
Cell A4 is the Cell Link for my Drop Down.
Cell A1 is the cell I want the date in.
I want to run the code when item # 1 is selected from the Drop Down's Input Range.
If your control happens to be an ActiveX DropDown/ComboBox, the steps are similar:
Right click the control and choose View Code.
You'll be taken immediately to the VBA Editor.
Paste the code.
The only way to do this, is using macro's.
In VBA (Excel -> Alt+F11) you can handle create events to handle things like cell changes.
The double click on the sheet you're entering your task tracker data and add the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
End Sub
Now you can use the Target parameter to detect the cell which has been changed and then modify some other cell based on the changes cell.
So let's assume you have the dropdown in colum '4' and the begin and end time in column '5' and '6'. Then using the code below will update the begin and endtime field based on what state the taks has:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 4 Then
If Target.Value = "Work in Progress" Then
Me.Cells(Target.Row, 5).Value = Time
ElseIf Target.Value = "Closed" Then
Me.Cells(Target.Row, 6).Value = Time
End If
End If
End Sub
NOTE
You need to create an Excel workbook with macro's which require you to enable them - by default Excel disables macro's - so take note on enabling them when asked.
Try this code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim FirstRow, StatusColumn, CurrentRow, CurrentColumn As Double
FirstRow = 5 'Define here the first row number of data
StatusColumn = 5 'Define here the column number of Status
CurrentRow = Target.Row
CurrentColumn = Target.Column
If CurrentColumn = StatusColumn And CurrentRow >= FirstRow Then
Select Case CStr(Target.Value)
Case "Work In Progress":
Cells(CurrentRow, CurrentColumn + 2) = Format(Now, "MM.dd.yy hh:mm")
Cells(CurrentRow, CurrentColumn + 3) = ""
Case "Closed":
Cells(CurrentRow, CurrentColumn + 3) = Format(Now, "MM.dd.yy hh:mm")
Case Else:
'Some code here...
End Select
End If
End Sub

Resources