Avoid dependant event trigger each other - excel

I have a Worksheet_change in which two events are checked (edits on cells of column C and edits on cells of column D). The problem is that an edit on column C's cells modify the value of column D's cells (and viceversa), so the Worksheet_change is triggered repeatedly and excel eventually crashes.
How can I avoid the problem but maintaining my functionality?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rgFound As Range
Dim defVal As Range
Dim currParam As Range
Dim currParamDict As Range
Set targ = Intersect(Target, Range("A:A"))
If Not targ Is Nothing Then
With Worksheets("FT_CASE_xx")
For Each defVal In .Range("A2", .Range("A" & Rows.Count).End(xlUp)).Offset(, 1)
Set currParam = defVal.Offset(, -1)
Dim xlFirstChar As String
xlFirstChar = Left$(currParam, 1)
If xlFirstChar = "B" Then
Set rgFound = Worksheets("DEF_BOOLEAN").Range("A:A").Find(currParam.value)
defVal.Offset(, 1).Interior.Color = RGB(230, 230, 230)
defVal.Offset(, 1).Locked = True
defVal.Offset(, 2).Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="TRUE,FALSE"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Else
Set rgFound = Worksheets("DEF_FLOAT").Range("A:A").Find(currParam.value)
defVal.Offset(, 1).Interior.ColorIndex = 0
defVal.Offset(, 1).Locked = False
defVal.Offset(, 2).Locked = False
defVal.Offset(, 1).NumberFormat = "0.000"
defVal.Offset(, 2).NumberFormat = "0.000"
defVal.Offset(, 3).NumberFormat = "0.000"
End If
If rgFound Is Nothing Then
Debug.Print "Name was not found."
Else
If xlFirstChar = "B" Then
Set currParamDict = rgFound.Offset(, 3)
Else
Set currParamDict = rgFound.Offset(, 5)
End If
defVal.value = currParamDict.value
End If
Next defVal
End With
Else
Set targ = Intersect(Target, Range("C:C"))
If Not targ Is Nothing Then
Dim coeffVal As Range
Dim currVal As Range
Dim RequestedVal As Range
With Worksheets("FT_CASE_xx")
For Each coeffVal In .Range("C2", .Range("C" & Rows.Count).End(xlUp))
Set currVal = coeffVal.Offset(, -1)
Set RequestedVal = coeffVal.Offset(, 1)
Set ParamName = coeffVal.Offset(, -2)
Dim xlFirstChar2 As String
xlFirstChar2 = Left$(ParamName, 1)
If ((xlFirstChar2 = "F") And (IsEmpty(coeffVal.value) = False)) Then
RequestedVal.value = coeffVal.value * currVal.value
End If
Next coeffVal
End With
Else
Set targ = Intersect(Target, Range("D:D"))
If Not targ Is Nothing Then
Dim coeffsVal As Range
Dim val As Range
Dim reqVal As Range
Dim Parameter As Range
With Worksheets("FT_CASE_xx")
For Each reqVal In .Range("D2", .Range("D" & Rows.Count).End(xlUp))
Set coeffsVal = reqVal.Offset(, -1)
Set val = reqVal.Offset(, -2)
Set Parameter = reqVal.Offset(, -3)
Dim xlFirstChar3 As String
xlFirstChar3 = Left$(Parameter, 1)
If ((xlFirstChar3 = "F") And (IsEmpty(reqVal.value) = False)) Then
If val.value = 0 Then
coeffsVal.value = reqVal.value
Else
coeffsVal.value = reqVal.value / val.value
End If
End If
Next reqVal
End With
Else
Exit Sub
End If
End If
End If
End Sub
Maybe a different management of target intersection? How?

My favoured method (which can also be useful in other situations) is to create a variable at global or module level (as required) then check this on each run of the code
Private disableEvents as Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
If disableEvents Then Exit Sub
disableEvents=True
<code here>
disableEvents=False
End sub

Related

Find any part of a text string of keywords separated by spaces

