Keeping a conditional format on other cells even if value changes? - vba

There is probably a better way to do what this however for science, I have a cell which goes up and down and at certain break points I would like to change the conditional formatting on other cells if a certain number is ever hit I want to change the color of the cell and when it changes I still want that cell to be conditionally formatted. Is this possible using a formula to conditional format?
Example
Let's say 100 is one of my breakpoints.
When I hit 100 on cell A1, I want to change B2 to a green fill
Now let's say A1 Changes from 100 to 125 for whatever reason. I still want to keep the fill on B2
When trying the below code:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Range("A1").value = 100 Then Range("B1").ColorIndex = 4
End Sub
I get this error
Run-Time error '438':
Object doesn't support this property or method

You could start by placing this code in the relevant worksheet code pane (not in a standard module one):
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Address = "$A$1" Then
If Target.Value = 100 Then Range("B1").Interior.ColorIndex = 4
End If
End Sub
You just have to change:
colorindex to the wanted color one
100 to the needed breakpoint

Related

Change formatting of Cell when it is edited

I want to change the formatting of a cell if the value changes. I just need it to be shaded in.
I'm trying to use the following:
Private Sub Worksheet_Change(ByVal Target As Range)
Target.Interior.ColorIndex = 45
End Sub
However this is far too sensitive. For example if i delete a row, the entire row changes colour as technically it's a change. Even if I go into a cell, make no change and come out of it, it changes the formatting.
Is there anyway to edit the above so it only formats the cell's when the value has changed?
Thanks
I think you could use below code as a base for your further logic.
The idea is: we need to remember value before it is changed, so best to read it when some range is selected (since you are talking about single cell, I didn't consider ranges consisting of more cells). The value would be stored in global variable ValueOnEnter.
When the change is finally made, we compare values "before" and after", and if they differ, change the color.
Public ValueOnEnter As String
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Target.Value <> ValueOnEnter Then
Target.Interior.ColorIndex = 45
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
ValueOnEnter = Target.Value
End Sub

Macro to Limit %

I have an excel spreadsheet which has multiple tabs and cells filled with % values. There are some cells which read 20%, 30%, 40% etc and the format of these cells are 'percentage'. There is a sum cell which sums up all these percentages to equal 100%. I am trying to write a simple macro/rule which would constantly read the sum cell and throw out an alert if it does not equal 100%. I am not sure how to proceed.
I am trying to use Data Validation to do this instead of any coding as what I really want is for the users to be unable to change the values of cells if the total changes from 100. Data Validation still is not working. It always seems to throw errors. Anyone have any thoughts on this ? I have selected the range of numbers and in data validation I am choosing Custom where I am saying = Sum(C5:C10)=100. This is always throwing an error even when the total is 100. Any thoughts ?
If I've understood your question correctly you'll be able to do this without any code.
For example, your percentage cells are on Sheet3, Sheet4 and Sheet5 in the ranges B2:B6.
On Sheet6 you can use the formula =SUM(Sheet3:Sheet5!$B$2:$B$6)
NB: This is a 3D formula and works providing Sheet4 is between Sheet3 & Sheet5 in tab order.
You can then use conditional formatting on the total - Format only cells that contain - Cell Value is greater than 1.
Then format it as something obvious (I generally use bold yellow text with a red background).
Ok, as reply to your comment, add this code to the worksheet code module which will run every time the sheet calculates:
Private Sub Worksheet_Calculate()
If Cells(6, 3) > 1 Then
MsgBox "Total is too high"
End If
End Sub
I would not use the Worksheet_Calculate event procedure because doing so would cause much too frequent evaluation of the MsgBox condition.
Try to keep that to an absolute minimum like so:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count = 1 Then
If Target.Column = 3 Then
If Target.Row < 6 Then
If Val(Me.[c6]) > 1 Then
MsgBox "Greater than 100%"
End If
End If
End If
End If
End Sub
You can use a UDF to replace the SUM function:
Function SumAndAlert(rng As Range) As Variant
SumAndAlert = Application.Sum(rng)
If Application.CountBlank(rng) = 0 And SumAndAlert <> 1 Then MsgBox "not 100%"
End Function
but I think it might be a little annoying to have message boxes poping out while entering data.

Worksheet_Change determine value not content

I am trying to detect if there are changes in a cell value, not particularly the cell contents. I have found multiple solutions to find out if a cell contents has changed, but it does not work when a cell is equal to another cell.
For example, I have cell A1 set to equal B1 and then B1 has a formula that calls in multiple other cells, so I am not able to go back to the beginning and determine whether the cell has changed from that. It needs to come directly from A1.
This is one of the examples I found on this site, but does not determine if the value of A1 has changed, just whether the contents has changed.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 1 Then
Cells(Target.Row, 3).Value = Date
End If
End Sub
The function application.volatile TRUE at the top of your sub will make your sub calculate each time any value in Excel changes. So then you need a global variable which stores the last-known value of your specified range, and any time the sub runs, start with an
If new_cell_value <> stored_global_variable then...
and close with
stored_global_variable = new_cell value'
End If
See here for further info [h/t to vzczc for the original answer and method]: Refresh Excel VBA Function Results

Run VBA code in Excel based on a cell value change by a function

Kindly I need help after trying for hours myself.
I have this code to run a code base on a cell value change, but works only if I type myself the change.
I need to be automatic with the function I have inside the cell, but I can get it right.
This is the code I have now that works well manually:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" Then
Application.EnableEvents = False
Range("D10").Select
Selection.ClearContents
Application.EnableEvents = True
End If
End Sub
Anything that I should add to make it automatic with the formula inside?
This is a tricky one since there is no built in worksheet event that triggers when a particular cell has a value change due to a formula. There is, however, a Worksheet.Calculate event that could be used.
First we make a global string variable. This is a variable that is declared outside of a subroutine or function. It will hold it's value between executions of subroutines and functions. So we will declare it, and then set it to the value of A1 when A1 is changed.
Dim lastValue As String
Private Sub Worksheet_Calculate()
If Range("A1").Value <> lastValue Then
lastValue = Range("A1").Value
Range("D10").ClearContents
End If
End Sub
lastValue here is our Global that will hold the last known value of A1. When worksheet.calculate is triggered it will compare that value against A1 to see if it's changed, if it is then it executes your code to clear the contents of D1
Instead of a Global you could also just stick that last known value of A1 into a Cell somewhere too. Then do you comparison to that. The advantage of using a cell over a global variable, is that the cell value will hold it's value even if you close and reopen the sheet. So, depending on your needs, it may be a better option:
Private Sub Worksheet_Calculate()
lastValue = Range("Z10").value
If Range("A1").Value <> lastValue Then
Range("Z10").value = Range("A1").Value
Range("D10").ClearContents
End If
End Sub
Where Range Z10 is the spot that holds the last known value.
Lastly I reduced your code to clear contents of D10 to a single line. Anytime you see Something.Select and then in the next line see Selection.DoSomething you can just get rid of that Select/Selection bit. Selecting a cell is generally something that only a human needs to do to interact with the sheet. VBA can do whatever it likes to cells without have to Select them.

Circle Invalid-data Macro

I have a worksheet with many dependant dropdowns that are liable to having invalid data if the initial drop down is altered. I would like a simple auto-macro that would automatically run the "circle invalid data" command every time a cell change within a specified range (D8:T800) is detected.
It sounds fairly straightforward but I am not sure how to do this.
Question - as this macro will run every single time a cell is amended would this macro slow down the worksheet?
EDIT:
Also: as this might be slow,is there a way we can run this command over a selected range?
Your thoughts thanks.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("D8:T800")) Is Nothing Then
Me.CircleInvalid
End If
End Sub
Note that CircleInvalid applies to the whole sheet, so while this code only triggers when a cell inside D8:T800 changes, all invalid cells on the sheet will be circled
Try placing this code inside your Worksheet:
Private Sub Worksheet_Change(ByVal Target As Range)
' Check target range has changed
If (Not Intersect(Target, Range("D8:T800")) Is Nothing) Then
' Prevent recusrive looping
Application.EnableEvents = False
' Refresh validation circles
Target.Worksheet.CircleInvalid
Application.EnableEvents = True
End If
End Sub
Note that this will NOT work if the values in those cells change due to a calculation from outside the specified range.
Also, the CircleInvalid method applies to the whole worksheet.
You could try editing the code in the conditional to 'do something' if the Target is validated — this would result in you changing the format of invalid cells instead of having the red circles around them.
**PSEUDO-CODE**
For each cell in Target.Range
cell.colour = bright red
Next cell