解决问题
使用python向word中插入office自带的可编辑的图表,查看python-docx v0.8.10文档还未实现该功能,考虑使用win32com。
前置知识
- 了解word编程时的几个主要对象和类,包括
Application对象:应用
Document对象:文档
Selection对象:选区
更多类别查阅文档:https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.office.interop.word?view=word-pia - 了解宏录制功能,通过查看宏编辑器里的VBA代码,了解操作使用了哪些对象和方法
- 这些前置知识可以参考文章https://zhuanlan.zhihu.com/p/67543981,主要解决思路来源于此。
通过在word中录制宏可以了解大部分操作对象,本人使用office365版本的word程序不能录制生成图表和编辑图表的操作。
具体思路
win32模块安装:pip install pypiwin32
考虑了两种实现思路:
思路一:从Excel应用中将图表copy至word
Excel本身对图表创建和操作相对更方便,且在Ecxel中可以录制创建、编辑等对图表的操作,方便查看使用的对象和方法。
该方法需要分别打开一个Word应用和Excel应用。
步骤
数据准备:
- Excel文件中保存生成图表的测试数据。
- 在word文档中插入书签,此处方便选择图表插入位置。也可调用Selection对象设置插入位置,具体可参考官方文档说明。
具体代码如下:
import win32com
from win32com.client import Dispatch
docApp = win32com.client.Dispatch('Word.Application')
excelAPP = win32com.client.Dispatch('Excel.Application')
docApp.Visible = True
docApp.DisplayAlerts = 0
excelAPP.Visible = True
excelAPP.DisplayAlerts = 0
doc = docApp.Documents.Open('test.docx')
excel = excelAPP.Workbooks.Open('test.xlsx')
# 设置生成图表类型及数据范围
# AddChart2方法说明详见思路二
excel_chart = excel.ActiveSheet.Shapes.AddChart2(201, 51)
excel_chart.Chart.SetSourceData(Source=excel.ActiveSheet.Range("A1:D4"))
# 设置图表样式,此处仅为简单示例,具体需求可通过录制宏参考调用的对象及其属性
excel_chart.Chart.ChartTitle.Text = '测试标题'
excel_chart.Chart.FullSeriesCollection(3).Format.Fill.ForeColor.ObjectThemeColor = 10
# 将excel中的图表复制粘贴到word中
excel_chart.Copy()
doc.Bookmarks("插入图表位置").Select()
# docApp.Selection.Paste() # 直接粘贴,一般默认为使用目标主题和链接数据
docApp.Selection.PasteAndFormat(16) # 保留所粘贴材料的原始格式
doc.Save()
doc.Close()
excel.Save()
excel.Close()
docApp.Quit()
excelAPP.Quit()
思路二:直接在word中插入图表
不需要打开Excel应用,直接在Word中调用图表对象。
步骤
数据准备:
- 在word文档中插入书签,此处方便选择图表插入位置。也可调用Selection对象设置插入位置,具体可参考官方文档说明。
具体代码如下:
import win32com
from win32com.client import Dispatch
docApp = win32com.client.Dispatch('Word.Application')
docApp.Visible = True
docApp.DisplayAlerts = 0
doc = docApp.Documents.Open('test.docx')
# 创建图表,图表的插入位置为预先在word文档中插入的书签,书签名为“插入图表位置”
shape_chart = doc.Shapes.AddChart2(Style=201, Type=51, Top=doc.Bookmarks("插入图表位置").Select())
shape_chart.WrapFormat.Type = 7 # 设置图表为嵌入型
# 设置Word中的图表
chart = shape_chart.Chart
worksheet = chart.ChartData.Workbook.Worksheets(1) #图表数据对应的工作表
chart.SetSourceData("Sheet1!$A$1:$C$4") # 设置数据源范围
# 簇状柱形图测试数据
chart_data = [["","系列A","系列B","系列C","系列D"],
[2020,2,4,2,3],
[2019,4,5,3,2]]
# 清空工作表默认数据
worksheet.Range("A1:D5").value = None
# 填入测试数据
for row_index,row in enumerate(chart_data):
for column_index,value in enumerate(row):
worksheet.Cells(row_index+1,column_index+1).Value = value
chart.SetSourceData("Sheet1!$A$1:$E$3") # 设置数据源范围
# 设置图表样式示例
chart.ChartTitle.Text = '测试标题' # 设置标题
chart.FullSeriesCollection(2).Format.Fill.ForeColor.ObjectThemeColor = 10 #设置系列2的填充颜色
chart.ChartData.Workbook.Close() # 关闭workbook窗口
doc.Save()
doc.Close()
docApp.Quit()
使用AddChart2
方法时,word文档中已插入默认图表,如图所示。
其中,添加图表的方法AddChart2
参数考链接,图表类型对应的代码参考链接(或直接参考文末“附录-图表对应代码”)。
插入图表效果如下:
讨论
- 首先尝试思路一是发现在Word中没法录制编辑图表的宏借以参考,而在Excel中可录制,因此采用复制图表的方式。
- 实践发现,思路二也可以通过在Excel中录制宏了解图表对应的对象,Word官方文档中对chart对象的相关属性、方法描述相对简单(很多详细设置没有说明),参考Excel文档中的说明即可。
- 目前在本地测试发现某些对象不能正常调用,如调整坐标轴的字体格式,调用
Chart.Axes(Type=2).Format.TextFrame2
的TextFrame2
时报错,暂未找到解决方案,由此推测还可能存在其它坑。 - 很多方法的参数(如
doc.Shapes.AddChart2(Style=201)
)或对象的属性值(如图表系列的填充颜色)既可以使用相应数值,也可以使用类型常量。示例代码中全都使用了数字代码,是由于使用常量报错的问题尚未解决。 - 本博客主要分享解决的思路,代码在本地环境均可运行,不足之处欢迎交流~
附录
图表类型对应代码
XlChartType | 代码 | 说明 |
---|---|---|
xl3DArea | -4098 | 三维面积图 |
xl3DAreaStacked | 78 | 三维堆积面积图 |
xl3DAreaStacked100 | 79 | 100%堆叠区域 |
xl3DBarClustered | 60 | 三维簇状条形图 |
xl3DBarStacked | 61 | 三维堆积条形图 |
xl3DBarStacked100 | 62 | 三维百分比堆积条形图 |
xl3DColumn | -4100 | 三维柱形图 |
xl3DColumnClustered | 54 | 三维簇状的柱形图 |
xl3DColumnStacked | 55 | 三维堆积柱形图 |
xl3DColumnStacked100 | 56 | 三维百分比堆积条形图 |
xl3DLine | -4101 | 三维折线图 |
xl3DPie | -4102 | 三维饼图 |
xl3DPieExploded | 70 | 分离型三维饼图 |
xlArea | 1 | 区域 |
xlAreaStacked | 76 | 堆积的面积图 |
xlAreaStacked100 | 77 | 100%堆叠区域 |
xlBarClustered | 57 | 簇状条形图 |
xlBarOfPie | 71 | 复合条饼图 |
xlBarStacked | 58 | 堆积条形的图 |
xlBarStacked100 | 59 | 百分比堆积条形图 |
xlBubble | 15 | 气泡图 |
xlBubble3DEffect | 87 | 三维气泡图 |
xlColumnClustered | 51 | 三维簇状的柱形图 |
xlColumnStacked | 52 | 堆积的柱形图 |
xlColumnStacked100 | 53 | 百分比堆积柱形 |
xlCombo | -4152 | |
xlComboAreaStackedColumnClustered | 115 | |
xlComboColumnClusteredLine | 113 | |
xlComboColumnClusteredLineSecondaryAxis | 114 | |
xlConeBarClustered | 102 | 簇状条形圆锥图 |
xlConeBarStacked | 103 | 堆积条形的圆锥图 |
xlConeBarStacked100 | 104 | 百分比堆积条形圆锥图 |
xlConeCol | 105 | 三维柱形圆锥图 |
xlConeColClustered | 99 | 柱形簇状圆锥图 |
xlConeColStacked | 100 | 堆积的柱形圆锥图 |
xlConeColStacked100 | 101 | 百分比堆积柱形圆锥图 |
xlCylinderBarClustered | 95 | 簇状条形圆柱图 |
xlCylinderBarStacked | 96 | 堆积条形的圆柱图 |
xlCylinderBarStacked100 | 97 | 百分比堆积条形圆柱图 |
xlCylinderCol | 98 | 三维柱形圆柱图 |
xlCylinderColClustered | 92 | 柱形簇状圆锥图 |
xlCylinderColStacked | 93 | 堆积条形的圆柱图 |
xlCylinderColStacked100 | 94 | 百分比堆积柱形圆柱图 |
xlDoughnut | -4120 | 圆环图 |
xlDoughnutExploded | 80 | 分离型圆环图 |
xlLine | 4 | Line |
xlLineMarkers | 65 | 折线图 |
xlLineMarkersStacked | 66 | 堆积的折线图 |
xlLineMarkersStacked100 | 67 | 百分比堆积折线图 |
xlLineStacked | 63 | 堆积的折线图 |
xlLineStacked100 | 64 | 百分比堆积折线图 |
xlOtherCombinations | 116 | |
xlPie | 5 | 饼图 |
xlPieExploded | 69 | 分离型的饼图 |
xlPieOfPie | 68 | 复合饼图 |
xlPyramidBarClustered | 109 | 簇状条形棱锥图 |
xlPyramidBarStacked | 110 | 堆积条形的棱锥图 |
xlPyramidBarStacked100 | 111 | 百分比堆积条形棱锥图 |
xlPyramidCol | 112 | 三维柱形棱锥图 |
xlPyramidColClustered | 106 | 柱形簇状棱锥图 |
xlPyramidColStacked | 107 | 堆积的柱形棱锥图 |
xlPyramidColStacked100 | 108 | 百分比堆积柱形棱锥图 |
xlRadar | -4151 | 雷达图 |
xlRadarFilled | 82 | 填充的雷达图 |
xlRadarMarkers | 81 | 数据点雷达图 |
xlStockHLC | 88 | 盘高-盘低-关闭 |
xlStockOHLC | 89 | 打开高低关闭 |
xlStockVHLC | 90 | 卷高低关闭 |
xlStockVOHLC | 91 | 卷-打开-高-低-关闭 |
xlSuggestedChart | -2 | |
xlSurface | 83 | 三维曲面图 |
xlSurfaceTopView | 85 | 曲面图(俯视图) |
xlSurfaceTopViewWireframe | 86 | 曲面图(俯视线框) |
xlSurfaceWireframe | 84 | 三维曲面图(线框) |
xlXYScatter | -4169 | 散点图 |
xlXYScatterLines | 74 | 折线散点图 |
xlXYScatterLinesNoMarkers | 75 | 无数据点折线散点图 |
xlXYScatterSmooth | 72 | 平滑线散点图 |
xlXYScatterSmoothNoMarkers | 73 | 无数据点平滑的线与散点图 |