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.
Related
I've found codes in other posts and other forums, but they don't seem to work for me.
I only have a basic working knowledge of VBA I can understand what it does, but creating a complex code is harder
I have a multiple worksheets A1:K##
Column C has a number or a code (text)
Starting with row B I want to add a thick bottom border every 9th row (so after 9, 18, 27 etc)
And stop when the numbers end
Restart the count for the Code(text).
Thanks in advance for any help
Here's a sample of what started with, but could not manage to properly modify it to do what I wanted.
I was able to have the whole row bottom border thick, but not just in the A to K range.
Sub Borders()
Dim cl As Range
Dim LC As Long
LC = Cells(1, Columns.Count).End(xlToLeft).Column
For Each cl In Range("$A$1:$A" & Cells(Rows.Count, "A").End(xlUp).Row)
If cl.Row Mod 10 = 0 Then
With cl.Resize(1, LC).Borders(xlEdgeBottom)
.LineStyle = xlDouble
.Weight = xlThick
.ColorIndex = xlAutomatic
End With
End If
Next cl
End Sub
I added the option of resetting the count at the text code, if I'm getting help may as well get it done right first.
Having re-read your question I spotted the multiple sheets part.
Your code works fine and will do on multiple sheets with a couple of minor changes.
This uses For....Each to loop through each sheet in the workbook that contains the code (ThisWorkbook).
Select Case sht.Name is used so the code only runs on specified sheets. Move the code to the Do Nothing line if it's easier to list the sheets you don't want it to run on. Remove the Select...End Select if you want it to run on all sheets.
With....End With is used to tell the range references what sheet you to look at - Cells, Rows, Columns - anything that is specific to a sheet is preceded by a . to tell the code you're referring to the sheet in the With line.
Sub Borders()
Dim cl As Range
Dim LC As Long
Dim sht As Worksheet
For Each sht In ThisWorkbook.Worksheets
Select Case sht.Name
Case "Sheet1", "Sheet2", "Sheet4"
With sht
LC = .Cells(1, .Columns.Count).End(xlToLeft).Column
For Each cl In .Range("$A$1:$A" & .Cells(.Rows.Count, "A").End(xlUp).Row)
If cl.Row Mod 9 = 0 Then
With cl.Resize(1, LC).Borders(xlEdgeBottom)
.LineStyle = xlSingle
.Weight = xlThick
.ColorIndex = xlAutomatic
End With
End If
Next cl
End With
Case Else
'Do nothing.
End Select
Next sht
End Sub
Further reading:
For...Each
With
Select Case
I want to use the value in cell as a dynamic way to change the range in my macro, more specifically when changing the colour of a cell.
Lets says CELL A1 hosts the desirable range data. The macro will always look at this cell. The text in A1 = 'B4' therefore I want this to be the selected cell to have a colour fill. This will be repeated quite a few times and the data will change, this is why i need it to be a dynamic macro not conditional formatting.
Below is the standard colour macro and is far as i can get, VBA noob sorry.
Sub Colour2()
'
' Colour2 Macro
'
'
Range("B4").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 16731903
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Hope this makes sense and thanks for your understanding and help.
M
Highlight Range Supplied in a Cell
This is an automated solution. You run nothing. Just copy the codes in the appropriate modules.
As you change the range address in cell A1, the color is applied to the cells of the supplied range address and the range is selected.
Sheet object module e.g. Sheet1 (the name not in parentheses in the VBE Project Explorer)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const mAddress As String = "A1"
Const ColorValue As Long = 16731903
Dim mCell As Range: Set mCell = Range(mAddress)
If Not Intersect(mCell, Target) Is Nothing Then
On Error Resume Next
Dim rg As Range: Set rg = Range(mCell.Value)
On Error GoTo 0
If Not rg Is Nothing Then
Application.ScreenUpdating = False
' Removes the colors from all cells before applying the color.
applyColor rg, ColorValue, True
' Applies the color without removing the previously applied colors.
'applyColor rg, ColorValue
rg.Select
Application.ScreenUpdating = True
End If
End If
End Sub
Standard Module e.g. Module1 (optionally in the same sheet object module)
Sub applyColor( _
ByVal rg As Range, _
ByVal ColorValue As Long, _
Optional ByVal resetBeforeApply As Boolean = False)
If resetBeforeApply Then
rg.Worksheet.Cells.Interior.Color = xlNone
End If
With rg.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = ColorValue
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
The standard module is preferred because it could then easily be used for other worksheets.
Could you please help me with my code. A have simple data to which I want to apply "All Borders". Number of rows will change
Sub Draw_Borbers()
Dim FO As Worksheet
Dim LastRow As Long
Dim AllRange As Range
Set FO = ThisWorkbook.Worksheets("Final Order")
LastRow = FO.Cells(Rows.Count, 1).End(xlUp).Row
Set AllRange = Range("A2:I2" & LastRow)
With AllRange.Borders
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = 0
.TintAndShade = 0
End With
End Sub
The problem is while I only have 361 non-empty row (based on column A), it gives me borders for 2361 rows.
I thought It is because of blanc rows and added
.Columns("B:B").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
to previous macros, but it still gives me that odd number of rows.
In previous macros I copy-paste data from pivot table and delete some rows, but even full list consists of only 651 rows...
Would appreciate your help very much!
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.
I have this code for workbook:
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
'toggles worksheet colors
'code will remove all color
'and color active row and column
If ActiveCell.Interior.ColorIndex <> xlNone Then
Cells.Interior.ColorIndex = xlNone
Else
Cells.Interior.ColorIndex = xlNone
ActiveCell.EntireRow.Interior.ColorIndex = 4
End If
End Sub
and works good. but if a row has an initial color, it will be removed. let me know how
active row will be highlighted and by changing the row, will get its initial color?
Damn, I couldn't find the Add-In but I recreated the code for you. Please note that this is not thoroughly tested. In whatever small tests that I did, it works...
Logic:
Create a hidden sheet.
Store the current cell's formats in row 1 of that hidden sheet
Store the currently selected row number in active sheet to cell A2 of the hidden sheet
when you move to a different row then retrieve the last row number and restore it.
Code:
In thisWorkbook code area
Private Sub Workbook_Open()
Dim ws As Worksheet
'~~> Delete the Temp sheet we created i.e if we created
Application.DisplayAlerts = False
On Error Resume Next
Sheets("MyHiddenSheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'~~> ReCreate the Sheet
Set ws = ThisWorkbook.Sheets.Add
'~~> i am using a normal name. Chnage as applicable
ws.Name = "MyHiddenSheet"
'~~> Hide the sheet
ws.Visible = xlSheetVeryHidden
End Sub
In relevant sheet code area. I am using Sheet1 as an example
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'~~> Don't do anything if multiple cells are selected
If Target.Cells.CountLarge > 1 Then Exit Sub
Dim ws As Worksheet
'~~> Set our relevant sheet
Set ws = ThisWorkbook.Sheets("MyHiddenSheet")
'~~> Get the row number of the last row we had selected earlier
'~~> For obvious reasons, this will be empty for the first use.
If Len(Trim(ws.Cells(2, 1).Value)) <> 0 Then
'~~> If user has moved to another row then
'~~> Restor the old row
If Target.Row <> Val(ws.Cells(2, 1).Value) Then
ws.Rows(1).Copy
Rows(ws.Cells(2, 1).Value).PasteSpecial xlFormats
End If
End If
'~~> Copy the current row's format to the hidden sheet
Rows(Target.Row).Copy
ws.Rows(1).PasteSpecial xlFormats
'~~> Store the current rows value in cell A2
ws.Cells(2, 1).Value = Target.Row
'~~> Highlight the current row in a shade of blue.
'~~> Chnage as applicable
With Rows(Target.Row).Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent5
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
Rows(Target.Row).Select
End With
'~~> Remove the `Ants` which appear after you do a copy
Application.CutCopyMode = False
End Sub
Screenshots:
Here's an alternate approach which makes use of the fact that Excel always "overlays" Conditional Formatting on top of whatever formatting is already on the sheet.
Define a worksheet-level name "ROWNUM" and assign a value of 0.
Add a conditional format using the formula =(ROW()=ROWNUM) and add whatever formatting you want to use for row highlighting.
Your SelectionChange sub is then just:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Me.Names("ROWNUM").RefersToR1C1 = "=" & Target.Cells(1).Row
End Sub