I'm trying to match any part of a text string of keywords to text in the Target cell.
If it is a text value, of a single keyword, like "wal" for Wal-mart, then this code finds the text string in the Target, i.e. " WAL-MART SUPERCENTER ".
When I have "wal otherstore" in the keywords cell it doesn't find Wal-mart anymore. I thought that is what xlPart was supposed to do.
Set Found = Target.Find(What:=Cell, LookIn:=xlValues, LookAt:=xlPart, MatchCase:=False)
The idea is to have a list of accounts in a budget spreadsheet with associated keywords, so that the macro then finds keywords, like "wal" and assigns the Target entry to that account.
The keywords are all in a single cell next to the accounts list. The keywords are separated by a space.
Full code:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, Cell As Range, Found As Range
Dim List As String
Dim Qty As Integer
Dim Coll As Collection
Dim i As Long
LastRowA = Sheets("Transactions").Cells(Rows.Count, "A").End(xlUp).Row
LastRowL = Sheets("Transactions").Cells(Rows.Count, "L").End(xlUp).Row
List = "Reset Options"
Qty = 0
Set Coll = New Collection
Set Rng1 = Sheets("Transactions").Range("G3:G" & LastRowA)
Set Rng2 = Sheets("Accounts & Budget").Range("I5:I104")
Set Rng3 = Sheets("Transactions").Range("L3:L" & LastRowL)
If Application.Intersect(Target, Rng1) Is Nothing Then
ElseIf Application.Intersect(Target, Rng1).Address = Target.Address Then
If Target = "" Then
Application.EnableEvents = False
Target.Offset(0, 5).Validation.Delete
Cells(Target.Row, "G") = ""
Cells(Target.Row, "L") = ""
Application.EnableEvents = True
ElseIf Target <> "" Then
For Each Cell In Rng2
Set Found = Target.Find(What:=Cell, LookIn:=xlValues, LookAt:=xlPart, MatchCase:=False)
If Found Is Nothing Then
Else
Qty = Qty + 1
Coll.Add Cell.Offset(0, -2)
End If
Next Cell
If Qty = 1 And Coll.Count = 1 Then
Application.EnableEvents = False
Target.Offset(0, 5).Validation.Delete
Target.Offset(0, 5) = Coll(1)
Target.Offset(0, 5).Validation.Add Type:=xlValidateList, Operator:=xlBetween, Formula1:="=Accounts"
Application.EnableEvents = True
ElseIf Qty = 0 And Coll.Count = 0 Then
Application.EnableEvents = False
Target.Offset(0, 5).Validation.Delete
Target.Offset(0, 5) = "No Results - Select From List"
Target.Offset(0, 5).Validation.Add Type:=xlValidateList, Operator:=xlBetween, Formula1:="=Accounts"
Application.EnableEvents = True
ElseIf Qty > 1 And Coll.Count > 1 Then
Application.EnableEvents = False
Target.Offset(0, 5).Validation.Delete
Target.Offset(0, 5) = "Multiple Results - Select From List"
For i = 1 To Coll.Count
List = List & "," & Coll(i)
Next i
Target.Offset(0, 5).Validation.Add Type:=xlValidateList, Operator:=xlBetween, Formula1:=List
Application.EnableEvents = True
End If
End If
End If
If Application.Intersect(Target, Rng3) Is Nothing Then
ElseIf Application.Intersect(Target, Rng3).Address = Target.Address Then
If Target = "Reset Options" Or Target = "" Then
Application.EnableEvents = False
Target.Validation.Delete
Target.Validation.Add Type:=xlValidateList, Operator:=xlBetween, Formula1:="=Accounts"
Application.EnableEvents = True
Target = "Select From List"
ElseIf Target.Offset(0, -5) = "" Then
Application.EnableEvents = False
Target.Validation.Delete
Target = ""
Application.EnableEvents = True
End If
End If
Application.ScreenUpdating = True
End Sub

Dynamically Hide/Unhide Multiple Ranges Using VBA With Minimal Lag

