Struggling with this one. Have a table with many columns but looking to apply the conditional formatting to a subset. Table looks like below. Number/name of columns are fixed but number of rows varies based on some user inputs. Below image shows the table
Table Image
With this table I am looking to apply the color scale conditional formatting on a row by row basis. The added wrinkle is the formatting needs to be dependent on the value in the column titled "Sign". Logic goes if Sign value in row is "+" then applies color scale with green for highest value, red for lowest and white for 50th percentile (used macro recorder to capture stock color scales in excel to produce code below). If Sign value in row is "-" then I reverse it with Red for highest value, green for lowest.
My code is as per below. Problem I'm facing is it is duplicating the formatting for each row MANY times and slowing down everything. Any ideas why its duplicating the formatting for each row?
Any help is GREATLY appreciated!
Dim Rng As Range
Dim cel As Range
Dim i As Integer
Application.ScreenUpdating = False
For Each Rng In Worksheets("Sheet1").Range("Table1[[Sign]:[TREND5]]").Rows
For Each cel In Rng.Cells
For i = 1 To Len(cel)
If cel.Value = "+" Then
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 = 7039480
.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 = 16776444
.TintAndShade = 0
End With
Rng.FormatConditions(1).ColorScaleCriteria(3).Type = _
xlConditionValueHighestValue
With Rng.FormatConditions(1).ColorScaleCriteria(3).FormatColor
.Color = 8109667
.TintAndShade = 0
End With
ElseIf cel.Value = "-" Then
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 = 16776444
.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 If
Next i
Next
Next
Application.ScreenUpdating = True
End Sub
Related
Conditional Formatting Condition:If selected cell("cel7") is not blank then put Black fill on it.
How can i modify my current code in such away that conditional formatting condition is used in cel7.
I tried to use xlnoblankscondition but i could not find any VBA examples of it on web.
P.S:As i have written all cel7 cell as C1,every condition will be true ie NOT BLANK.
x = ws.Range("A4").Value
y = ws.Range("A5").Value
ocol = 4
Set cel = Range("E6")
Set cel7 = cel.Offset(2, 0)
For m = 1 To x
For o = 1 To y
cel7.Value = "C1"
cel7.Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
Set cel7 = cel7.Offset(4, 0)
Next
Set cel = cel.Offset(0, ocol)
Set cel7 = cel7.Offset(0, ocol)
Next
I'm sorry as I'm still not clear on what you mean.
Anyway, I'm guessing that you want to coding the Conditional Formatting, just like when you do it manually.
I find the code below after I macro recording my manual step in Conditional Formatting.
I think the code in your condition maybe like this :
Sub test()
Cells.FormatConditions.Delete
cel7.Select
cf = cel7.Address(0, 0)
Selection.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=NOT(ISBLANK(" & cf & "))"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight1
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Application.WindowState = xlMaximized
End Sub
I try the code above by having cel7 variable refer to cell D10.
After I run the code, if I type something in cell D10, D10 fill black with white font.
If I clear the content of D10, D10 back to normal (no fill).
Also I try by having cel7 variable to a range D2 to D10.
If I type on any cell within D2:D10, the cell fill black with white font.
If I clear it, the cell back to normal.
But once again, maybe that's not what you want to achieve.
If I'm not mistaken read your code, it seems that your cel7 formatting is a non-contagious row. So please try your o loop like this one :
Cells.FormatConditions.Delete 'put this line before m loop
For m = 1 To x
For o = 1 To y
Cel7.Select
cf = Cel7.Address(0, 0)
Selection.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=NOT(ISBLANK(" & cf & "))"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight1
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Application.WindowState = xlMaximized
Set Cel7 = Cel7.Offset(4, 0)
Next o
In the code below I took out your Selection of Cel7. You can address the range directly. I also added variable declarations. Omitting them causes more work than it saves. For the rest of it, the cell color is applied if the cell is found not to be Empty.
Sub Macro1()
Dim Ws As Worksheet
Dim Cel As Range, Cel7 As Range
Dim Tmp As Variant
Dim oCol As Long
Dim x As Long, y As Long
Dim m As Long, o As Long
Set Ws = ActiveSheet
x = Ws.Range("A4").Value
y = Ws.Range("A5").Value
oCol = 4
Set Cel = Ws.Range("E6")
Set Cel7 = Cel.Offset(2, 0)
For m = 1 To x
For o = 1 To y
With Cel7
Tmp = "C1" ' avoid read/write to sheet multiple times
.Value = Tmp
If IsEmpty(Tmp) Then
.Interior.Pattern = xlNone
Else
.Interior.Color = vbBlack
End If
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
Set Cel7 = Cel7.Offset(4, 0)
Next o
Set Cel = Cel.Offset(0, oCol)
Set Cel7 = Cel7.Offset(0, oCol)
Next m
End Sub
I'm not sure if the heading is accurately describing what my query is, so I'll try my best to describe it here.
I have a sheet that keeps track of expenses and income and I have a macro that I use to insert check boxes into selected cells, link the checkbox to those cells and finally, apply a condition for a conditional format once the checkbox is checked and likewise if it is unchecked again.
Here is code that does that:
Sub:
Sub Insert_Checkbox_Link_Cell()
Dim rngCel, myCells As Range
Dim ChkBx As CheckBox
Dim cBx As Long
Set myCells = Selection
myCells.NumberFormat = ";;;"
Application.ScreenUpdating = False
For Each rngCel In myCells
With rngCel.MergeArea.Cells
If .Resize(1, 1).Address = rngCel.Address Then
Set ChkBx = ActiveSheet.CheckBoxes.Add(.Left, .Top, .Width, .Height)
With ChkBx
.Value = xlOff
.LinkedCell = rngCel.MergeArea.Cells.Address
.Text = ""
.Width = 18
.Top = rngCel.Top + rngCel.Height / 2 - ChkBx.Height / 2
.Left = rngCel.Left + rngCel.Width / 2 - ChkBx.Width / 2
.Select
'Function Call
Selection.OnAction = "Change_Cell_Colour"
End With
End If
End With
Next rngCel
If (Range(ChkBx.LinkedCell) = "True") Then
myCells.Interior.ColorIndex = 43
Else
myCells.Interior.ColorIndex = 48
End If
Application.ScreenUpdating = True
End Sub
Function:
Function Change_Cell_Colour()
Dim xChk As CheckBox
Dim clickedCheckbox As String
clickedCheckbox = Application.Caller
Set xChk = ActiveSheet.CheckBoxes(clickedCheckbox)
If xChk.Value = 1 Then
ActiveSheet.Range(xChk.LinkedCell).Interior.ColorIndex = 43
Else
ActiveSheet.Range(xChk.LinkedCell).Interior.ColorIndex = 48
End If
End Function
So how this works is, I select the range of cells I want to have the checkboxes in, then I run the macro and it inserts the checkboxes as stated above.
Now I am wanting to add a little more and I am not sure if it is possible.
In the image below, I have listed income and at the bottom is the total. So, as the money comes in, the checkbox is checked.
What I would like to do is this:
While the checkbox is UNCHECKED, I don't want the value in the cell to be added to the total count at the bottom.
When it is CHECKED, then the value in the cell should be added to the total count at the bottom.
Image 1: No Check Boxes
Image 2: Check Boxes Added
Image 3: One Check Box Checked
Image 4: 2 Checkboxes Checked
You could achieve this using Conditional Formatting and SUMIF formula to achieve this
I've used the following conditional formatting rules (You will need to change this for your ranges)
The conditional formatting is applied to both the cell fill and also the font text colour (to make the True/False be 'invisible')
In cell C6 (a merged range) I have the formula
=SUMIF($D$3:$D$5,TRUE,$C$3:$C$5)
Where cells in the D range contain the values of the linked cells for the checkboxes (i.e. True, False)and C range is the values you want to sum.
This is a much simpler approach then any VBA solution and personally, I'd remove the formatting of the cells from your vba above and just use the conditional formatting.
If you're looking for a VBA way to initiate this (except for the SUMIF formula) I've updated your below code to add the conditional formatting
Sub Insert_Checkbox_Link_Cell()
Dim rngCel, myCells As Range
Dim ChkBx As CheckBox
Dim cBx As Long
Set myCells = Selection
myCells.NumberFormat = ";;;"
Application.ScreenUpdating = False
For Each rngCel In myCells
With rngCel.MergeArea.Cells
If .Resize(1, 1).Address = rngCel.Address Then
Set ChkBx = ActiveSheet.CheckBoxes.Add(.Left, .Top, .Width, .Height)
With ChkBx
.Value = xlOff
.LinkedCell = rngCel.MergeArea.Cells.Address
.Text = ""
.Width = 18
.Top = rngCel.Top + rngCel.Height / 2 - ChkBx.Height / 2
.Left = rngCel.Left + rngCel.Width / 2 - ChkBx.Width / 2
End With
End If
End With
Next rngCel
With myCells
' Set default value
.Value2 = False
' Add conditional formatting for False value
With .FormatConditions
.Add Type:=xlExpression, Formula1:="=" & myCells.Cells(1).Address(False, True) & "=False"
End With
With .FormatConditions(.FormatConditions.Count)
.SetFirstPriority
With .Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 9868950
.TintAndShade = 0
.PatternTintAndShade = 0
End With
With .Font
.Color = -6908266
.TintAndShade = 0
End With
End With
' Add conditional formatting for True value
With .FormatConditions
.Add Type:=xlExpression, Formula1:="=" & myCells.Cells(1).Address(False, True) & "=True"
End With
With .FormatConditions(.FormatConditions.Count)
.SetFirstPriority
With .Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 52377
.TintAndShade = 0
.PatternTintAndShade = 0
End With
With .Font
.Color = -16724839
.TintAndShade = 0
End With
End With
End With
Application.ScreenUpdating = True
End Sub
You can give a value (eg: 1 for checked and 0 for unchecked) to the cell where the checkbox is added in your color change function. keep the cell's font color the same as the cell's fill color so that the value will be invisible to naked eyes. then in the total sum section, you can use sumif function.
My script works in its entirety but there's one section of it I want to "tone" up and simplify. I have three values that I'm removing highlight from if one of the cells meets a certain condition. I apply the same WITH statement to all three cells. It'd be nice to trim it to select all three values so I can reduce it to only one loop.
I'm including only the important part of the script for simplicity so ignore the missing definitions.
For Each rngCell In NetworkPatchRange
If InStr(rngCell.Value, "-") > 0 Then
rngCell.Select
With Selection.Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
rngCell.Offset(0, -1).Select
With Selection.Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
rngCell.Offset(0, -2).Select
With Selection.Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next
Avoid using Select in Excel VBA macros.
For Each rngCell In NetworkPatchRange
If cbool(InStr(1, rngCell.Value, chr(45))) Then
rngCell.offset(0, -2).resize(1, 3).interior.Pattern = xlNone
End If
Next
The recorded macro code for removing a highlight performs more actions than is actually necessary. Just set the .interior.Pattern to xlNone.
It may be prudent to remember that manually removing a cell's 'Fill' (aka highlight) does not apply to cells that have been highlighted with a conditional formatting rule.
How can I get headings "underproject" to be darker marked automatic? I can do it myself, but want it to happen automatic for all headings.
Before & After
Range("A6:L6,A7:D7").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight1
.TintAndShade = 0.249977111117893
.PatternTintAndShade = 0
End With
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
With Selection
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
You can do this with conditional formatting. Select the whole table column A to column G and add a new conditional formmating rule and choose the bottom option to enter a formula. enter =left($A1,4)="Unde" click the format button and choose the format you want.
Select the Columns A to C and create another conditional formatting rule and select formula. Enter =left($A1,4)="Navn" and set the format that you want.
this won't merge the cells but in my opinion it is better no keep the cells unmerged as it allows you to sort and filter the data if required.
It is possible using a Macro but you would have to loop through all the cells in column A looking for "Navn" and "Underproject" and use if statements to set the formats.
Code to delete rows based on heading
I can't tell from your comment what it is exactly that you want to delete but to can change the critera to suit your requirements.
IMPORTANT: make sure that you make a backup copy of your data before running this macro as changes made by the macro cannot be undone.
Sub DeleteEx()
Dim intRow As Integer
Dim strContinue As String
Dim bolDelete As Boolean 'true or false
intRow = 2
strContinue = Cells(intRow, 1) ' the value in A2
bolDelete = False
Do While strContinue <> "" ' this loop will continue down each row as long as there is a value in column A
If Left(strContinue, 5) = "Under" Or Left(strContinue, 5) = "Navn:" Then 'change this to match your criteria
'delete the current row
Rows(intRow & ":" & intRow).Delete Shift:=xlUp
intRow = intRow - 1 ' because we deleted a row
End If
intRow = intRow + 1
strContinue = Cells(intRow, 1)
Loop
End Sub
I have two Excel sheets where 6 of the 30 columns have databars in them. They all use the same code as below.
But two of the columns in one of the sheets do not display the databar. When I look at Manage Rules in conditional formatting, I do see the databar there.
Then I create several files from that sheet based on different sorts - product, region, etc. and these files also inconsistently do not show the databar.
I am using Excel 2010 32-bit on Windows 7 64-bit.
What am I doing wrong? Thanks in advance for your help.
Public Function formatDatabar(wbkO As Workbook, wks As Worksheet, colNo As Integer)
Dim i As Integer, ctr As Integer, col As Integer
wbkO.Activate
Set wks = wbkO.Worksheets(wks.Name)
wks.Activate
ctr = findLastRow(wks.Name)
col = findLastCol(wks.Name)
wbkO.Activate
wks.Activate
wks.Range(wks.Cells(5, 1), wks.Cells(ctr, col)).Select
With Selection
.Cells.Font.Size = "8"
.Cells.Font.Bold = False
.Cells.Font.Name = "Calibri"
.VerticalAlignment = xlCenter
End With
wks.Range(wks.Cells(5, colNo), wks.Cells(ctr, colNo)).Select
Selection.FormatConditions.AddDatabar
Selection.FormatConditions(Selection.FormatConditions.Count).ShowValue = True
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1)
.MinPoint.Modify newtype:=xlConditionValueAutomaticMin
.MaxPoint.Modify newtype:=xlConditionValueAutomaticMax
End With
With Selection.FormatConditions(1).BarColor
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.13012579
End With
Selection.FormatConditions(1).BarFillType = xlDataBarFillGradient
Selection.FormatConditions(1).Direction = xlContext
Selection.FormatConditions(1).NegativeBarFormat.ColorType = xlDataBarColor
Selection.FormatConditions(1).BarBorder.Type = xlDataBarBorderSolid
Selection.FormatConditions(1).NegativeBarFormat.BorderColorType = _
xlDataBarColor
With Selection.FormatConditions(1).BarBorder.Color
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.13012579
End With
Selection.FormatConditions(1).AxisPosition = xlDataBarAxisAutomatic
With Selection.FormatConditions(1).AxisColor
.Color = 0
.TintAndShade = 0
End With
With Selection.FormatConditions(1).NegativeBarFormat.Color
.Color = 255
.TintAndShade = 0
End With
With Selection.FormatConditions(1).NegativeBarFormat.BorderColor
.Color = 255
.TintAndShade = 0
End With
End Function
In the 2472nd row, the % was very high, making all others almost nothing. This caused the databar for all other rows to not display.
Thanks Scott for your help.