So I am trying to run the code below. It should be straight to the point, and I don't understand why it's not working. If cell b2 is "John", and cell O2 is empty, then O2 should be red. If O2 is not empty, then it should not be colored.
Any help is must appreciated.
Sub columnO(d As Long)
If Cells(d, "B") = "John" And Cells(d, "O") = "" Then
Cells(d, "O").Interior.Color = RGB(255, 0, 0)
Else
Cells(d, "O").Interior.Color = RGB(1000, 1000, 1000)
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("B10:O10000"), Target) Is Nothing Then
columnO Target.Row
End If
End Sub
This can be easily done with conditional formatting. Just pick conditional formatting from Home menu on your ribbon --> new rule -->Use a formula to determine... and type formula
=$B$2<>"John"
Then you need only set your desired format. You may toggle with $ in formula to allow dragging and copying the format if you need it.
Why don't you rather use conditional formatting instead of VBA?
Might be easier to manage
Related
What I want to achieve is this:
Cell F1 can contain values "MT", "LT" or "MT+LT". If I change the value to "MT", cells C10:C15 should change to value 0. If I change value to LT, cells C3:C8 should change to 0. This looks like a simple task, but I can't find an example, how to do it.
I'm new to VBA so please be gentle :)
You can try this code (you have to paste it in desired sheet in VBE). It will be fired on every change in the sheet:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
'if value changed in some other cell than F1, then finish Sub
If Target.Address <> "$F$1" Then Exit Sub
If Target.Value = "MT" Then
Range("C10:C15").Value = 0
ElseIf Target.Value = "LT" Then
Range("C3:C8").Value = 0
ElseIf Target.Value = "MT+LT" Then
'some action, you seem to forgot
End If
End Sub
Anyone know how to block cells from input (also gray it out) if for example cells A1:C1 = "No" then the rest of the row up to a say F1 is grayed out and blocked from input? I was hoping to do this in VBA but if there are other easier ways, please let me know! Thank you!
Didi
Just to show a different approach:
Put this in the sheet-code-tab:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not (Intersect(Target, Me.Range("D1:F1")) Is Nothing) And Me.Evaluate("AND(LOWER(A1:C1)=""no"")") Then Me.Range("A1").Select
End Sub
And to grey them out, best will be conditional formatting:
Range: =$D$1:$F$1
Formula: =AND(LOWER($A$1:$C$1)="no")
Using the conditional formatting allows to change the cells as you like without the need to alter the VBA code (this also will be faster)
The VBA part itself, just sets the selected cell to A1 if A1:C1 is "No" and a range is selected which also includes any of the cells of D1:F1
The LOWER can be skipped if you want it to be case sensitive
The only con is: if A1:C1 is "no" you still can paste a range to a cell (not any of D1:F1 directly) which also include the locked cells.
The biggest pro is: this also works for shared workbooks (as there is no need to lock/unlock sheets)
EDIT
If the cells need to be protected then something like this will do:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim a As Boolean
a = Me.Evaluate("AND(LOWER(A1:C1)=""no"")")
If a <> Me.Range("D1").Locked Then
Me.Unprotect
Me.Range("D1:F1").Locked = a
Me.Protect
End If
End Sub
as was mentioned in the comments, look to use a workbook change event with the following sub
Sub test()
If Worksheets("Sheet1").Range("A1").Value = "no" And Worksheets("Sheet1").Range("B1").Value = "no" And Worksheets("Sheet1").Range("C1").Value = "no" Then
Worksheets("Sheet1").Range("D1:F1").Interior.Color = RGB(220, 220, 220)
Worksheets("Sheet1").Range("D1:F1").Locked = True
Worksheets("Sheet1").Protect
End If
End Sub
I'm trying to put an array formula into a range of cells ("B2:B10") The formula should return multiple results dependent on the value in cell A2. When I do it the normal way (ctrl, shift, enter) it works ok, but when I try to do it with code it returns the same result in each cell which is the first instance found. Can anyone help me out to get the result I'm looking for?
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("$A$2").Address Then
With Range("B2:B10")
.FormulaArray = "=INDEX(Absence!$C$2:$C$151, SMALL(IF($A$2=Absence!$A$2:$A$151, ROW(Absence!$A$2:$A$151)-ROW(Absence!$A$2)+1), ROW(Absence!1:1)))"
.Value = .Value
End With
End If
End Sub
Is this any better:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("$A$2").Address Then
Range("B2").FormulaArray = "=INDEX(Absence!$C$2:$C$151, SMALL(IF($A$2=Absence!$A$2:$A$151, ROW(Absence!$A$2:$A$151)-ROW(Absence!$A$2)+1), ROW(Absence!1:1)))"
Range("B2").Copy Range("B3:B10")
Range("B2:B10").Value = Range("B2:B10").Value
End If
End Sub
The problem is that you are array-entering the formula into all of the cells at once instead of array-entering into the first cell and filling down. Without filling down, the ROW(1:1) does not progess. You need to put all of the possible k values for the SMALL function in at once with ROW(1:150).
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("$A$2").Address Then
With Range("B2:B10")
.FormulaArray = "=INDEX(Absence!$C$2:$C$151, SMALL(IF($A$2=Absence!$A$2:$A$151, ROW(2:151)-ROW(2:2)+1), ROW(1:9)))"
.Value = .Value
End With
End If
End Sub
Btw, when we use ROW(Absence!$A$2:$A$151) to achieve a number between 2 and 151, the worksheet and column letter are not necessary. ROW(2:151) will do fine and cleans up the formula a little.
I'm not an expert in Excel or VBA, but I do my best. I have an Excel file where cell D10 is either blank or not blank.
Based on cell D10 being blank or not blank, I want to format the text color and/or cell fill in other cells. Cell D10 can change between being blank and not blank, and the colors have to change accordingly.
First I tried to do this without using VBA:
This did not work as I had hoped. The changes did not apply to all cells in the selection, and changing cell D10 from blank to not blank and back to blank did not work.
Then I tried some VBA, which I do not really know how to do. Could someone give me a helping hand?
Sub colourChange()
If Range("D10") = ISBLANK Then
Range("C18:I20").Font.Color = RGB(256, 256, 256)
Range("C32:I33").Font.Color = RGB(256, 256, 256)
End If
If Range("D10") = Not (ISBLANK) Then
Range("C18:I20").Font.Color = RGB(0, 0, 0)
Range("C32:I33").Font.Color = RGB(0, 0, 0)
End If
End Sub
How do I make this module constantly "on"?
Select cell D10 and the ribbon go to Formulas > Define Name and give cell D10 a name (for example, I'll use myVal.)
For your first conditional formatting formula rule have:
=myVal=""
And for your second:
=myVal<>""
This will check to see if there is any sort of value in D10, and apply the formatting correctly.
I've updated this answer as Excel wasn't cooperating fully with the initial solution I gave, but I believe this should solve it!
If you want to use VBA, you need to move the code to Worksheet_Change event of the relevant sheet.
Then, you need to check if the Target range is Cell D10, and then check how to modify the Font.Color accordingly.
Note: you can set multiple ranges in one line with Union, as I implemented in my code below.
Code
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim WatchRange As Range
' set watch range to cell D10
Set WatchRange = Range("D10")
' if modifed cell is D10 >> enter the rest of the code
If Not Intersect(Target, WatchRange) Is Nothing Then
If IsEmpty(Range("D10")) Or Range("D10").Value = "" Then
Union(Range("C18:I20"), Range("C32:I33")).Font.Color = RGB(256, 256, 256)
Else
Union(Range("C18:I20"), Range("C32:I33")).Font.Color = RGB(0, 0, 0)
End If
End If
End Sub
Can i increase the cell address by using macro?
I'm implementing excel cell color matching function.
Example:
When i change the cell "A1" to red, cell "D1" will change to red.
if change "C1" to red, "F1" will change to red too. All need to increase 3 column.
Now i just need to modify the "c.Address" by + 3 so the cell will go do D1.
I try using c.Address + 3 but it can't work.
Any help will be appreciate!
Thanks!
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
For Each c In Worksheets("Sheet1").Range("A1:C1").Cells
If c.Interior.Color = 255 Then
Sheet1.Range(c.Address + 3 ).Interior.Color = 255 <<-- Can't work
Else
Sheet1.Range(c.Address + 3 ).Interior.Color = white <<-- Can't work
End If
Next c
End Sub
Change this:
Sheet1.Range(c.Address + 3 )
To this
Sheet1.Range(c.Address).offset(0,3)
Although I don't know why you need Sheet1.Range(c.Address) and not just c, is c a range? if so you can just do c.offset(0,3)
I really hoped, that Sixthsense is going to edit his answer so I can give him the +1 but it doesn't look like that will happen :(
Still knowing what he tried to achieve, I will at least show some working code and explain it a bit. So first things first: the code:
Option Explicit
Dim rngHolder As Range
Private Sub Worksheet_Activate()
If rngHolder Is Nothing Then Set rngHolder = Intersect(Selection, Range("A1:C1"))
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not rngHolder Is Nothing Then
Dim rngRunner As Variant
For Each rngRunner In rngHolder.Cells
rngRunner.Offset(0, 3).Interior.Color = IIf(rngRunner.Interior.Color = 255, 255, xlNone)
Next
End If
Set rngHolder = Intersect(Target, Range("A1:C1"))
End Sub
The rngHolder (like the sPrev from Sixthsense) is important, because changing the selection, does not return the "old" selection. If you select A1 and change the color no trigger will be activated, so we are going with the Worksheet_SelectionChange. Now after the change, we select D19 and nothing will tell us that A1 has been changed. But we also do not want to run all changes every time the selection changes. For this reason the "last" selection will be stored inside the rngHolder.
I skipped some parts and directly push the selected ranges which cross the cells we need to look at in the variable (or nothing if no intersect is found).
If rngHolder is not empty the next time we select a different cell, it will run all cells in rngHolder to change the background color of the desired cells 3 columns to the right. (this way also changing multiple cells at once will work) and also push the new intersect in the rngHolder.
To the point which I was complaining about the solution of Sixthsense:
If the first selection you do is ...lets say X7... then selecting A3 afterwards will change the background color of AA7 to the same like X7 has. This may be not noticed due to conditional formatting and stuff like that. Wrong "highlight" however may leed to user-errors later on (you also may notice it at a point lots of cells have allready beed changed)
However, the question was just for the "Offset"-function which is already answered in a proper way ;)
Replace your current code with the below one.
Dim sPrev As String
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If sPrev = "" Then sPrev = Target.Address
If Target.Cells.Count = 1 Then
If Target.Column = Range("A:A").Column Then
With Range(sPrev)
.Offset(, 3).Interior.Color = .Interior.Color
End With
sPrev = Target.Address
End If
End If
End Sub