What can you learn here?
- ramp color scales
- gradient between colors
- Use a ramp library

Generalized Color Ramps
If you read A tagCloud in Outlook, How to create a tag cloud or Create a heatmap in Excel you would have seen reference to a heatmap scale. This is specific form of color ramp that calculates a color ranging from blue through red depending on it’s value compared to the rest of the range it is in. Here we will look at creating a generalized color ramp, and an extensible VBA library of useful ramps.
As usual this code is implemented in the cDataSet.xlsm module downloadable from Download Complete Projects. There is a Google Apps Script version of this library if you are a Google Docs user. See Charts and color ramps for how to make interesting charts using color ramps
If you are interested in creating maps or shapes with heatmaps, here’s a one liner to do it.
How it works
You provide 2 or more colors, and the difference between their red, green and blue component values is calculated. A single RGB color is provided that you can use to represent the input value.
Example Color ramps
Here is the code to produce the ramps shown above.
Public Sub testHeatMapScaleRamp()
Dim m As Long, n As Long, r As Range
Set r = Sheets("heatmapramp").Range("a1")
r.Worksheet.Cells.Interior.color = vbWhite
Const npoints = 200
For m = 0 To npoints
r.Offset(, m).Interior.color = _
rampLibraryRGB("heatmap", 0, npoints, m)
r.Offset(1, m).Interior.color = _
rampLibraryRGB("heatmaptowhite", 0, npoints, m)
r.Offset(2, m).Interior.color = _
rampLibraryRGB("blacktowhite", 0, npoints, m)
r.Offset(3, m).Interior.color = _
rampLibraryRGB("whitetoblack", 0, npoints, m)
r.Offset(4, m).Interior.color = _
rampLibraryRGB("hotinthemiddle", 0, npoints, m)
r.Offset(5, m).Interior.color = _
rampLibraryRGB("candylime", 0, npoints, m)
r.Offset(6, m).Interior.color = _
rampLibraryRGB("heatcolorblind", 0, npoints, m)
r.Offset(7, m).Interior.color = _
rampLibraryRGB("gethotquick", 0, npoints, m)
r.Offset(8, m).Interior.color = _
rampLibraryRGB("greensweep", 0, npoints, m)
Next m
End Sub
Here is the colorramp library defining them
Public Function rampLibraryRGB(sName As String, min As Variant, _
max As Variant, Value As Variant, _
Optional brighten As Double = 0) As Long
Select Case Trim(LCase(sName))
Case “heatmaptowhite”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlue, vbGreen, vbYellow, vbRed, vbWhite), , _
brighten)
Case “heatmap”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlue, vbGreen, vbYellow, vbRed), , _
brighten)
Case “blacktowhite”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlack, vbWhite), , brighten)
Case “whitetoblack”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbWhite, vbBlack), , brighten)
Case “hotinthemiddle”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlue, vbGreen, vbYellow, vbRed, _
vbYellow, vbGreen, vbBlue), , brighten)
Case “candylime”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(RGB(255, 77, 121), RGB(255, 121, 77), _
RGB(255, 210, 77), RGB(210, 255, 77)), , _
brighten)
Case “heatcolorblind”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlack, vbBlue, vbRed, vbWhite), , brighten)
Case “gethotquick”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlue, vbGreen, vbYellow, vbRed), _
Array(0, 0.1, 0.25, 1), brighten)
Case “greensweep”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(RGB(153, 204, 51), RGB(51, 204, 179)), , _
brighten)
Case “terrain”
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlack, RGB(0, 46, 184), RGB(0, 138, 184), _
RGB(0, 184, 138), _
RGB(138, 184, 0), RGB(184, 138, 0), _
RGB(138, 0, 184), vbWhite), , _
brighten)
Case Else
Debug.Assert False
End Select
End Function
ColorRamp Function
Intermediate colors
Aside from the min, max and value that you want the color calculated for, you can also provide an array of as many colors as you want. colorRamp will use these to ‘pass through’ – so for example a heatmap would be Array(vbBlue, vbGreen, vbYellow, vbRed). To get the exact effect you want, just add some more intermediate colors.
Ramp speed
By default, the rate at which the colors evolve between intermediate or ‘milestone’ colors is evenly divided. However if you wanted to modify that – for example the library entry ‘gethotquick’, spends longer on the red tone colors than on the blue – you can specify the ramp up speed for each milestone color as below –
Case "gethotquick"
rampLibraryRGB = colorRamp(min, max, Value, _
Array(vbBlue, vbGreen, vbYellow, vbRed), _
Array(0, 0.1, 0.25, 1))
Code
Here us the code for the colorRamp function.
Public Function colorRamp(min As Variant, _
max As Variant, Value As Variant, _
Optional mileStones As Variant, _
Optional fractionStones As Variant, _
Optional brighten As Double = 1)
‘ create a value from a colorramp going through the array of milestones
Dim spread As Double, ratio As Double, red As Double, _
green As Double, blue As Double, j As Long, _
lb As Long, ub As Long, cb As Long, r As Double, i As Long
‘—-defaults and set up milestones on ramp
Dim ms() As Long
Dim fs() As Double
If IsMissing(mileStones) Then
ReDim ms(0 To 4)
ms(0) = vbBlue
ms(1) = vbGreen
ms(2) = vbYellow
ms(3) = vbRed
ms(4) = vbWhite
Else
ReDim ms(0 To UBound(mileStones) – LBound(mileStones))
j = 0
For i = LBound(mileStones) To UBound(mileStones)
ms(j) = mileStones(i)
j = j + 1
Next i
End If
‘ tedious this is
lb = LBound(ms)
ub = UBound(ms)
cb = ub – lb + 1
‘ only 1 milestone – thats the color
If cb = 1 Then
colorRamp = ms(lb)
Exit Function
End If
If Not IsMissing(fractionStones) Then
If UBound(fractionStones) – LBound(fractionStones) <> _
cb – 1 Then
MsgBox (“no of fractions must equal number of steps”)
Exit Function
Else
ReDim fs(lb To ub)
j = lb
For i = LBound(fractionStones) To UBound(fractionStones)
fs(j) = fractionStones(i)
j = j + 1
Next i
End If
Else
ReDim fs(lb To ub)
For i = lb + 1 To ub
fs(i) = i / (cb – 1)
Next i
End If
‘spread of range
spread = max – min
Debug.Assert spread >= 0
ratio = (Value – min) / spread
Debug.Assert ratio >= 0 And ratio <= 1
‘ find which slot
For i = lb + 1 To ub
If ratio <= fs(i) Then
r = (ratio – fs(i – 1)) / (fs(i) – fs(i – 1))
red = rgbRed(ms(i – 1)) + (rgbRed(ms(i)) – rgbRed(ms(i – 1))) * r
blue = rgbBlue(ms(i – 1)) + (rgbBlue(ms(i)) – rgbBlue(ms(i – 1))) * r
green = rgbGreen(ms(i – 1)) + (rgbGreen(ms(i)) – rgbGreen(ms(i – 1))) * r
colorRamp = RGB(lumRGB(red, brighten), _
lumRGB(green, brighten), _
lumRGB(blue, brighten))
Exit Function
End If
Next i
Debug.Assert False
End Function
Private Function lumRGB(rgbCom As Double, brighten As Double) As Double
Dim x As Double
x = rgbCom * brighten
If x > 255 Then x = 255
If x < 0 Then x = 0
lumRGB = x
End Function
Public Function rgbRed(rgbColor As Long) As Long
rgbRed = rgbColor Mod &H100
End Function
Public Function rgbGreen(rgbColor As Long) As Long
rgbGreen = (rgbColor \ &H100) Mod &H100
End Function
Public Function rgbBlue(rgbColor As Long) As Long
rgbBlue = (rgbColor \ &H10000) Mod &H100
End Function
Summary
For more tips like this, take a look at Get Started Snippets In the meantime why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available. You can also submit anything you want considered for publication, including any nice color ramps you come up, with on this site to our forum. There is a Google Apps Script version of this library if you are a Google Docs user. See Charts and color ramps for how to make interesting charts using color ramps.
Related pages