I am trying to dynamically hide or unhide rows in a worksheet based off of selections within dropdown menus.
The script that I have works with smaller data sets, but because I have 35 different ranges of 26 rows each this slows down really quickly.
I have seen several solutions offered to similar question here, but I have been unable to get them to work.
I want to collect the value in cells B15 down to B41 and hide any rows that have a blank value, then repeat for the remaining 34 ranges.
Each of the cells in the range above have a formula that can return a "" value (which are the rows I want to hide).
Private Sub Worksheet_Change(ByVal Target As Range)
'Turns off worksheet protection to allow for hiding and unhiding of rows
ActiveSheet.Unprotect "xxxx"
'Turns off screen updating and animations while hiding and unhiding rows
Application.EnableAnimations = False
Application.ScreenUpdating = False
Hide1
Hide2
Hide3
Hide4
Hide5
Hide6
Hide7
Hide8
Hide9
Hide10
Hide11
Hide12
Hide13
Hide14
Hide15
Application.ScreenUpdating = True
Application.EnableAnimations = True
ActiveSheet.Protect "xxxx"
End Sub
Sub Hide1()
Application.EnableEvents = False
Application.EnableAnimations = False
Application.ScreenUpdating = False
'Run #1
If Range("B15").Value = "" Then
Rows(15).EntireRow.Hidden = True
Else
Rows(15).EntireRow.Hidden = False
End If
If Range("B16").Value = "" Then
Rows(16).EntireRow.Hidden = True
Else
Rows(16).EntireRow.Hidden = False
End If
If Range("B17").Value = "" Then
Rows(17).EntireRow.Hidden = True
Else
Rows(17).EntireRow.Hidden = False
End If
If Range("B18").Value = "" Then
Rows(18).EntireRow.Hidden = True
Else
Rows(18).EntireRow.Hidden = False
End If
If Range("B19").Value = "" Then
Rows(19).EntireRow.Hidden = True
Else
Rows(19).EntireRow.Hidden = False
End If
If Range("B20").Value = "" Then
Rows(20).EntireRow.Hidden = True
Else
Rows(20).EntireRow.Hidden = False
End If
If Range("B21").Value = "" Then
Rows(21).EntireRow.Hidden = True
Else
Rows(21).EntireRow.Hidden = False
End If
If Range("B22").Value = "" Then
Rows(22).EntireRow.Hidden = True
Else
Rows(22).EntireRow.Hidden = False
End If
If Range("B23").Value = "" Then
Rows(23).EntireRow.Hidden = True
Else
Rows(23).EntireRow.Hidden = False
End If
If Range("B24").Value = "" Then
Rows(24).EntireRow.Hidden = True
Else
Rows(24).EntireRow.Hidden = False
End If
If Range("B25").Value = "" Then
Rows(25).EntireRow.Hidden = True
Else
Rows(25).EntireRow.Hidden = False
End If
If Range("B26").Value = "" Then
Rows(26).EntireRow.Hidden = True
Else
Rows(26).EntireRow.Hidden = False
End If
If Range("B27").Value = "" Then
Rows(27).EntireRow.Hidden = True
Else
Rows(27).EntireRow.Hidden = False
End If
If Range("B28").Value = "" Then
Rows(28).EntireRow.Hidden = True
Else
Rows(28).EntireRow.Hidden = False
End If
If Range("B29").Value = "" Then
Rows(29).EntireRow.Hidden = True
Else
Rows(29).EntireRow.Hidden = False
End If
If Range("B30").Value = "" Then
Rows(30).EntireRow.Hidden = True
Else
Rows(30).EntireRow.Hidden = False
End If
If Range("B31").Value = "" Then
Rows(31).EntireRow.Hidden = True
Else
Rows(31).EntireRow.Hidden = False
End If
Application.EnableEvents = True
Application.EnableAnimations = True
Application.ScreenUpdating = True
End Sub
Please, try the next code. As it is set, it will hide all rows having empty values returned by a formula. firstRand lastR can be chosen to process a specific number of rows:
Sub Hide1()
Dim sh As Worksheet, lastR As Long, firstR As Long
Dim rng As Range, rngH As Range, arr, i As Long
Set sh = ActiveSheet 'use here the sheet you need
lastR = sh.Range("B" & sh.rows.Count).End(xlUp).row 'last row on B:B
firstR = 15 'first row of the range to be processed
Set rng = sh.Range("B" & firstR & ":B" & lastR)
rng.EntireRow.Hidden = False 'show all rows in the range
arr = rng.Value 'place the range in an array for faster iteration
For i = 1 To UBound(arr)
If arr(i, 1) = "" Then
If rngH Is Nothing Then 'set the range to keep the cells where the rows must be hidden
Set rngH = rng.cells(i, 1)
Else
Set rngH = Union(rngH, rng.cells(i, 1))
End If
End If
Next
'hide the rows at once:
If Not rngH Is Nothing Then rngH.EntireRow.Hidden = True
End Sub
Hide Blank Rows
Adjust the values in the constants section.
Option Explicit
Sub HideBlankRows()
Const fCellAddress As String = "B16"
Const crgCount As Long = 35
Const crgSize As Long = 16 ' maybe 26 ?
Const crgGap As Long = 5
Dim ws As Worksheet: Set ws = ActiveSheet
Dim crg As Range: Set crg = ws.Range(fCellAddress).Resize(crgSize)
Dim crgOffset As Long: crgOffset = crgSize + crgGap
Dim rg As Range: Set rg = crg
Dim n As Long
For n = 2 To crgCount
Set crg = crg.Offset(crgOffset)
Set rg = Union(rg, crg)
Next n
Dim drg As Range
Dim cCell As Range
For Each cCell In rg.Cells
If Len(CStr(cCell.Value)) = 0 Then
If drg Is Nothing Then
Set drg = cCell
Else
Set drg = Union(drg, cCell)
End If
End If
Next cCell
If drg Is Nothing Then Exit Sub
rg.EntireRow.Hidden = False
drg.EntireRow.Hidden = True
End Sub

