I have the following problem. I want to call a soubroutine for changing the background color for a cell range. The cell range is calculated with cells(1,1) and then the address is calculated to receive A1.
Before the subroutine is called I get the addresses for my cells like this:
Range1 = cells(4, 4).Address(RowAbsolute:=False, ColumnAbsolute:=False)
Range2 = cells(4, CellAmount - 1).Address(RowAbsolute:=False, ColumnAbsolute:=False)
I thought I need this because the subroutine is declared like this:
Sub SetBGLightGrey(cells As String)
range(cells).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 15921906
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Range 1 and Range 2 are strings and I concat it to a range declaration:
RangeArea = """" & Range1 & ":" & Range2 & """"
When I call my subroutine like this:
Call SetBGLightGrey(RangeArea)
I get the following error-message:
"Run-time error '1004': Method 'Range' of object '_Global' failed. I don't understand it because if I call the subroutine with the correct cell values:
Call SetBGLightGrey("D4:K4")
it works. It is string and of the same value. This simply cannot be can it?
You do not need quotes around RangeArea.
RangeArea = Range1 & ":" & Range2
But then, why would you want to pass ranges around as strings and then convert them back to ranges? Pass the range objects all the time.
Sub SetBGLightGrey(byval cells as range)
With cells.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 15921906
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
SetBGLightGrey range(cells(4, 4), cells(4, CellAmount - 1))
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.
I need to a create similar macro for duplicates (see below). The user will be able to choose a column symbol and then all the duplicates from the chosen column will be highlighted with color. I do not how to do that.
Below is the same idea but with empty cells.
Could you help? THX!
Sub EmptyCells()
Dim kol As String
Dim ost As Long
ost = Cells(Rows.Count, "A").End(xlUp).Row
kol = InputBox("Enter column symbol: B, C...etc.", "Column symbol", "B")
If kol = vbNullString Then Exit Sub
If IsNumeric(kol) Then
MsgBox "You entered number, please enter column symbol", _
vbInformation, "ERROR"
Exit Sub
End If
If ost < 5 Then Exit Sub
Range("A5:E" & ost).Interior.Color = xlNone
Range(Cells(5, kol), Cells(ost, kol)).SpecialCells(xlCellTypeBlanks).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Please make the following changes as per comments in your program. After changes it works for me. Assuming I have cleared existing formats on the worksheet and it is going to be first format condition.
Sub DuplicateCells() ' changed sub name
Dim kol As String
Dim ost As Long
ost = Cells(Rows.Count, "A").End(xlUp).Row
kol = InputBox("Enter column symbol: B, C...etc.", "Column symbol", "B")
If kol = vbNullString Then Exit Sub
If IsNumeric(kol) Then
MsgBox "You entered number, please enter column symbol", _
vbInformation, "ERROR"
Exit Sub
End If
If ost < 5 Then Exit Sub
Range("A5:E" & ost).Interior.Color = xlNone
Range(Cells(5, kol), Cells(ost, kol)).Select ' Remove SpecialCells(xlCellTypeBlanks)
Selection.FormatConditions.AddUniqueValues 'Add this line
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority 'Add this line
Selection.FormatConditions(1).DupeUnique = xlDuplicate 'Add this line
With Selection.FormatConditions(1).Interior ' add FormatConditions(1)
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
End Sub
Results on my sample data are shown.
This is a snippet of a much larger code. I have the following code that I am trying to use to insert a conditional format in a range of cells where the active column can change. I would like the conditional format formula to update as the active column changes. f1 = "=IF(AND(MID(CTO_1,6,1)=""W"",NOT(ISBLANK(RC[-7]))),RC12<>RC19,RC11<>RC19)"'this works correctly, but when I try to modify it to be dynamic it doesn't work.
I have spent a many hours searching for a solution with no luck
Private Sub test()
Worksheets("C9 map").Activate
Dim lstCol, lstRow, nCol As Integer
Dim cRng3, cRng2, cRng1, strRow As Variant
lstCol = LastRowColumn("c") ' function to find last column
lstRow = LastRowColumn("r") ' function to find last row
nCol = lstCol + 1
strRow = 5
Range(Columns(nCol).Rows(strRow), Columns(nCol).Rows(strRow)).Activate
Dim actCol, hdrRow5 As Variant
actCol = ActiveCell.Column
Dim f1 As String
hdrRow5 = 5
cRng1 = "RC" & 11 'Column K = 11
cRng2 = "RC" & 12 'Column L = 12
cRng3 = "RC" & ActiveCell.Column
f1 = "=IF(AND(MID(CTO_1,6,1)=""W"",NOT(ISBLANK(RC[-7]))),cRng2<>cRng3,cRng1<>cRng3)"
With Columns(actCol)
.ColumnWidth = 20
.HorizontalAlignment = xlCenter
.WrapText = True
End With
With Range(Columns(actCol).Rows(hdrRow5), Columns(actCol).Rows(lstRow))
.FormatConditions.Add Type:=xlExpression, Formula1:=f1
With .FormatConditions(1).Font
.Bold = True
.Italic = False
.Color = -16776961
.TintAndShade = 0
End With
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
End Sub
The issue comes from the fact that your cRng1, cRng2 and cRng3 are given as string in your code, because of the "".
Change your line to:
f1 = "=IF(AND(MID(CTO_1,6,1)=""W"",NOT(ISBLANK(RC[-7])))," & cRng2 & "<>" & cRng3 & "," & cRng1 & "<>" & cRng3 & ")"
I'm trying to make a macro that select colors a group of 5 cells
So basically it goes:
clear, yellow, blue, clear, yellow, blue, ...
Sub ColorBanding()
Dim num As Integer
For i = 2 To 50
Dim range As String
range("A" + Str(i) + ":E" + Str(i)).Select
If i Mod 3 = 0 Then
Cells(1, 1).Select
' Yellow
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
ElseIf i Mod 3 = 2 Then
' Blue
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent1
.TintAndShade = 0.399975585192419
.PatternTintAndShade = 0
End With
End If
Next i
End Sub
I'm having trouble with this line:
"range("A" + Str(i) + ":E" + Str(i)).Select"
Example on evaluation for i = 2:
outputs: "A 2:E 2"
should be: "A2:E2"
The technical error I get is:
"Expected an array"
Is there a better way of doing this?
And is there a way to get this way to work right?
This is correct syntax. Also don't select/activate anything as it only slows things down. What use is 'num'?
Sub test()
Dim num As Integer, MyRange As Range, i As Integer
For i = 2 To 50
Set MyRange = Range("A" & i & ":E" & i)
MsgBox MyRange.Address 'Delete this test line
With MyRange.Cells(1, 1).Interior
If (i Mod 3) = 0 Then
'Yellow
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
ElseIf i Mod 3 = 2 Then
'Blue
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent1
.TintAndShade = 0.399975585192419
.PatternTintAndShade = 0
End If
End With
Next i
End Sub
The problem is here
Dim num As Integer
For i = 2 To 50
Dim range As String
range("A" + Str(i) + ":E" + Str(i)).Select
If i Mod 3 = 0 Then
Cells(1, 1).Select
Please put all dims at the top
dim range as string? what where you thinking, a range is a range. As in a lumb of cells on a worksheet.
range is a reserved word, don't use it as a variable name, use something like MyRange instead.
Objects (like range, worksheet etc..) can only be assigned in a Set object = reference_to_other_object_of_the_same_type statement, see below.
Cells(1,1) relative to what? The default object is ActiveWorksheet and ActiveWorksheet.Cells(1,1) is permanently fixed to cell "A1". MyRange.Cells(1,1) on the other hand can move around.
In VBA '&' concatenates strings, the '+' operator only works on numbers
Change it to:
Dim num As Integer
Dim MyRange as Range
Dim i as Integer
For i = 2 To 50
Set MyRange = range("A" & Str(i) & ":E" & Str(i))
MyRange.Select
If (i Mod 3) = 0 Then
MyRange.Cells(1, 1).Select
...
Haven't tested the code yet, but I'm pretty sure it is close.