Selecting part of a row dynamically for colouring cells - excel

I want to change the background color of cells, but not the entire row, based on the value of a cell. I have some code that does what I want, but I'm sure there is a more efficient way and would like some help in making my code more efficient. Listed below is a snippet of the code that performs the task.
Sub chg_bkgrnd_Color()
Dim rng As Range
Dim row As Range
Dim cell As Range
Dim counter As Long
Set rng = Range("k2:k23")
Range("k2").Select
For Each cell In rng
Select Case cell.Value
Case Is = "Closed"
ActiveCell.Offset(counter, -10).Interior.ThemeColor = xlThemeColorDark1
ActiveCell.Offset(counter, -10).Interior.TintAndShade = -0.249977111117893
ActiveCell.Offset(counter, -9).Interior.ThemeColor = xlThemeColorDark1
ActiveCell.Offset(counter, -9).Interior.TintAndShade = -0.249977111117893
ActiveCell.Offset(counter, -8).Interior.ThemeColor = xlThemeColorDark1
ActiveCell.Offset(counter, -8).Interior.TintAndShade = -0.249977111117893
ActiveCell.Offset(counter, -7).Interior.ThemeColor = xlThemeColorDark1
ActiveCell.Offset(counter, -7).Interior.TintAndShade = -0.249977111117893
End Select
counter = counter + 1
Next
End Sub