Remove Duplicates and make unique list

The Fruits contains list - Apple,Banana,Orange
and
Colors contains list - Red,Black,Orange
so when I multi select the Fruits as well as Colors from drop-down list from cell "G1". Then the "Offset(0, -1)" means "F1" shows me the combine output list as - (Apple, Banana, Orange, Red, Black, Orange).
So, The list in cell "F1" contains duplicate value Orange and it prints 2 times.
It should pick up only unique items from the selected one and remove the duplicate one and should print in cell F1 as - (Apple, Banana, Orange, Red, Black).
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range, oldVal As String, newVal As String
Dim arr As Variant, El As Variant
If Target.count > 1 Then GoTo exitHandler
If Target.value = "" Then
Application.EnableEvents = False
Target.Offset(0, -1).value = ""
Application.EnableEvents = True
Exit Sub
End If
On Error Resume Next
Set rngDV = cells.SpecialCells(xlCellTypeAllValidation)
On Error GoTo exitHandler
If rngDV Is Nothing Then GoTo exitHandler
If Not Intersect(Target, rngDV) Is Nothing Then
Application.EnableEvents = False
newVal = Target.value: Application.Undo
oldVal = Target.value: Target.value = newVal
If Target.Column = 7 Then
If oldVal <> "" Then
If newVal <> "" Then
arr = Split(oldVal, ",")
For Each El In arr
If El = newVal Then
Target.value = oldVal
GoTo exitHandler
End If
Next
Target.value = oldVal & "," & newVal
Target.EntireColumn.AutoFit
End If
End If
End If
writeSeparatedStringLast Target
End If
exitHandler:
Application.EnableEvents = True
End Sub
Sub writeSeparatedStringLast(rng As Range)
Dim arr As Variant, arrFin As Variant, El As Variant, k As Long, listBox As MSForms.listBox
Dim arrFr As Variant, arrVeg As Variant, arrAnim As Variant, El1 As Variant
Dim strFin As String ', rng2 as range
arrFr = Split("Apple,Banana,Orange", ",")
arrVeg = Split("Onion,Tomato,Cucumber", ",")
arrAnim = Split("Red,Black,Orange", ",")
arr = Split(rng.value, ",")
For Each El In arr
Select Case El
Case "Fruits"
arrFin = arrFr
Case "Vegetables"
arrFin = arrVeg
Case "Colors"
arrFin = arrAnim
End Select
For Each El1 In arrFin
strFin = strFin & El1 & ", "
Next
Next
strFin = left(strFin, Len(strFin) - 1)
With rng.Offset(0, -1)
.value = strFin
.WrapText = True
.Select
End With
End Sub
'Firstly run the next Sub, in order to create a list validation in range "G1":
Sub CreateValidationBis()
Dim sh As Worksheet, rng As Range
Set sh = ActiveSheet
Set rng = sh.Range("G1")
With rng.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="Fruits,Vegetables,Colors"
.IgnoreBlank = True
.InCellDropdown = True
.ShowInput = True
.ShowError = True
End With
End Sub
Is this code will fit to remove the duplicates from output arrays and give me the unique value.
Public Function RemoveDuplicateWords(InputString As String) As String
Dim InputArray() As String
InputArray = Split(InputString, " ")
Dim DictUnique As Object
Set DictUnique = CreateObject("Scripting.Dictionary")
Dim OutputString As String
Dim Word As Variant
For Each Word In InputArray
If Not DictUnique.Exists(Word) Then
DictUnique.Add Word, 1
OutputString = OutputString & " " & Word
End If
Next Word
RemoveDuplicateWords = Trim$(OutputString)
End Function

Hide/Unhide Excel Sheets based on multiple cell values

