对于图表而言,颜色至关重要。所谓着色,怎么着,是技术问题;着什么色,是艺术问题。本节介绍着色和配色的基础知识,以及怎么给不同类型的图形元素进行着色。[大谦Excel,dqexcel点com]
颜色的表示
关于图形的颜色,Excel提供了4种设置方法,即RGB着色、主题颜色着色、配色方案着色和索引着色。
图形对象,不管是线形对象还是面对象,它们的BackColor属性和ForeColor属性都会返回一个ColorFormat对象,该对象提供了RGB, ObjectThemeColor, SchemeColor等属性,用它们设置RGB着色、主题颜色着色和配色方案着色。
一、RGB颜色着色
所谓RGB颜色着色,就是用红色、绿色和兰色分量来定义颜色。使用图形对象的颜色相关的属性设置RGB颜色。如果习惯于指定RGB分量来设置颜色,可以使用xlwings.utils模块中的rgb_to_int方法将类似(255,0,0)的RGB分量指定转换为整型值,然后设置给Color属性。还可以将颜色相关属性的值设置为10进制整数或16进制整数。
16进制整数方式也是使用红色、绿色和兰色三种颜色混合得到新的颜色。表示颜色的16进制整数类似于0xFF0000的形式。
表1-7中列出了一些常用颜色的10进制整数、16进制整数和RGB表示。
表1-7 一些颜色的16进制整数和RGB定义
| 红 | 绿 | 蓝 | 10进制整数 | 16进制整数 | 颜色 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0x000000 | 黑色 |
| 255 | 255 | 255 | 16777215 | 0xFFFFFF | 白色 |
| 255 | 0 | 0 | 16711680 | 0xFF0000 | 红色 |
| 0 | 255 | 0 | 65280 | 0x00FF00 | 绿色 |
| 0 | 0 | 255 | 255 | 0x0000FF | 兰色 |
| 255 | 255 | 0 | 16776960 | 0xFFFF00 | 黄色 |
| 255 | 0 | 255 | 16711935 | 0xFF00FF | 粉红 |
| 0 | 255 | 255 | 65535 | 0x00FFFF | 青色 |
| 128 | 128 | 128 | 8421504 | 0x808080 | 灰色 |
| 128 | 0 | 0 | 8388608 | 0x800000 | 深红色 |
| 255 | 158 | 102 | 16777478 | 0xFF9E66 | 紫铜色 |
| 125 | 255 | 212 | 8236403 | 0x7CFFD3 | 碧绿色 |
下面代码中ForeColor属性返回一个ColorFormat对象,用它的RGB属性设置RGB分量表示的颜色。
shp.Fill.ForeColor.RGB = RGB(0, 255, 0)
shp.Line.ForeColor.RGB = RGB(0, 0, 255)
下面代码将一个表示颜色的10进制整数,也就是xw.utils.rgb_to_int()函数的结果赋给RGB属性。
shp.Fill.ForeColor.RGB = 65280
shp.Line.ForeColor.RGB = 16711680
也可以直接将一个十六进制整数赋给RGB属性。
shp.Line.ForeColor.RGB = &HFF0000&
二、主题颜色着色
Excel提供了10余种主题颜色,如表1-8中所示。使用这些主题颜色,可以很方便地给图形着色。
表1-8 主题颜色
| 名 称 | 值 | 说 明 |
|---|---|---|
| xlThemeColorAccent1 | 5 | Accent1 |
| xlThemeColorAccent2 | 6 | Accent2 |
| xlThemeColorAccent3 | 7 | Accent3 |
| xlThemeColorAccent4 | 8 | Accent4 |
| xlThemeColorAccent5 | 9 | Accent5 |
| xlThemeColorAccent6 | 10 | Accent6 |
| xlThemeColorDark1 | 1 | Dark1 |
| xlThemeColorDark2 | 3 | Dark2 |
| xlThemeColorFollowedHyperlink | 12 | Followed hyperlink |
| xlThemeColorHyperlink | 11 | Hyperlink |
| xlThemeColorLight1 | 2 | Light1 |
| xlThemeColorLight2 | 4 | Light2 |
对于图形对象,使用ForeColor属性和BackColor属性返回的ColorFormat对象的ObjectThemeColor属性,进行主题颜色着色。
shp.Fill.ForeColor.ObjectThemeColor = 10
shp.Line.ForeColor.ObjectThemeColor = 3
三、配色方案着色
利用Excel提供的配色方案中的颜色,也可以给图形对象着色。对于图形对象, ForeColor属性和BackColor属性返回的ColorFormat对象有一个SchemeColor属性,而配色方案中的每个颜色都有一个索引号,将它指定给SchemeColor属性即可。
shp.Fill.ForeColor.SchemeColor = 3
shp.Line.ForeColor.SchemeColor = 4
四、索引着色
索引着色需要两张表,第一张表中曲面的每个数据点对应一个索引值,第二张表中每个索引值对应一种颜色,称为颜色查找表,如图1-14所示。两张表通过索引值建立数据点和颜色值之间的映射关系。
图1-14 颜色查找表
索引着色常常用于控件和字体的着色。下面将工作表sht中单元格C3的字体颜色设置为红色。
sht.Range(“C3”).Font.ColorIndex = 3
sht.Range(“C3”).Value = “Hello”
1.3.5小节将在Excel中引入MATLAB和Python中经常使用的颜色查找表。使用它们,可以很方便地对一组图形对象进行渐变着色。
下面的代码绘制复合线形图,并用不同的方法给图元对象着色。完整代码见:Samples->ch04 美化Excel图表->10 颜色的表示->py.py。
Sub CreateChart()
Dim cht As Chart
Dim ser As Series
ActiveSheet.Range("A2:C11").Select
Set cht = ActiveSheet.Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
Set ser = cht.SeriesCollection(1) ‘获取第1个序列
ser.Format.Fill.ForeColor.RGB = RGB(0, 255, 0) ‘序列1面的颜色
'ser.Format.Fill.ForeColor.RGB = &HFF00& ‘更多颜色表示方式
'ser.Format.Fill.ForeColor.RGB = Application.Hex2Dec("00FF00")
'ser.Format.Fill.ForeColor.RGB = 65280
'ser.Format.Fill.ForeColor.ObjectThemeColor = 10
'ser.Format.Fill.ForeColor.SchemeColor = 3
SetStyle cht, 0, 0.28
End Sub
运行代码生成图1-15。
图1-15 给复合线形图着色
配色理论
配色理论中比较有名的是色轮配色理论。有很多种色轮,但是最常用的色轮是12色径向上每种颜色有5个色阶的色轮,如图1-16所示。12种颜色中,红色、黄色和蓝色是三原色,其他颜色都是由这三种颜色混合而成。三原色两两之间一半位置上的橙色、绿色和紫色称为二次色,是由它两边的原色混合而成。剩下的称为三次色,是由它们各自两边的原色和二次色混合而成。
图1-16 12色色轮
使用色轮配色的方法有下面几种:
- 单色配色
- 色轮中每种颜色在径向上都有从浅到深5个色阶,单色配色就是使用同一种颜色的不同色阶对图表进行着色。如图1-17中第一个图所示。
- 对比色配色
- 对比色即补色,指的是色轮中直线相对的两种颜色,如图1-17中的红色和绿色,或蓝色和橙色等。对比色适合表现活力,效果如图1-17中右上图所示。
- 类比色配色
- 色轮上相邻的颜色称为类比色,如色轮中的黄橙色、橙色和红橙色,它们拥有共同的颜色,都由黄色和红色混合而成。所以,类别色对比度较低,如图1-17中左下角图所示。
- 三色配色
- 三色配色,可以使用原色配色和二次色配色,也可以使用分裂补色。所谓分裂补色,是取对比色中的一种颜色,以及另一种颜色两侧的颜色。效果如图1-17中右下角图所示。
图1-17 用色轮配色
下面列出实现图1-17中左上角图的部分代码。完整代码见:Samples->ch04 美化Excel图表->11 配色理论->py.py。
Sub CreateChart()
Dim cht As Chart
ActiveSheet.Range("A1:B4").Select
Set cht = ActiveSheet.Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
cht.ChartGroups(1).GapWidth = 100 ‘分组之间的距离
‘分别设置序列1中各数据点对应的柱面的颜色
cht.SeriesCollection(1).Points(1).Format.Fill.ForeColor.RGB = RGB(0, 51, 51)
cht.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = RGB(0, 102, 102)
cht.SeriesCollection(1).Points(3).Format.Fill.ForeColor.RGB = RGB(0, 153, 153)
cht.SeriesCollection(1).Points(4).Format.Fill.ForeColor.RGB = RGB(0, 204, 204)
SetStyle cht
End Sub
下面列出实现图1-17中右上角图的部分代码。完整代码见:Samples->ch04 美化Excel图表->12 配色理论2->py.py。
Sub CreateChart()
Dim cht As Chart
ActiveSheet.Range("A1:B4").Select
Set cht = ActiveSheet.Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
cht.ChartGroups(1).GapWidth = 100 ‘分组之间的距离
‘分别设置序列1中各数据点对应的柱面的颜色
cht.SeriesCollection(1).Points(1).Format.Fill.ForeColor.RGB = RGB(0, 51, 51)
cht.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = RGB(0, 102, 102)
cht.SeriesCollection(1).Points(3).Format.Fill.ForeColor.RGB = RGB(0, 153, 153)
cht.SeriesCollection(1).Points(4).Format.Fill.ForeColor.RGB = RGB(0, 204, 204)
SetStyle cht
End Sub
下面列出实现图1-17中左下角角图的部分代码。完整代码见:Samples->ch04 美化Excel图表->13 配色理论3->py.py。
Sub CreateChart()
Dim cht As Chart
ActiveSheet.Range("A1:B4").Select
Set cht = ActiveSheet.Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
cht.ChartGroups(1).GapWidth = 100 ‘分组之间的距离
‘分别设置序列1中各数据点对应的柱面的颜色
cht.SeriesCollection(1).Points(1).Format.Fill.ForeColor.RGB = RGB(0, 51, 51)
cht.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = RGB(0, 102, 102)
cht.SeriesCollection(1).Points(3).Format.Fill.ForeColor.RGB = RGB(0, 153, 153)
cht.SeriesCollection(1).Points(4).Format.Fill.ForeColor.RGB = RGB(0, 204, 204)
SetStyle cht
End Sub
下面列出实现图1-17中右下角图的部分代码。完整代码见:Samples->ch04 美化Excel图表->14 配色理论1->py.py。
Sub CreateChart()
Dim cht As Chart
ActiveSheet.Range("A1:B4").Select
Set cht = ActiveSheet.Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
cht.ChartGroups(1).GapWidth = 100 ‘分组之间的距离
‘分别设置序列1中各数据点对应的柱面的颜色
cht.SeriesCollection(1).Points(1).Format.Fill.ForeColor.RGB = RGB(0, 51, 51)
cht.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = RGB(0, 102, 102)
cht.SeriesCollection(1).Points(3).Format.Fill.ForeColor.RGB = RGB(0, 153, 153)
cht.SeriesCollection(1).Points(4).Format.Fill.ForeColor.RGB = RGB(0, 204, 204)
SetStyle cht
End Sub
配色工具和资源
对学术图表进行配色,不可避免地要用到一些配色工具。网上有专门的帮助配色的网站,比如Adobe Color, Coolors, Colorspire, ColorBlender等。国内也有一些微信公众号专门讨论学术图表的配色,给出2种、3种或更多种颜色的配色方案和各颜色的RGB值。目前这方面的资料还是比较多的,搜索一下就可以找到。
有时候看到好的配色,想知道各种颜色对应的RGB分量,可用专门的取色器进行获取。一般比较专业的绘图软件和平面设计软件都会提供取色器,网上也有一些在线的取色器。
给一组对象着色
绘制图表时经常需要给一组对象着色,例如给简单柱状图中的一组柱面着色,或者给饼图的各扇区着色。可以使用前面介绍的方法给序列中的单个点逐个修改颜色,也可以先将需要用到的颜色放到一个数组中,然后用循环绘制各数据点并从数组中取色绘图。这里介绍后者。
下面先将需要用到的颜色放到一个数组colors中,然后用循环从数组中依次取色并用于修改各柱面的颜色。完整代码见:Samples->ch04 美化Excel图表->15 给一组对象着色->py.py。
Sub CreateChart()
Dim cht As Chart
ActiveSheet.Range("A1:B4").Select
Set cht = ActiveSheet.Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
cht.ChartGroups(1).GapWidth = 100 ‘分组之间的距离
‘把全部颜色放到一个数组
Dim intR(1 To 4) As Integer
Dim intG(1 To 4) As Integer
Dim intB(1 To 4) As Integer
Dim intI As Integer
intR(1) = 51: intG(1) = 51: intB(1) = 0
intR(2) = 102: intG(2) = 102: intB(2) = 0
intR(3) = 153: intG(3) = 153: intB(3) = 0
intR(4) = 204: intG(4) = 204: intB(4) = 0
‘从数组中取色,给各柱面着色
For intI = 1 To 4
cht.SeriesCollection(1).Points(intI).Format.Fill.ForeColor.RGB _
= RGB(intR(intI), intG(intI), intB(intI))
Next
SetStyle cht
End Sub
运行代码生成图1-18。
图1-18 给一组对象着色
使用颜色查找表
Python和MATLAB软件中提供了很多颜色查找表,使用它们可以很方便地对一组图形对象进行渐变着色。本小节在Excel中引入MATLAB中的大部分颜色查找表并结合实例进行使用。
所谓的颜色查找表实际上是一个N行3列的数组,数组中每行3个数表示一种颜色的R、G、B分量,即红色、绿色和兰色分量。笔者在Excel中引入了MATLAB的主要颜色查找表。在本书的随书资料中,在Samples目录下可以找到一个名为colormap.xlsx的Excel文件,打开该文件如图1-19所示。
图1-19 在Excel中引入MATLAB中的颜色查找表
工作簿中,每个工作表存放一个颜色查找表的颜色矩阵数据,它们都是256行3列的矩阵。工作表的名称就是颜色查找表的名称。各颜色查找表的颜色说明和对应的色条如表1-9所示。
表1-9 引入MATLAB内置的颜色查找表
| 名称 | 说 明 | 色 条 |
|---|---|---|
| parula | 兰色、青色、橙色和黄色之间渐变 | |
| turbo | 兰色和红色之间渐变 | |
| hsv | 变化HSV颜色模型中的色度组分 | |
| hot | 黑色、红色、橘红色、黄色和白色之间渐变 | |
| cool | 青色和洋红之间渐变 | |
| spring | 洋红和黄色之间渐变 | |
| summer | 绿色和黄色之间渐变 | |
| autumn | 红色向橘黄色、黄色渐变 | |
| winter | 兰色和绿色渐变 | |
| gray | 线性灰阶颜色查找表 | |
| bone | 为含有较高的兰色组分的gray颜色查找表 | |
| copper | 黑色和亮铜色之间渐变 | |
| pink | 品红色和白色渐变 | |
| sky | 白色和天兰色之间渐变 | |
| abyss | 深兰色和天兰色之间渐变 | |
| jet | 兰色、青色、黄色、橘红色、红色之间渐变 |
使用颜色查找表时,需要给定一组着色数据,将该数据从小到大进行排序,并与颜色查找表中的颜色数据建立映射关系。将着色数据的最小值对应表数据的末行,将着色数据的最大值对应表数据的首行,中间的数据根据它的位置取表数据中相应位置的颜色。这样,通过线性插值,可以获取每个着色数据对应的颜色,用于绘制图表。
下面创建有8个柱面的简单柱状图,使用parula颜色查找表对每个柱面单独着色。完整代码见:Samples->ch04 美化Excel图表->16 使用颜色查找表->py.py。
Sub CreateChart()
Dim cht As Chart
ActiveWorkbook.Sheets("Sheet1").Range("A2:B9").Select
Set cht = ActiveWorkbook.Sheets("Sheet1").Shapes.AddChart2(-1, _
xlColumnClustered, 200, 20, 350, 250, True).Chart
cht.ChartGroups(1).GapWidth = 50 ‘分组之间的间隔
Dim intI As Integer
Dim intR As Integer
Dim intG As Integer
Dim intB As Integer
Dim dblW As Double
Dim Count As Integer
Dim cm()
‘获取颜色查找表的颜色数据
cm = ActiveWorkbook.Sheets("parula").Range("A1:C256").Value
‘对于每个柱面,根据序号从颜色查找表中取色进行着色
For intI = 1 To 8
dblW = intI / 8
If CInt(dblW * 256) = 0 Then
Count = 1
intR = cm(1, 1)
intG = cm(1, 2)
intB = cm(1, 3)
Else
Count = CInt(dblW * 256)
intR = cm(Count, 1)
intG = cm(Count, 2)
intB = cm(Count, 3)
End If
cht.SeriesCollection(1).Points(intI).Format.Fill. _
ForeColor.RGB = RGB(intR, intG, intB)
Next
SetStyle cht
End Sub
运行代码生成图1-20。
图1-20 使用parula颜色查找表 图1-21 使用cool颜色查找表
下面创建有8个柱面的简单柱状图,使用cool颜色查找表对每个柱面单独着色。完整代码见:Samples->ch04 美化Excel图表->17 使用颜色查找表2->py.py。
‘省略部分代码
cm = ActiveWorkbook.Sheets("cool").Range("A1:C256").Value ‘获取颜色查找表的颜色数据
‘省略部分代码
运行代码生成图1-21。
下面创建有8个柱面的简单柱状图,使用summer颜色查找表对每个柱面单独着色。完整代码见:Samples->ch04 美化Excel图表->18 使用颜色查找表3->py.py。
‘省略部分代码
‘获取颜色查找表的颜色数据
cm = ActiveWorkbook.Sheets("summer").Range("A1:C256").Value
‘省略部分代码
运行代码生成图1-22。
图1-22 使用summer颜色查找表 图1-23 使用jet颜色查找表
下面创建有8个柱面的简单柱状图,使用jet颜色查找表对每个柱面单独着色。完整代码见:Samples->ch04 美化Excel图表->19 使用颜色查找表1->py.py。
‘省略部分代码
cm = ActiveWorkbook.Sheets("jet").Range("A1:C256").Value ‘获取颜色查找表的颜色数据
‘省略部分代码
运行代码生成图1-23。
使用颜色查找表对图表进行着色时,往往需要绘制色条,作为图例标示各颜色对应的着色数据的大小。色条实际上是一个多色渐变填充的矩形,如图1-25所示。
本书随书资料中,在Samples目录下可以找到一个名为colormaps.txt的文本文件,打开该文件如图1-24所示。文件中罗列了各颜色查找表中颜色节点处的位置和颜色,利用该数据,以及1.2.3小节介绍的多色渐变填充的方法,可以绘制对应的色条。
图1-24 绘制色条的数据
上面使用parula, cool, summer和jet 4个颜色查找表对简单柱状图进行了着色,它们对应的色条如图1-25所示。每个色条右侧用标签标示了色条种指定颜色对应的着色数据的大小。
图1-25 绘制色条
下面是绘制图1-25的部分代码。这部分代码涉及到坐标转换,需要学习第5章的内容后才能看懂。完整代码见:Samples->ch04 美化Excel图表->20 绘制色条->py.py。
Sub CreateChart()
'创建图表
Dim shp As Shape
Dim cht As Chart
Set shp = ActiveSheet.Shapes.AddChart2()
Set cht = shp.Chart
cht.ChartType = xlXYScatter
Dim ax1 As Axis
Set ax1 = cht.Axes(1)
Dim ax2 As Axis
Set ax2 = cht.Axes(2)
ax1.MinimumScale = 0
ax1.MaximumScale = 300
ax2.MinimumScale = 0
ax2.MaximumScale = 300
SetStyle cht
cht.SeriesCollection.NewSeries
‘第1个色条,矩形垂向多色渐变填充
Dim shp2 As Shape
Dim shp3 As Shape
Dim shp4 As Shape
Dim shp5 As Shape
Dim shp6 As Shape
Dim x As Double
Dim y As Double
Dim w As Double
Dim h As Double
x = ShapeX(cht, 50)
y = ShapeY(cht, 250)
w = cht.PlotArea.InsideWidth / (ax1.MaximumScale - ax1.MinimumScale) * 10
h = cht.PlotArea.InsideHeight / (ax2.MaximumScale - ax2.MinimumScale) * 200
Set shp2 = cht.Shapes.AddShape(1, x, y, w, h)
‘垂向多色渐变填充
shp2.Fill.ForeColor.RGB = RGB(255, 255, 26)
shp2.Fill.OneColorGradient msoGradientHorizontal, 1, 1
shp2.Fill.GradientStops.Insert RGB(255, 204, 51), 0.25
shp2.Fill.GradientStops.Delete 2
shp2.Fill.GradientStops.Insert RGB(204, 204, 51), 0.5
shp2.Fill.GradientStops.Insert RGB(0, 179, 179), 0.75
shp2.Fill.GradientStops.Insert RGB(51, 128, 255), 0.85
shp2.Fill.GradientStops.Insert RGB(255, 204, 51), 1
shp2.Line.Weight = 1
Dim intI As Integer
‘给色条添加标签
Dim cmLabels(1 To 3) As String
Dim cmLabelPos(1 To 3) As Double
Dim cmLabelPosX(1 To 4) As Double
cmLabels(1) = 0: cmLabels(2) = 0.5: cmLabels(3) = 1
cmLabelPos(1) = 50: cmLabelPos(2) = 150: cmLabelPos(3) = 250
For intI = 1 To 3
lf = ShapeX(cht, 57)
tp = ShapeY(cht, cmLabelPos(intI) + 20)
wd = cht.PlotArea.InsideWidth / (cht.Axes(1).MaximumScale - cht.Axes(1).MinimumScale) * 40
ht = cht.PlotArea.InsideHeight / (cht.Axes(2).MaximumScale - cht.Axes(2).MinimumScale) * 30
Set shp6 = cht.Shapes.AddLabel(msoTextOrientationHorizontal, lf, tp, wd, ht)
shp6.TextFrame2.TextRange.Characters.Text = Format(CStr(cmLabels(intI)), "0.00")
shp6.TextFrame2.TextRange.Characters.Font.Size = 8
shp6.TextFrame2.AutoSize = msoAutoSizeTextToFitShape
Next
‘第2个色条,矩形垂向多色渐变填充
‘... 省略代码
‘第3个色条,矩形垂向多色渐变填充
‘... 省略代码
‘第4个色条,矩形垂向多色渐变填充
‘... 省略代码
End Sub