事先声明以下内容基本全部是学习大神刘万祥的热力型数据地图(HeatMap)做法详解做成的,基本算是一个学习笔记。其中我添加了一些个人的见解和改进。
(做这个热力图是给公司用的,其它是回家整理的,所以附件是英文,截图的excel是中文,有点混乱,但是不妨碍理解。)
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
EXCEL做热力图的思路是:
1. 找到中国的矢量图,导入EXCEL后拆解成FreeForm(大概是自由图形的意思),对这些FreeForm逐个命名
2. 填充省份对应数据,供后续使用
3. 设定数据区间和对应色块
4. 设置相关名称便于后续处理
5. 用VBA查询数据和对应区间进行地图填充
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
具体步骤
1. 地图处理
刘老师的博客里提到:
所谓矢量格式,是使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,其文件后缀名一般为.WMF、.AI、.EPS、.CDR等。Excel可以读取.WMF格式的文件,其他格式的一般需要专门的软件打开。
我在查找矢量图的时候先找到.eps格式,于是试了试EXCEL,发现2013版本是可以读取.eps格式的(不知道之前的版本可不可以)。导入(用插入图片的方式导入矢量图)以后还是一个完整图片,需要右键点击“edit picture"(中文版本是”编辑图片“),才能分解各个省份。分解完以后的地图仍然是组合模式,但是你不用ungroup,直接点击单个省份就可以选中它。然后把这些省份命名为各自的拼音(注意案例里的西藏、内蒙都是拼音,并没有用国际惯例的英文拼法)。
命名图片的方式很简单,只要直接在工作簿左上角的名称框(公式栏左侧)里填写省份拼音就行了(如图,以新疆为例)。图中的每个省份都需要逐一手动命名,没有捷径。
2. 数据准备
中国有4个直辖市、23个省、5个自治区以及2个特别行政区。除了特别行政区比较小显示不能以外,其它32个行政单位都列在了此案例里。
32个行政区都放在了O列,按拼音的字母顺序排列。每次使用这个模版前,只要更新对应省份的原始数据即可。唯一要注意的是如果数据缺失,必须要写上na或者NA(不区分大小写)。为了处理方便和数据结构的稳定性,这32行数据的格式最好保持不变。
案例里的销量数据(P列)是用RANDBETWEEN(1,10000)随机生成,所以不具备真实性。
3. 数据区间及色块
第二步中,随机生成的数据是1和10000之间,所以区间的设置也是据此进行(截图里没有进行平均划分,是比较随意的划法,可根据需要自行修改T列和U列的对应值),考虑到数据缺失的情况,特别设置了一个NA的对应颜色。V列用于后续的名称引用,接下来的两个步骤里会用到。色块可以用Camera(相机)功能拍下来然后放到地图左下角作为解释图例。
4. 名称设置
为了方便后续VBA的处理,还需要添加一些辅助的单元格和名称:
考虑到接下来的步骤里VBA要逐个读取行政区划和相关数据并据此填充省份地图,我们需要有一个单元格来记录每一轮读取的省/市名称,一个单元格来记录该省/市对应的销量数据,另外还需要一个单元格记录销量所在的区间对应的色块标示。
另外,对为了VBA操作简便,也需要将必要的数据用Formula(公式)一栏中的name manger(名称管理器)命名(见截图和下表,包括上面提到的那三个单元格,参考附件中的工作簿"NameMgrRef"):
Name | Formula | Illustration | Cell Formula (if any) |
ProvData | =HeatMap!$O$4:$P$35 | Data Source | |
Pallete | =HeatMap!$U$4:$V$8 | Pallete Source | |
ActProv | =HeatMap!$AA$4 | Temporary place for storing Province Name | |
ActSales | =HeatMap!$AA$5 | Temporary place for storing Province Sales | =VLOOKUP(ActProv, ProvData, 2, 0) |
ActColor | =HeatMap!$AA$6 | Temporary place for storing Province Color Index | =VLOOKUP(ActSales, Pallete, 2, 1) |
Color1 | =HeatMap!$R$4 | Color Index 1 | |
Color2 | =HeatMap!$R$5 | Color Index 2 | |
Color3 | =HeatMap!$R$6 | Color Index 3 | |
Color4 | =HeatMap!$R$7 | Color Index 4 | |
Color5 | =HeatMap!$R$8 | Color Index 5 |
5. VBA编写
主要的VBA片段意在从ProvData中逐个读取省份名称,然后将对应的ActSales对应的颜色块填充到省份图形中去,关键部分如下:
For i = 4 To 35 'in which lines the prov list lays
Range("ActProv").Value = Range("O" & i).Value
'ActProv to be filled by Province Name
If UCase(Range("ActSales").Value) = "NA" Then'Case when missing data encountered
ActiveSheet.Shapes(Range("ActProv").Value).Select
Selection.ShapeRange.Fill.ForeColor.RGB = Range("S10").Interior.Color
Else
ActiveSheet.Shapes(Range("ActProv").Value).Select
'Select the FreeForm regarding Province Name
Selection.ShapeRange.Fill.ForeColor.RGB = Range(Range("ActColor").Value).Interior.Color
End If
Next i
用developper设置一个按钮,将这个按钮指向写好的宏,就可以顺利创建热力图了。
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
改进点
1. 添加NA
用于区别有数据的情况,具体步骤里已经提到,不再赘述。
2. 色块选择
附件中的样例是采用的Theme Color(主题颜色)的蓝色渐变。为了有更多选择,我们可以设置一个个性化的滚动条,用于选择不同的主题颜色:
通过点击调整滚动条的位置,来获取不同的主题颜色。主题颜色在这里是通过条件格式实现的(用了一个笨办法,可以参看AA列对应位置添加的辅助项)。但是条件格式所实现的颜色是没法用VBA读取的,所以还要有一段VBA来将选定的条件格式的色块系列应用到数据区间(见具体步骤的第三步的截图)中去(这段code比较长,但是结构简单,只列举一小部分):
For i = 23 To 27 'where color cards lay
Select Case Range("AA" & i).Value
'Color Card 1
Case 6
Range("S" & i - 18).Interior.Color = RGB(221, 235, 247)
Case 7
Range("S" & i - 18).Interior.Color = RGB(189, 215, 238)
Case 8
Range("S" & i - 18).Interior.Color = RGB(155, 194, 230)
Case 9
Range("S" & i - 18).Interior.Color = RGB(47, 117, 181)
Case 10
Range("S" & i - 18).Interior.Color = RGB(31, 78, 120)
'Color Card 2
'Color Card 3
'...
Next i
附件中采用的主体颜色主要是六种,基本都是单色系的浅深渐变,如果有兴趣可以自己设置其它的颜色:
上面RGB的三个参数有很多种查看方式,其中一种可以再主体颜色下拉框里电击其它颜色,然后就可以看到不同颜色对应的3个RGB参数:
3. 添加颜色清理功能
即再写一段VBA,将所有省/市图形处理成同一颜色。我这里选择的是处理成浅灰色。VBA 代码比较简单,可以参考上面的第一段来写。
4. 数据标题可选
在单元格P3用data validation设置了一个list,是个人想到的比较常用的一些数据名称,比如降雨,GDP,人口等等(无技术难度 :P)。
5. 热力图标题
因为案例中的热力图并不是EXCEL自带功能实现的,EXCEL不支持为此图添加图标元素。如上文提到的图例。
标题同样有很多种解决办法,这里提供一种个人比较偏好的:
1. 在图中合适的位置插入一个横向的文本框,不要在文本框中输入任何内容,
2. 选中文本框,然后在公式栏中输入 = $AA$3 (文本框只能用来赋值——显示某单元格的内容,无法与公式连用,所以需要在其他的单元格用公式串起你想要的动态名称,然后将这个单元格赋值给文本框,这里AA3 = P3 & " per province")
3. 选择字体和大小就可以了,这样,无论单元格P3的下拉框选中什么,热力图的标题都可以相应改变
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
使用方法
0. (可选) 电击按钮"Remove Colors" (Section 3)
1. 在P列中填充数据,缺失数据标记为"na"或者"NA"(大小写均可) (Section 1)
2. 使用滚动条选择自己喜欢的色块系列,点击"Apply..."按钮应用此系列 (Section 4)
3. 点击按钮"Fill Color..." (Section 3)
一切都很简单 :P
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
整体效果
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
网上很多Geographical Heat Map都是收费资源,所以我这里免费了,共享才是王道 :)
参考附件:China Heat Map
提取密码: bc7x
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
补充:
主体颜色选择那块儿可以继续优化,现有的实现方式是在第四区块通过条件格式确定用户喜好的主题颜色系,然后用VBA调用对应颜色填充到第二部分的色块显示区。
更直接的方法是创建用户窗体,或者是用开发者工具(Developper)创建一个ActiveX滚动条(此例中创建的是表单空间,只能指定给某个VBA程序)。然后在滚动条上右键,查看代码,写入相应的程序。另外还需要在其他worksheet创建一个主题颜色库,用ActiveX滚动条调用这个库中的色系。这样可以随意在色库中添加和修改我们想要的色系。不用像附件中的例子那样,需要VBA大量添加修改RGB参数。