I have an Excel workbook which contains multiple sheets. I want to hide/unhide sheets based on cell values in Main sheet cells B3:B8. Values in Main sheet are changed by the user from pre-defined list.
Eg. If "A" exists in the "Config" column, then unhide sheet "A" in my workbook.
At the moment I have following code, which works, but looks
clunky, Excel flickers as the code runs every time a value is changed in "Config" column:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
Sheets("A").Visible = False
Sheets("B").Visible = False
Sheets("C").Visible = False
Sheets("D").Visible = False
For i = 3 To 8
If InStr(1, Cells(i, 2), "A") Then
Sheets("A").Visible = True
ElseIf InStr(1, Cells(i, 2), "B") Then
Sheets("B").Visible = True
ElseIf InStr(1, Cells(i, 2), "C") Then
Sheets("C").Visible = True
ElseIf InStr(1, Cells(i, 2), "D") Then
Sheets("D").Visible = True
End If
Next i
End Sub
I also tried to run this macro from a button, but it stops with first TRUE value (a sheet becomes unhidden).
I would use this method:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
Sheets("A").Visible = xlSheetHidden
Sheets("B").Visible = xlSheetHidden
Sheets("C").Visible = xlSheetHidden
Sheets("D").Visible = xlSheetHidden
Application.ScreenUpdating = False
For i = 3 To 8
If InStr(1, Cells(i, 2), "A") Then Sheets("A").Visible = xlSheetVisible
If InStr(1, Cells(i, 2), "B") Then Sheets("B").Visible = xlSheetVisible
If InStr(1, Cells(i, 2), "C") Then Sheets("C").Visible = xlSheetVisible
If InStr(1, Cells(i, 2), "D") Then Sheets("D").Visible = xlSheetVisible
Next i
Application.ScreenUpdating = True
End Sub
Another way to do this would be:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RNG As Range, CL As Range
Dim WS As Worksheet
Application.ScreenUpdating = False
Set RNG = Sheets("Main").Range("B3:B8")
If Not Intersect(Target, RNG) Is Nothing Then
Application.ScreenUpdating = False
For Each WS In ThisWorkbook.Worksheets
If WS.Name <> "Main" Then
With RNG
Set CL = .Find(What:=WS.Name, LookIn:=xlValues, LookAt:=xlWhole)
If Not CL Is Nothing Then
WS.Visible = xlSheetVisible
Else
WS.Visible = xlSheetHidden
End If
End With
End If
Next WS
End If
Application.ScreenUpdating = True
End Sub
More versatile and more dynamic
EDIT: To also check if Target intersects with your lookup range to prevent triggering macro unwanted.
To help optimize the running and have it look better use Application.ScreenUpdating. It will reduce the flickering by not trying to repaint the scrren until the Sub has finished running. If the rest of the program runs with no issue it should be all you need
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
Sheets("A").Visible = False
Sheets("B").Visible = False
Sheets("C").Visible = False
Sheets("D").Visible = False
For i = 3 To 8
If InStr(1, Cells(i, 2), "A") Then
Application.ScreenUpdating = False
Sheets("A").Visible = True
ElseIf InStr(1, Cells(i, 2), "B") Then
Application.ScreenUpdating = False
Sheets("B").Visible = True
ElseIf InStr(1, Cells(i, 2), "C") Then
Application.ScreenUpdating = False
Sheets("C").Visible = True
Application.ScreenUpdating = False
ElseIf InStr(1, Cells(i, 2), "D") Then
Sheets("D").Visible = True
End If
Next i
Application.sScreenUpdating = True
End Sub
I also agree with 's comment. Ifs would be better. ElseIf assumes only one condition is the correct one when there could be multiple iterations.
edit:
Also a though: It looks like the way its set up you intend that any value between B3:B8 that has an "A" will show page "A". If you dedicate it differently B3 = "A" , B4="B" etc and so on, you can change the conditionals to If Target.Address = "$B$3" Then and have B# be the on/off to sheet"A" with any non-empty value.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
If Target.Address = "$B$3" Then
If IsEmpty(Sheet1.Range("B3")) = False Then
Sheets("A").Visible = True
Else
Sheets("A").Visible = False
End If
End If
''etc etc and so on
Application.ScreenUpdating = True
End Sub

Column looping in Worksheet Change Event

