上一篇用一个简单实例描述了openpyxl
和xlsxwriter
对Excel表格的操作,本文则实例介绍一下xlsxwriter
图表的绘制。
Chart
类是用于在 XlsxWriter
中实现图表的模块基础类。支持的图表类型有:面积、条形图、柱形图、折线图、饼图、散点图、股票和雷达等。
Chart
通过指定图表类型的工作簿的add_chart()
方法来创建图表对象。
# e.g.
chart = workbook.add_chart({
'type': 'column'})
type
类型字段值的选择有:
area
: 创建区域样式(面积图)的图表。bar
:创建条形图(转换直方图)的图表。column
:创建列样式(直方图)的图表。line
:创建折线图表。pie
:创建饼图样式的图表。doughnut
:创建旭日图样式的图表。scatter
:创建散射样式(散点图)的图表。stock
:创建股票样式的图表。radar
:创建雷达样式的图表。# e.g.
worksheet.insert_chart('A4', chart, {
'x_offset': 25, 'y_offset': 10})
图表的常用方法:
add_series(options)
: 定义图表系列选项(如:值、轴标签和格式)。
name
: 系列的名称。categories
: 类别标签。values
: 取值列表。line
: 系列行类型的属性,如颜色和宽度。fill
: 系列的填充属性,如颜色。gradient
: 系列的渐变填充属性。marker
: 系列标记的属性,如样式和颜色。data_labels
: 系列设置数据标签。overlap
: 设置系列之间的重叠,范围为+/-100。gap
: 设置系列之间的间隙,范围为 0 到 500。set_title(options)
: 设置图表标题选项。
name
: 设置图表标题。name_font
: 设置图表标题的字体属性。layout
: 设置标题位置。set_x_axis(options)
: 设置图表 X 轴选项。
name
: 设置轴标题。name_font
: 设置轴名的字体属性。num_font
: 设置轴标的字体属性。set_y_axis(options)
: 设置图表 Y 轴选项(同上)。set_y2_axis(options)
: 设置图表 Y 副轴选项(同上)。set_legend(options)
: 设置图表图例选项。
position
: 设置图表图例的位置。font
: 设置图表图例的字体属性。pattern
: 设置图例的模式填充属性。set_size(options)
: 设置图表的尺寸。
width
: 设置宽度。height
: 设置高度。set_style(style_id)
: 设置图表样式类型。set_table(options)
: 设置轴为数据表格形式。def construct_test_data(dimension='all'):
"""
构造数据
"""
if dimension == 'all':
sheetName = '国内_整体'
data = [
['指标', '加速线路', '安全加速', '精品EIP', '普通EIP', '腾讯', 'AWS', '阿里云'],
['延时(ms)', 51.22, 56.12, 65.61, 92.76, 116.02, 76.02, 66.02],
['丢包率(%)', 1.45, 3.21, 0.74, 6.18, 2.32, 1.32, 0.62]
]
else:
sheetName = '国内_运营商'
data = [
['运营商', '加速线路', None, '安全加速', None, '精品EIP', None, '普通EIP', None, '腾讯', None, 'AWS', None, '阿里云', None],
[None, '延时(ms)', '丢包率(%)', '延时(ms)', '丢包率(%)', '延时(ms)', '丢包率(%)', '延时(ms)', '丢包率(%)', '延时(ms)', '丢包率(%)', '延时(ms)', '丢包率(%)', '延时(ms)', '丢包率(%)'],
['中国电信', 52.68, 2, 42.1, 0.82, 24.21, 1.08, 52.32, 0.12, 50.97, 2, 121.2, 6.8, 90.33, 0.54],
['中国移动', 53.92, 0.3, 56.12, 2, 34, 0.27, 68.21, 1.45, 89.21, 0.42, 77.8, 0.52, 44.3, 0],
['中国联通', 67.31, 0.69, 65.15, 0.38, 88, 0.52, 55.52, 0.66, 80.2, 0.22, 92.3, 0.44, 210.2, 2.21]
]
return sheetName, data
import xlsxwriter
color_lst = [
['#000000', '#312D30', '#444245'], # 黑色
['#DDEBCF', '#9CB86E', '#156B13'], # 绿色
['#0000FF', '#6A98CC', '#46A7F5'], # 蓝色
['#800000', '#633915', '#A45D2D'], # 棕色
['#00FFFF', '#29CFCD', '#006054'], # 青色
['#808080', '#76797E', '#878785'], # 灰色
['#FF0000', '#801801', '#D70F19'], # 红色
['#C0C0C0', '#C2C2C2', '#8A8687'], # 银色
['#800080', '#621C9B', '#46024F'], # 紫色
['#FFFF00', '#F2BF04', '#FFE057'], # 黄色
['#FFFFFF', '#FCFAFB', '#CECECC'], # 白色
]
def export_simple_excel(filename=None, sheetLst=None, contents=None, dimensions=None):
filename = filename if filename else '竟对_xlsxwriter_Test.xlsx'
sheetLst = sheetLst if sheetLst else ['竟对分析测试']
contents = contents if contents else []
dimensions = dimensions if dimensions else ['all', 'isp']
wb = xlsxwriter.Workbook(filename)
# 设置风格
style1 = wb.add_format({
"bold": True,
'font_name': '仿宋',
'font_size': 12,
'bg_color': '#4DCFF6',
"align": 'center',
"valign": 'vcenter',
'text_wrap': 1
})
style2 = wb.add_format({
'font_size': 11,
'font_color': '#217346',
'bg_color': '#E6EDEC',
"align": 'center',
"valign": 'vcenter',
})
for index_, sheetName in enumerate(sheetLst):
ws = wb.add_worksheet(name=sheetName)
dimension = dimensions[index_]
# ws.set_default_row(35) # 设置默认行高
ws.set_column(0, len(contents[index_][0])-1, 20) # 设置列宽
# 写入
if dimension == 'all':
for i, row_lst in enumerate(contents[index_]):
style = style2 if i != 0 else style1
ws.write_row(f'A{i+1}', row_lst, style)
else:
line1, line2 = list(filter(lambda col: col, contents[index_][0])), list(filter(lambda col: col, contents[index_][1]))
isp, titleLine1 = line1[0], line1[1:]
titleLine2 = line2
ws.set_column(0, 0, 20) # 设置列宽
ws.set_column(1, len(titleLine2), 15) # 设置列宽
# 标题
ws.merge_range(0, 0, 1, 0, isp, style1)
[ws.merge_range(0, 2*i+1, 0, 2*(i+1), name, style1) for i, name in enumerate(titleLine1)]
[ws.write(1, i+1, name, style1) for i, name in enumerate(titleLine2)]
# 内容
for i, row_lst in enumerate(contents[index_][2:]):
ws.write_row(f'A{i+3}', row_lst, style2)
# 画图
y1_name = '延时(ms)'
y2_name = '丢包率(%)'
x_name = '产品类型'
title_name = sheetName
# 柱状图
column_chart = wb.add_chart({
'type': 'column'})
# 折线图
line_chart = wb.add_chart({
'type': 'line'})
if dimension == 'all': # 整体维度
column_name = f'={sheetName}!A2'
line_name = f'={sheetName}!A3'
categories = f'={sheetName}!B1:H1'
column_values = f'={sheetName}!B2:H2'
line_values = f'={sheetName}!B3:H3'
column_chart.add_series({
'name': column_name,
'categories': categories,
'values': column_values,
})
line_chart.add_series({
'name': line_name,
'categories': categories,
'values': line_values,
'marker': {
'type': 'circle'}, # 系列标记
'data_labels': {
# 数据标签
'value': True,
'series_name': True,
'position': 'above',
'separator': "\n",
'font': {
'name': 'Consolas', 'color': 'red', 'size': 8}
},
'y2_axis': True,
})
else: # 运营商维度
# 添加规则
d_lst = ['B', 'D', 'F', 'H', 'J', 'L', 'N']
l_lst = ['C', 'E', 'G', 'I', 'K', 'M', 'O']
for i, c in enumerate(d_lst):
# 写法一
categories_str = f'={sheetName}!A3:A5'
column_name_str = f'={sheetName}!{c}1:{c}2'
line_name_str = f'={sheetName}!{l_lst[i]}1:{l_lst[i]}2'
column_values_str = f'={sheetName}!{c}3:{c}5'
line_values_str = f'={sheetName}!{l_lst[i]}3:{l_lst[i]}5'
# 添加数据选项
column_chart.add_series({
'name': column_name_str,
'categories': categories_str,
'values': column_values_str,
'gap': 50, # 间隙
'overlap': -5, # 系列重叠
'gradient': {
# 渐变填充
'colors': color_lst[i],
'type': 'radial'
},
})
line_chart.add_series({
'name': line_name_str,
'categories': categories_str,
'values': line_values_str,
'marker': {
'type': 'circle'}, # 系列标记
'data_labels': {
# 数据标签
'value': True,
'series_name': True,
'position': 'above',
'separator': "\n",
'font': {
'name': 'Consolas', 'color': 'yellow', 'size': 8}
},
'y2_axis': True,
})
# 设置副坐标
line_chart.set_y2_axis({
'name': y2_name,
'name_font': {
'name': 'Calibri','color': 'red' }, # 轴标题设置
'num_font': {
'name': 'Arial', 'color': '#00B0F0', 'size': 8}, # 轴参数设置
})
# 设置前、背景色
column_chart.set_plotarea({
'pattern': {
'pattern': 'percent_5',
'fg_color': '#555555',
'bg_color': '#595959',
}
})
# 组合
column_chart.combine(line_chart)
column_chart.set_title({
'name': title_name, 'name_font': {
'name': 'Calibri','color': 'red' , 'size': 15}})
column_chart.set_x_axis({
'name': x_name, 'name_font': {
'name': 'Calibri','color': 'green' }, 'num_font': {
'name': 'Arial', 'color': 'green', 'size': 9}})
column_chart.set_y_axis({
'name': y1_name, 'name_font': {
'name': 'Calibri','color': 'blue' }, 'num_font': {
'name': 'Arial', 'color': 'blue', 'size': 8}})
# 样式
column_chart.set_style(2)
column_chart.set_legend({
'font': {
'size': 8, 'bold': False}})
column_chart.set_size({
'width': 720, 'height': 576})
# 插入
ws.insert_chart('A4', column_chart, {
'x_offset': 25, 'y_offset': 10}) # 在A4单元格插入图表
# 保存关闭文件
wb.close()
import os
FILE_PATH = os.path.join(os.path.dirname(__file__), 'files/')
def simple_test():
dimension_lst = ['all', 'isp']
# 方式一:按文件拆分
for dimension in dimension_lst:
filename = os.path.join(FILE_PATH, f'竟对分析_SimpleTest_{dimension}.xlsx')
sheetName, data = construct_test_data(dimension=dimension)
export_simple_excel(filename=filename, sheetLst=[sheetName], contents=[data], dimensions=[dimension])
# 方式二:按sheet拆分
file = os.path.join(FILE_PATH, '竟对分析_SimpleTest.xlsx')
sheetLst = []
contents = []
for dimension in dimension_lst:
sheetName, data = construct_test_data(dimension=dimension)
sheetLst.append(sheetName)
contents.append(data)
export_simple_excel(filename=file, sheetLst=sheetLst, contents=contents, dimensions=dimension_lst)
if __name__ == '__main__':
simple_test()
以上就是利用XlsxWriter
包的Chart
类绘制的简单的组合图。