Conditional Formatting would be best, but if you wish to use normal formatting, this is a streamlined version of your code:
Sub chg_bkgrnd_Color()
Dim i&
For i = 2 To 23
If Cells(i, 11) = "Closed" Then
With Range(Cells(i, 1), Cells(i, 4)).Interior
.ThemeColor = xlThemeColorDark1
.TintAndShade = -0.249977111117893
End With
End If
Next
End Sub
Following #Jeeped's suggestion, here is a version to use to automate this. In the worksheet's code module, place this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
RangeAutoBackFill "Closed", 11, 2, 23, 1, 4, xlThemeColorDark1, -0.249977111117893
End Sub
And then in a standard code module, place this:
Public Sub RangeAutoBackFill(Key$, KeyCol&, KeyRowLow&, KeyRowHigh&, FillColLow&, FillColHigh&, FillTheme&, FillTint#)
Dim i&
For i = KeyRowLow To KeyRowHigh
If Cells(i, KeyCol) = Key Then
With Range(Cells(i, FillColLow), Cells(i, FillColHigh)).Interior
.ThemeColor = FillTheme
.TintAndShade = FillTint
End With
End If
Next
End Sub

You are inquiring about how to get the cells from columns A:D to have a highlight based upon whether the corresponding value in column K is "Closed" or not. Conditional Formatting is a better solution as it provides an automated, background reaction to changes in column K instantly.
Sub Create_Conditional_Formatting_for_AD_based_on_K_Closed()
Dim v As Long, vSTATEs As Variant, vCOLOURs As Variant
vSTATEs = Array("Open", "Closed", "Pending")
vCOLOURs = Array(3, 10, 5)
With ActiveSheet.Columns("A:D")
.FormatConditions.Delete
For v = LBound(vSTATEs) To UBound(vSTATEs)
With .FormatConditions.Add(Type:=xlExpression, _
Formula1:="=$K1=" & Chr(34) & vSTATEs(v) & Chr(34))
With .Interior
.ColorIndex = vCOLOURs(v)
End With
.StopIfTrue = True
End With
Next v
End With
End Sub
This routine may be well suited to a situation where you want to apply the CF rules to a large number of worksheets or as a recurring task on a regular import to a new worksheet but it probably is more work than simply creating the six rules manually.
I've simplified the selection of a backfill colour with the .ColorIndex property. You can find a table of ColorIndex numbers and colours here.
Please note that I am deleting previous CF rules with an Applies to: of columns A:D before constructing new ones. That may be a consideration if you have other CF rules governing the behavior in columns A:D.
Using a formula in a CF rule and locking the column K reference with an absolute $ indicator allows you to implement an Applies to: that is different from the column being evaluated. Use Home ► Conditional Formatting ► Manage Rules to view the outcome.
Manual method:
Select columns A:D with A1 as the ActiveCell
Choose Home ► Conditional Formatting ► New Rule
Choose Use a formula to determine which cells to format and supply the following in the Format values where this formula is true: text box: =$K1="closed  
Click format and choose an appropriate highlight combination from the Fill tab.
Click OK to accept the formatting change and then OK again to create the rule.
Go to step 2 and repeat as necessary. If you start with Home ► Conditional Formatting ► Manage Rules and choose New you can save a few clicks.
Your results should resemble the following.
        

Related

dropdownlist selection changed - grey out cells

Hi I'm just new here and I just need some guidance for me to be able to solve the issue that I have. I have a excel file and I have a drop down in column AA (Yes or No), I know there's conditional formatting that will change the color of the row. But I have 3000 rows.
What I want to happen is when the user, select on No, it will grey out the entire row. Is there easy way. Because it will take some time if i will do it on conditional formatting 1 by 1.
For example, if user on AA4 select no on drop down. It will gray out AB4 - AK4
You would NOT apply this rule row by row. Instead, apply it to one row and then expand the scope of the rule to the desired range. While you can do this in VBA, it is by no means necessary.
Use a formula to set your conditional format by navigating to Conditional Formatting > New Rule > Use a formula to determine which cells to format.
Your formula should reference the column of interest (In my example Column A and in yours it's Column AA). Be sure to not lock the row reference and apply your desired format here!
Once done, navigate to your existing rules to modify the range the rule applies to (Conditional Formatting > Manage Rules > Select newly created rule). Given my setup, the range to apply the rule is B2:F10 so the form looks like so:
When done the range supplied in the last step should highlight per the formula and format you applied in the first step
You can automate it in two ways (using VBA):
Create cnditional formatting for the necessary range, in this way:
Sub makeCondForm()
Dim sh As Worksheet, lastRow As Long
Set sh = ActiveSheet
lastRow = sh.Range("AA" & rows.count).End(xlUp).row
With sh.Range("AB4:AK" & lastRow)
.FormatConditions.Delete
.FormatConditions.Add Type:=xlExpression, Formula1:="=$AA4=""No"""
.FormatConditions(.FormatConditions.count).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorDark1
.TintAndShade = -0.14996795556505
End With
End With
End Sub
Using Sheet Change Event. Please, copy the next code in the sheet code module:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = Range("AA1").Column Then
If Target.Value = "No" Then
With Range(Target.Offset(0, 1), cells(Target.row, "AK")).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorDark1
.TintAndShade = -0.14996795556505
End With
Else
Range(Target.Offset(0, 1), cells(Target.row, "AK")).Interior.Color = xlNone
End If
End If
End Sub
Please, note that the range in discussion must not have any Conditional Formatting. And it must be initialized, in a way. I mean, it will work only after you change a cell value in the column "AA" from something else to 'No'...

Excel VBA Macro Help - Mandatory Cells

New user, was referred to your helpful website by a friendly team member.
Problem: Trying to force a user in excel to fill in a cell in a column (column O) before filling in a cell in columns I-L. The problem lies in that not every cell in the columns needs to be filled in. I've found a VBA code that has somewhat helped but the problem is the pop up will still occur if column O is filled before there is text in just one of the cells in column I-L (and therefore the error occurs unless all 4 cells in the row are filled in). As mentioned, the goal is (for example) to get O264 to be filled in first before any of the cells in column I,J,K or L264 are filled in.
Further exacerbating this issue is there are multiple rows I need this applied to, believe this is where the range fits in. However, playing with the range line in excel does not work in the way I've tried.
Code below:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("I:L")) Is Nothing Then
If Target.Cells.Count > 1 Or IsEmpty(Target) Then Exit Sub
If Target.Offset(, -1).Value = "" Then
MsgBox "You must first enter feedback in column ""O"""
Target.Value = ""
Target.Offset(, -1).Select
End If
End If
End Sub
This could be a case where you might need to aid the user a little more. You could do that by hiding the dependent cells, by locking them, by greying them out, etc. My feeling is that displaying a message box whenever a user enters data in the wrong order is a little too reactive.
In the example below, the target cells are locked and greyed until something is entered in column 'O'. You'd also need to create a list of target rows if you have more than one.
In your code behind the appropriate sheet, the skeleton code below should get you started. I've included a couple of helper functions to make the code a little clearer for you:
Option Explicit
Private Const SHEET_PASSWORD As String = "xyz" 'whatever password you choose.
Private Const TARGET_ROWS As String = "2,4,6" 'your target rows, separated by commas.
Private Const TARGET_COLUMN As String = "O"
Private Const DEPENDENT_COLUMNS As String = "I:L"
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range, cell As Range
Set rng = Intersect(Target, Me.Columns(TARGET_COLUMN))
'Exit routine if we're not in the target column.
If rng Is Nothing Then Exit Sub
'Process the target column cells.
For Each cell In rng.Cells
If IsTargetRow(cell.Row) Then
SetDependentStates cell
End If
Next
End Sub
Private Sub SetDependentStates(cell As Range)
Dim DependentRange As Range
'Define the Dependent range based on passed cell row.
Set DependentRange = Intersect( _
cell.EntireRow, _
Me.Range(DEPENDENT_COLUMNS) _
)
'Lock/unlock and paint Dependent rows, based on
'contents of passed cell.
Application.EnableEvents = False 'prevent capture of change event.
Me.Unprotect SHEET_PASSWORD
With DependentRange.Cells
If Len(cell.Value) = 0 Then
.ClearContents
.Locked = True
With .Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorDark1
.TintAndShade = -0.249977111117893
.PatternTintAndShade = 0
End With
Else
.Locked = False
With .Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
End With
Me.Protect SHEET_PASSWORD
Me.EnableSelection = xlUnlockedCells
Application.EnableEvents = True
End Sub
Private Function IsTargetRow(rowNum As Long) As Boolean
Dim v As Variant
'Tests if the pass row number is in the target row list.
For Each v In Split(TARGET_ROWS, ",")
If CLng(v) = rowNum Then
IsTargetRow = True
Exit Function
End If
Next
End Function
Public Sub InitialiseDependentStates()
Dim v As Variant
Dim cell As Range
'Define your unlocked cells.
'This is a simple example, adjust as you wish.
With Me
.Unprotect SHEET_PASSWORD
.Cells.Locked = False
.Protect SHEET_PASSWORD
.EnableSelection = xlUnlockedCells
End With
For Each v In Split(TARGET_ROWS, ",")
Set cell = Me.Range(TARGET_COLUMN & v)
SetDependentStates cell
Next
End Sub
You'll likely want to initialise the dependent states when the workbook is opened. Do this in the code behind the Workbook:
Private Sub Workbook_Open()
Sheet1.InitialiseDependentStates 'use whichever sheet you're using.
End Sub

VBA code to find a color in a selection and change it

Trying to write a code that will find red cells and change them to green within a selection. I am a total beginner so this will look barbaric but here it is. I can get it to go down a column and change the colors along the way but what I am really looking to do is have it do that within a selection and when it gets to the bottom of the selected column go back up to the next column within the selection and so on until there is no data available. Here is what I have. Thanks a bunch for any help!
Sub change_colour()
Do While ActiveCell.Value <> ""
Do While Selection.Interior.Color = 255
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 5296274
.TintAndShade = 0
.PatternTintAndShade = 0
End With
ActiveCell.Offset(1, 0).Select
Loop
ActiveCell.Offset(1, 0).Activate
Loop
End Sub
What I would do is set a Range variable to the current selection, and just loop through that range and check the color. If it is red, change it.
You're close, but there's some unnecessary code here (which is to be expected as you're learning).
I think the key is declaring and assigning the Range variable and the use of a For..Each loop.
Public Sub Change_Colour()
Dim rSel As Range, c As Range
Set rSel = Selection
For Each c In rSel
If c.Interior.Color = 255 Then
c.Interior.Color = 5296274
End If
Next c
End Sub
So this code declares two range variables rSel and c. rSel is initiated as the user's selection. I use the For..Each loop with the range variable c to loop through all of the cells in the selection.
The If statement is a stripped-down version of what you have, checking to see if the cell's color is red and changing it to green if so.

VBA Excel - Date Formatting Iteration Issue

Basically, I want VBA to loop through a range (E2 - last row), and when it finds any month and day "dd/mm" to add on 2014, c.i.p "dd/mm/2014." Secondly, if it finds "n/a" it should highlight that cell in red. My code doesn't do anything, however. What is wrong with my code?
Sub yearstandard()
Dim wb As Workbook
Dim ws As Worksheet
Dim range As range
Dim i As Long
LastRow = FindLastRow(1)
For i = 5 To LastRow 'test row 1 to whatever the last populated row is
Set cell = Cells(i, 2) 'Define cell as the cell to be tested e.g. (cells 1,1) is A1
Select Case cell.Value 'select case value in cell
Case Is = "dd/mm"
cell.Value = "dd/mm/2014" 'wrap each date entered in year 2014
Case Is = "n/a"
cell.Interior.Color = RGB(255, 255, 102) 'highlight cells with value "n/a" in red
End Select
Next i 'go to the next loop counter
End Sub
In your comment you indicated you would be manually entering either 3/14 or n/a into cells.
Assuming your regional settings are US (mdy), and you are going to be entering the data this year, there is no need for VBA. Merely enter 3/14 and Excel will automatically add the current year. With regard to turning the n/a red, just use conditional formatting on the entire column. You might want to custom format the column as d/m/yyyy if you don't "see" the 2014.
If you absolutely must do this in VBA, then something like the below will set those options for range in column E from E2 to the last row.
I have also assumed that there is no other conditional formatting in that column. If there is, then, instead of deleting the old conditional formatting, we will need to preserve it when running the macro.
Sub FormatColE()
With Range("E2", Cells(Rows.Count, "E").End(xlUp))
.NumberFormat = "m/d/yyyy"
.FormatConditions.Delete
.FormatConditions.Add Type:=xlCellValue, Operator:=xlEqual, _
Formula1:="=""n/a"""
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1)
.Interior.Color = vbRed
.StopIfTrue = False
End With
End With
End Sub

Excel 2010 conditional formatting individual rows

I am trying to use conditional formatting (green - yellow - red color scales) on 844 distinct rows to track premium volume over the last six years (years are columns). Here is the tricky part in between each volume column is number of items. I would like to format each row for premium volume and leave the number of items unchanged.
At this point I am selecting each individual premium volume cell by holding ctrl down and then selecting the conditional formatting.
I am trying to automate this so I don't have to continue this process for 844 rows and future spreadsheets as well.
I attached a picture of the worksheet for your reference.
Any help is greatly appreciated!!!
Thanks,
Brad
I got some basic code for the conditional formatting by running the Macro Recorder. I replaced all the occurrences of Selection with a rng variable, and set that rng variable as a parameter to the subroutine so the Sub can be called in a loop:
Sub SetRangeCF(rng As Excel.Range)
rng.FormatConditions.AddColorScale ColorScaleType:=3
rng.FormatConditions(rng.FormatConditions.Count).SetFirstPriority
rng.FormatConditions(1).ColorScaleCriteria(1).Type = _
xlConditionValueLowestValue
With rng.FormatConditions(1).ColorScaleCriteria(1).FormatColor
.Color = 8109667
.TintAndShade = 0
End With
rng.FormatConditions(1).ColorScaleCriteria(2).Type = _
xlConditionValuePercentile
rng.FormatConditions(1).ColorScaleCriteria(2).Value = 50
With rng.FormatConditions(1).ColorScaleCriteria(2).FormatColor
.Color = 8711167
.TintAndShade = 0
End With
rng.FormatConditions(1).ColorScaleCriteria(3).Type = _
xlConditionValueHighestValue
With rng.FormatConditions(1).ColorScaleCriteria(3).FormatColor
.Color = 7039480
.TintAndShade = 0
End With
End Sub
Then you call the sub above in a loop, in this case once for any row that has a value in column A. This assumes that the condtional formatting starts in row 2 and that you have uninterrupted data in column A. If not, you'd have to adjust this looping code:
Sub SetEachRow()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim cell As Excel.Range
Set ws = ActiveSheet 'change as necessary
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
For Each cell In .Range("A1:A" & LastRow)http://stackoverflow.com/questions/10245638/excel-changes-conditional-formatting-formula?rq=1
cell.EntireRow.FormatConditions.Delete
SetRangeCF cell.EntireRow
Next cell
End With
End Sub
I don't know what the limit of rows is that this will work on, but 1,000 worked fine for me.

Resources