I am a beginner with VBA and would like to know how loop columns in worksheet event. Below are the scenario.
I want to populate the data validation and "Fill this cell" comment not just in row when I select the trigger cell (target). Below is the code I tried to update but really hopeless on making it work.
Thank you so much for all your help.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Dim cel As Range
Dim myRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
'This subroutine fires when a cell value changes in this worksheet.
Set KeyCells = Range("A5:A8")
'did someone change something specifically in cell A5?
If Not Intersect(Target, KeyCells) Is Nothing Then
For Each cel In Target.Rows ' do the next steps for each cell that was changed
myRow = cel.Row
'Is the value A or C?
If Target.Value = "A" Or Target.Value = "C" Then
For Each col In Target.Columns '---I added this but not working,
myCol = col.Columns.Offset(3)
ws.Range("C" & myCol).Validation.Delete '---I added this but not working
'Remove any data validation for this cell:
ws.Range("C" & myRow).Validation.Delete
'and change the value of C5 to "Fill in this cell"
ws.Range("C" & myRow).Value = "Fill in this cell"
ws.Range("C" & myCol).Value = "Fill in this cell" '---I added this but not working
Next col '---I added this but not working
End If
Application.EnableEvents = True
Next cel
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim ws As Worksheet
Dim cel As Range
Dim myRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
'This subroutine fires when a user selects a different cell or range.
'So... it fires ALL The time so the next line is super important.
Set KeyCells2 = Range("C5:C8")
'Did someone change selection specifically to cell C5?
If Not Intersect(Target, KeyCells2) Is Nothing Then
For Each cel In Target ' do the next steps for each cell that was changed
myRow = cel.Row
'Is the value currently "Fill in this cell"?
If ws.Range("C" & myRow).Value = "Fill in this cell" Then
'Empty the cell
ws.Range("C" & myRow).Value = ""
'Add data validation to some list somewhere
With ws.Range("C" & myRow).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=$J$1:$J$4" 'This the range that the list exists in
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End If
Next cel
End If
End Sub
input this to your worksheet module. Note that there are global variables declared
Private previousValue As String
Private previousRange As Range
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyIntersect1 As Range
Dim KeyIntersect2 As Range
Dim eachCell1 As Range
Dim eachCell2 As Range
Dim strHolder As String
Application.EnableEvents = False
Set KeyIntersect1 = Intersect(Target, Range("A5:A8")) '<~ get intersect
If Not KeyIntersect1 Is Nothing Then '<~ check if change happened here
For Each eachCell1 In KeyIntersect1 '<~ loop through. in case copy/pasted
strHolder = eachCell1.Value
eachCell1.Value = strHolder
If eachCell1.Value = "A" Or eachCell1.Value = "C" Then '<~ check the new values
Set KeyIntersect2 = ActiveSheet.Range(eachCell1.Offset(0, 2), eachCell1.Offset(0, 73))
For Each eachCell2 In KeyIntersect2 '<~ loop through columns
eachCell2.Value = "Fill in this cell" '<~ fill them with values
Next
End If
Next
End If
Application.EnableEvents = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim eachCell As Range
Dim KeyIntersect As Range
If previousRange.Value = "" Then '<~checks if the previous range is blank
previousRange.Value = previousValue '<~if so gives previous value
End If
If Target.Value = "Fill in this cell" Then '<~if the target is default value
previousValue = "Fill in this cell" '<~give this to value holder
Set previousRange = Target '<~and set it to previous range
'<~if there is no change it will be checked later
Target.Value = "" '<~cleans this cell.ready for input
End If
Set KeyIntersect = Intersect(Target, Range("C5:C8"))
If Not KeyIntersect Is Nothing Then
For Each eachCell In KeyIntersect
With eachCell
With .Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=$J$1:$J$4"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End With
Next
End If
End Sub
if there is a valid value in the previous cell. it will not give the "Fill in this cell". i am hoping that this will help.
This will copy the value of the changed cell into C5:BV5 on the Worksheet_change event:
Private Sub Worksheet_Change(ByVal Target As Range)
Target.Copy
Range("C5:BV5").PasteSpecial
Application.CutCopyMode = False
End Sub
I have able to also create some solution for this.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Dim cel As Range
Dim myRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
'This subroutine fires when a cell value changes in this worksheet.
Set KeyCells = Range("A5:A8")
'did someone change something specifically in cell A5?
If Not Intersect(Target, KeyCells) Is Nothing Then
For Each cel In Target.Rows ' do the next steps for each cell that was changed
myRow = cel.Row
For columnid = 4 to 8
'Is the value A or C?
If Target.Value = "A" Or Target.Value = "C" Then
ws.cells(myRow, columnID).Validation.Delete
'and change the value of C5 to "Fill in this cell"
ws.cells(myRow, columnID).Value = "Fill in this cell"
Next columnID
End If
Application.EnableEvents = True
Next cel
End If
End Sub

Resources