I have VBA code that works, but does not seem to be optimal. The code should change the colour of the text in the relevant cell in columns H & I when a cell in Column N is clicked.
For example, when cell N5 is clicked, the text in cells H5 and I5 should turn white. When it is unclicked, they return to their normal colour.
The code does not seem to be optimal because the change in column I lags behind that in column H.
I would like a way to make both change instantaneously.
(Bonus points if you can make the cells change colour AND turn into bold instaneously, with the constraint that like for colour, the bold disappears once the cell is unselected).
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim r As Range
Intersect(Columns("H"), ActiveSheet.UsedRange).Font.Color = vbBlack
Set r = Intersect(Range("N:N"), Target)
If r Is Nothing Then Exit Sub
Cells(r.Row, "H").Font.Color = vbWhite
Intersect(Columns("I"), ActiveSheet.UsedRange).Font.Color = vbBlack
Set r = Intersect(Range("N:N"), Target)
If r Is Nothing Then Exit Sub
Cells(r.Row, "I").Font.Color = vbWhite
End Sub
Please note, this is my first time writing VBA, hence any amateurismes.
You don't need to address each column separately...
EDIT: added bold and multiple cells
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim r As Range, c As Range
Set r = Intersect(Me.Range("N:N"), Target)
'? what to do if user selects multiple cells ?
'E.g. - exit if user has >100 cells selected (possibly whole column)
If r Is Nothing Or Target.Cells.CountLarge > 100 Then Exit Sub
Application.ScreenUpdating = False
HighlightIt Application.Intersect(Me.Range("H:I"), Me.UsedRange), False
For Each c In r.Cells
HighlightIt Me.Cells(c.Row, "H").Resize(1, 2)
Next c
Application.ScreenUpdating = False
End Sub
'utility sub for highlighting/unhighlighting
Sub HighlightIt(rng As Range, Optional hilite As Boolean = True)
With rng
.Font.Color = IIf(hilite, vbWhite, vbBlack)
.Font.Bold = hilite
End With
End Sub
Always worth thinking about what should happen if the user selects multiple cells (or even a whole column). Handling this robustly is sometimes a challenge, depending on what you want to happen when they do that.
Related
I have a macro set up to perform a chunk of code in an 'onclick' event, and I'm trying to determine if they've selected a numeric value in a table range. An example of my table is below, and I'm trying to figure out if they've selected a number > 0 in the second column. I know how to reference the second column of a specific table, something like:
ListObjects("Table1").ListColumns(2).DataBodyRange
but I'm not sure how to figure out if the selected cell is in that range. Any suggestions? Thanks so much for your help!
Use Intersect.
Dim rangeToCheck as Range
Set rangeToCheck = Intersect(ActiveCell, ListObjects("Table1").ListColumns(2).DataBodyRange)
If Not rangeToCheck Is Nothing Then
If IsNumeric(ActiveCell.Value) Then
If ActiveCell.Value > 0 Then
' do the suff
End If
End If
End If
Assuming your table has filters then you have to check the visible cells only
Try this code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
Dim r As Range
Set r = ListObjects(1).ListColumns(2).DataBodyRange.SpecialCells(xlCellTypeVisible)
Dim hit As Boolean
hit = Not Application.Intersect(r, Target) Is Nothing
If hit Then
Range("A1").Value = "Inside"
Else
Range("A1").Value = "Outside"
End If
Application.EnableEvents = True
End Sub
otherwise for all visible and non-visible cells use
Set r = ListObjects(1).DataBodyRange
I need to highlight and entire row if a cell string contains the word "risk". But I need to make it using vba since the person using it will write on it after using the macro.
I have something like:
The reason will be written afterwards and I need to highlight the row if someone writes the word risk anywhere in this column. Anything can be written there.
I use this to highlite a row when I want a full match:
lastReg= Cells(Rows.Count, 1).End(xlUp).Row
Set Rng = Range("A1:J" & lastReg)
Rng.FormatConditions.Add Type:=xlExpression, Formula1:="=$J1=""Plat"""
...
so I tried:
Rng.FormatConditions.Add Type:=xlExpression, Formula1:="=FIND(""risk"",$J1)>0"
But it doesn't work.
Edit: it gives me an execution error so the code itself doesn't run.
Edit2: Someone else uses this macro, and he can't do it by himself so I wanted the code to do it for him.
Also, the code is stored in the personal.xlsb because he runs the code in a different worksheet everyday, so I can't pre config the formatConditions for the worksheet.
I would use a worksheet change event. place this sub in your worksheet. Whenever any cell in column 5 changes and the value is "risk", it will color the row.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Rng As Range
Set Rng = Columns(5)
If Not Intersect(Rng, Target) Is Nothing And Target.Value = "risk" Then
Target.Offset(, -4).Resize(, 5).Interior.Color = vbYellow
End If
End Sub
Try:
Option Explicit
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim cell As Range
If Not Intersect(Target, Sh.UsedRange) Is Nothing Then
For Each cell In Target.Cells
With cell
If UCase(.Value) = "RISK" Then
.Font.Color = vbRed
Else
.Font.Color = vbBlack
End If
End With
Next cell
End If
End Sub
I need to create an Excel document with updating totals in the A column, based on numbers entered in the B column. Each respective cell in row A should update based on its equivalent B cell value whenever a new value is added, and then the value entered into B is cleared once added to A.
I have gotten things working for one single row but don't have knowledge or understanding on how to best make this work for EACH cell pair in the entire column. I really don't want to copy and paste this 10,000 times and update the cells to reference the correct pair. Code for single cell:
Private bIgnoreEvent As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
If bIgnoreEvent Then Exit Sub
bIgnoreEvent = True
Cells(1, 2) = Cells(1, 2) + Cells(1, 1)
Cells(1, 1) = ""
bIgnoreEvent = False
End Sub
I am hoping this can be achieved with a loop function, or a range of some sort.
This should work:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range, c As Range
'any updates in ColB?
Set rng = Application.Intersect(Target, Me.Columns(2))
If Not rng Is Nothing Then
Application.EnableEvents = False '<< prevent re-triggering of event
'Process each updated cell
For Each c In rng
If IsNumeric(c.Value) Then
With c.Offset(0, -1)
.Value = .Value + c.Value
End With
c.ClearContents
End If
Next c
Application.EnableEvents = True '<< re-enable event
End If
End Sub
I have rows from 1-100.
I know how to target specific cells and get data from them, but how would I do this when any row from 1 to 100 can be changed?
Say you put anything into Row A3. How would you write "Updated" into row B3 via VBA?
I want this to apply to rows A1-A100.
Thanks
Place the following event macro in the worksheet code area:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim A As Range, Intersection As Range, Cell As Range
Set A = Range("A1:A100")
Set Intersection = Intersect(Target, A)
If Intersection Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each Cell In Intersection
Cell.Offset(0, 1).Value = "Updated"
Next Cell
Application.EnableEvents = True
End Sub
Open VBA Editor
Double click on the sheet you event take action (sheets appears in the left top box)
Select Worksheet on the left box above code box
Select change on the right box above code box
Paste the code
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
With ThisWorkbook.Worksheets("Sheet1")
If Not Intersect(Target, .Range("A1:A100")) Is Nothing Then
Application.EnableEvents = False
.Range("B" & Target.Row).Value = "Updated"
Application.EnableEvents = True
End If
End With
End Sub
I have the following code:
Sub ConditionalFormattingNamedRange()
Dim x As Range, Cell As Range
Set x = Range("AALB_Exposure")
For Each Cell In x
If Cell.Value > Sheets("Overview").Range("E4").Value Then
Cell.Interior.Color = RGB(0, 255, 0)
End If
Next
End Sub
Background information: This formula makes values in my defined range "AALB_Exposure" colored if they are larger than cell E4 on sheet "Overview". The value of cell E4 is the result of two other cells. Sometimes one of these cells varies. I have more than 20 defined ranges such as "AALB_Exposure", so I prefer to use a module.
Problem: This module makes all values colored. Sometimes there are some blank cells in "AALB_Exposure". I would like to see that this does not occurs. Is this possible?
In addition, this module is static and does not modifies the color of the cells in the defined range as I adjust E4. This happens only after I run the module. Is it possible to ensure that the color of cells adjust immediately depending on varying the values of E4.
Thank you!
----- Edit ------
After the excellent suggestion of Bruce Wayne, I changed my code a little bit.
Private Sub Workbook_SheetCalculate(ByVal Target As Range, ByVal Sh As Worksheet)
If Target.Address = "$A$9" Then
Application.ScreenUpdating = False
Dim x As Range, Cell As Range
Set x = Sh.Range("P1:P150,AD1:AD150,AR1:AR150,BF1:BF150,BT1:BT150,CH1:CH150,CV1:CV150,DJ1:DJ150,DX1:DX150,EL1:EL150")
For Each Cell In x
If Cell.Value > Sh.Range("A9").Value And Cell.Value <> "" Then
Cell.Interior.Color = RGB(0, 255, 0)
End If
Next
End If
Application.ScreenUpdating = True
End sub
As the named range is always the same for each sheet, it is maybe better to address the problem this way? Consequently, I changed Cell E4 that is located on the Overview sheet for a cell that is always on the same location for each sheet.
However, is this new module correct?
If you want this to run whenever E4 is changed, you need to put it in a Worksheet Change event:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$E$4" Then
Application.ScreenUpdating = False
Dim x As Range, Cell As Range
Set x = Range("AALB_Exposure")
For Each Cell In x
If Cell.Value > Sheets("Overview").Range("E4").Value And Cell.Value <> "" Then ' added `AND` part to check if cell is not blank
Cell.Interior.Color = RGB(0, 255, 0)
End If
Next
End If
Application.ScreenUpdating = True
End Sub
Put that in the Worksheet Module of the sheet you want to run it on. It will also check to see if the cell is blank or not before adding the color.