|
Excel does not have any built-in worksheet functions for working with
the colors of cells or fonts. If you want to read or test the color of a
cell, you have to use VBA procedure. This page describes several functions
for counting and summing cells based on the color of the font or
background. All of these functions use the ColorIndex
property. Excel worksheets can't have the vast amount of colors that
other applications support. In Excel, you are limited to the 56 colors
that are part of the Color Pallet for the workbook. You may assign any
color you want to an entry in the Color Pallet, but each workbook is limited to
a total of 56 different colors.
The ColorIndex of a range is simply the
offset of the color into the Color Pallet table. For example, ColorIndex
6 is simply the sixth entry in the Color Pallet. You can change the
default colors in the Color Pallet of a workbook by using the Colors
array. For example, to change ColorIndex
6 from yellow (the default) to red, use the following code:
ThisWorkbook.Colors(6) = RGB(255,0,0)
If you use the Color property of a cell's
Font or Interior, Excel will change the value you assign to the closest match color
that exists in the current Color Pallet.
NOTE: When you change the background or font color of a
cell, Excel does not consider this to be changing the value of the cell.
Therefore, it will not recalculate the worksheet, nor will it trigger a
Worksheet_Change event procedure. This means that the values returned by
these functions may not be correct immediately after you change the color of a
cell. They will not return an updated value until you recalculate the
worksheet by pressing ALT+F9 or by changing the actual value of a cell.
There is no practical work-around to this. You could use the
Worksheet_SelectionChange event procedure to force a calculation, but this could
have a serious and detrimental impact on performance.
NOTE: These functions will not detect colors that are
applied by Conditional Formatting. They will read only the default colors
of the cell and its text. For information about returning colors in
effect by conditional formatting, see the Conditional
Formatting Colors page.
It is important to remember that if a cell has no color assigned to it, and
therefore appears to be white, the ColorIndex is equal to the constant
xlColorIndexNone, or -4142. It does not equal 2, the
default ColorIndex value for white. Similarly, text that has not been
assigned a color, and therefore appears to be black, has a ColorIndex value
equal to the constant
xlColorIndexAutomatic, or -4105. It does not equal 1,
the default ColorIndex value for black.
The sections below describe a number of VBA functions for working with cell
colors.
Returning The ColorIndex Of A Cell
The following function will return the ColorIndex
property of a cell. InRange
is the cell to examine, OfText
indicates whether to return the ColorIndex
of the Font (if True) or the
Interior (if False). If
InRange
contains more than one cell, the first cell (InRange(1,1))
of the range is tested.
Function CellColorIndex(InRange As Range, Optional
_
OfText As Boolean = False) As Integer
'
' This function returns the ColorIndex value of a the Interior
' (background) of a cell, or, if OfText is true, of the Font in the cell.
'
Application.Volatile True
If OfText = True Then
CellColorIndex = InRange(1,1).Font.ColorIndex
Else
CellColorIndex = InRange(1,1).Interior.ColorIndex
End If
End Function
You can call this function from a worksheet cell with a formula like
=CELLCOLORINDEX(A1,FALSE)
Counting Cells With A Specific Color
The following function will return the number of cells in a range that have
either an Interior (background) or Font of a specified color.
InRange
is the range of cells to examine, WhatColorIndex
is the ColorIndex value to count, and
OfText
indicates whether to return the
ColorIndex of the Font (if OfText
is True) or the
Interior (if OfText is False or
omitted).
Function CountByColor(InRange As Range,
_
WhatColorIndex As
Integer, _
Optional OfText As Boolean = False) As Long
'
' This function return the number of cells in InRange with
' a background color, or if OfText is True a font color,
' equal to WhatColorIndex.
'
Dim Rng As Range
Application.Volatile True
For Each Rng In InRange.Cells
If OfText = True Then
CountByColor = CountByColor - _
(Rng.Font.ColorIndex = WhatColorIndex)
Else
CountByColor = CountByColor - _
(Rng.Interior.ColorIndex = WhatColorIndex)
End If
Next Rng
End Function
You can call this function from a worksheet cell with a formula like
=COUNTBYCOLOR(A1:A10,3,FALSE)
Summing The Values Of Cells With A Specific
Color
The following function will return the sum of cells in a
range that have either an Interior (background) or Font of a specified
colorindex. InRange is the range of cells to
examine, WhatColorIndex
is the ColorIndex value to count, and OfText
indicates whether to return the ColorIndex of the Font (if True) or the
Interior (if False).
Function SumByColor(InRange As Range, WhatColorIndex As Integer, _
Optional OfText As Boolean = False) As Double
'
' This function return the SUM of the values of cells in
' InRange with a background color, or if OfText is True a
' font color, equal to WhatColorIndex.
'
Dim Rng As Range
Dim OK As Boolean
Application.Volatile True
For Each Rng In InRange.Cells
If OfText = True Then
OK = (Rng.Font.ColorIndex = WhatColorIndex)
Else
OK = (Rng.Interior.ColorIndex = WhatColorIndex)
End If
If OK And IsNumeric(Rng.Value) Then
SumByColor = SumByColor + Rng.Value
End If
Next Rng
End Function
You can call this function from a worksheet cell with a formula like
=SUMBYCOLOR(A1:A10,3,FALSE)
Summing The Values Of Cells Based On The
Color Of Other Cells
The following function will return the sum of cells in a
range which correspond to cells in another range that have either an Interior
(background) or Font of a specified color. InRange
is the range of cells to examine, WhatColorIndex
is the ColorIndex value to count, SumRange
is the range of value to sum, and OfText
indicates whether to return the ColorIndex of the Font (if True) or the
Interior (if False).
Function SumIfByColor(InRange As Range,
_
WhatColorIndex As Integer, SumRange As Range, _
Optional OfText As Boolean = False) As Variant
'
' This function will return the SUM of the values of cells in
' SumRange where the corresponding cell in InRange has a background
' color (or font color, if OfText is true) equal to WhatColorIndex.
'
Dim OK As Boolean
Dim Ndx As Long
Application.Volatile True
If (InRange.Rows.Count <> SumRange.Rows.Count) Or _
(InRange.Columns.Count <> SumRange.Columns.Count) Then
SumIfByColor = CVErr(xlErrRef)
Exit Function
End If
For Ndx = 1 To InRange.Cells.Count
If OfText = True Then
OK = (InRange.Cells(Ndx).Font.ColorIndex =
WhatColorIndex)
Else
OK = (InRange.Cells(Ndx).Interior.ColorIndex =
WhatColorIndex)
End If
If OK And IsNumeric(SumRange.Cells(Ndx).Value) Then
SumIfByColor = SumIfByColor + SumRange.Cells(Ndx).Value
End If
Next Ndx
End Function
You can call this function from a worksheet cell with a formula like
=SUMIFBYCOLOR(A1:A10,3,B1:B10,FALSE)
Getting The Range Of Cells With A Specific Color
The following function will return a Range object
consisting of those cells in a range that have either an Interior (background)
or Font of a specified color.
InRange is
the range of cells to examine, WhatColorIndex
is the ColorIndex value to count, and OfText
indicates whether to use the ColorIndex of the Font (if OfText
is True) or the
Interior (if OfText False or
omitted). This function uses the AddRange
function to combine two ranges into a single range, without the possible
problems of the Application.Union
method. See AddRange,
below, for more details about this function.
Function RangeOfColor(InRange As Range,
_
WhatColorIndex As Integer, _
Optional OfText As Boolean = False) As Range
'
' This function returns a Range of cells in InRange with a
' background color, or if OfText is True a font color,
' equal to WhatColorIndex.
'
Dim Rng As Range
Application.Volatile True
For Each Rng In InRange.Cells
If OfText = True Then
If (Rng.Font.ColorIndex =
WhatColorIndex) = True Then
Set RangeOfColor =
AddRange(RangeOfColor, Rng)
End If
Else
If (Rng.Interior.ColorIndex =
WhatColorIndex) = True Then
Set RangeOfColor =
AddRange(RangeOfColor, Rng)
End If
End If
Next Rng
End Function
The following function will return the address, as a
string, of the range returned by RangeOfColor.
Function AddressOfRangeOfColor(InRange As Range, _
WhatColorIndex As Integer, _
Optional OfText As Boolean = False) As String
'
' This function returns the address of the result range of RangeOfColor.
'
Dim Rng As Range
Set Rng = RangeOfColor(InRange, WhatColorIndex, OfText)
If Rng Is Nothing Then
AddressOfRangeOfColor = ""
Else
AddressOfRangeOfColor = Rng.Address
End If
End Function
Getting Range Of A Cell With A Specific Color
The following function will return a Range object
consisting of the cell in a range that has either an Interior (background) or
Font of a specified color. InRange is the
range of cells to examine, WhatColorIndex
is the ColorIndex value to count, FindWhich
indicates which cell to return, and OfText
indicates whether to return the ColorIndex of the Font (if True) or the
Interior (if False). The value of FindWhich
can be 0 to return the address of last cell with the specified color, or any
positive integer to return that occurance (e.g., 3 to return the third occurance).
Function FindColor(InRange As Range, WhatColorIndex As Integer, _
FindWhich As Long, Optional OfText As Boolean = False) As Range
'
' This function returns the Range of a cell in InRange with a
' background color, or if OfText is True a font color, equal
' to WhatColorIndex. Which cell address is returned depends on
' the value of FindWhich:
' 0 = last occurance
' 1 to n = the first, second, etc, nth occurance.
'
Dim Rng As Range
Dim Addr As String
Dim OK As Boolean
Dim Ndx As Long
For Each Rng In InRange
If OfText = True Then
OK = (Rng.Font.ColorIndex = WhatColorIndex)
Else
OK = (Rng.Interior.ColorIndex = WhatColorIndex)
End If
If OK Then
Ndx = Ndx + 1
If FindWhich = 0 Then
Set FindColor = Rng
Else
If FindWhich = Ndx Then
Set FindColor = Rng
Exit Function
End If
End If
End If
Next Rng
End Function
The following function will return the address, as a
string, of the range returned by .
Function AddressOfFindColor(InRange As Range,
_
WhatColorIndex As
Integer, FindWhich As Long, _
Optional OfText As Boolean = False) As String
'
' This function returns the address of the result of FindColor.
'
Dim Rng As Range
Set Rng = FindColor(InRange, WhatColorIndex, FindWhich, OfText)
If Rng Is Nothing Then
AddressOfFindColor = ""
Else
AddressOfFindColor = Rng.Address
End If
End Function
AddRange
The following function will return a Range object that is
the logical union of two ranges. Unlike the Application.Union method,
AddRange will not return duplicate cells in the result. For example,
Application.Union(Range("A1:B3"), Range("B3:D5")).Cells.Count
will return 15, since B3 is counted twice, once in each
range.
AddRange(Range("A1:B3"), Range("B3:D5")).Cells.Count
willl return 14, counting B3 only once.
Function AddRange(ByVal Range1 As Range,
_
ByVal Range2 As Range) As Range
Dim Rng As Range
If Range1 Is Nothing Then
If Range2 Is Nothing Then
Set AddRange = Nothing
Else
Set AddRange = Range2
End If
Else
If Range2 Is Nothing Then
Set AddRange = Range1
Else
Set AddRange = Range1
For Each Rng In Range2
If
Application.Intersect(Rng, Range1) Is Nothing Then
Set AddRange = Application.Union(AddRange, Rng)
End If
Next Rng
End If
End If
End Function
Sorting By Color
For information about sorting cells based on colors, please read
Sorting By Color.
RGB Colors
A color is defined by a number made up of the Red, Green, and Blue components
of the color. To convert the individual components to a color value, you
can use the VBA function RGB. For example, ActiveCell.Interior.Color
= RGB(100,123, 50)However, there is no built-in
method to break out the individual color components from a color value.
The procedure below will accomplish this. Sub GetRGB(RGB As Long, ByRef Red As Integer, _
ByRef Green As Integer, ByRef Blue As Integer)
Red = RGB And 255
Green = RGB \ 256 And 255
Blue = RGB \ 256 ^ 2 And 255
End Sub
Notice that the Red, Green, and Blue variables are
passed by reference. The procedure will put the color values in these
variables. For example, you can use this procedure as follows: Dim R As Integer
Dim G As Integer
Dim B As Integer
GetRGB ActiveCell.Interior.Color, R, G, B
MsgBox "The active cell has these color components:" & vbCrLf & _
"Red: " & R & vbCrLf & _
"Green: " & G & vbCrLf & _
"Blue: " & B
|