2017年9月还有一个问题可以解决这个问题,但没有答案:create a pivotchart with python win32com
我尝试了几种方法来使它起作用,所以我想解释一下这些方法,并希望从某人那里获得如何使它起作用的见解。这似乎不是一条破旧的道路,所以我没有很高的希望。
环境详细信息:
我使用
win32com.client.gencache.EnsureDispatch('Excel.Application')
但我也可以使用
win32com.client.DispatchEx('Excel.Application')
或
win32com.client.dynamic.Dispatch('Excel.Application')
每个人都返回此CLSID win32com.gen_py.00020813-0000-0000-C000-000000000046x0x1x8
每个人也有相同的错误。
我还根据文档here运行了此命令:
C:\Users\home_dir>python AppData\Local\Continuum\anaconda3\pkgs\pywin32-223-py36hfa6e2cd_1\Lib\site-packages\win32com\client\makepy.py -i "Microsoft Excel 15.0 Object Library"
Output generated from makepy.py:
Microsoft Excel 15.0 Object Library {00020813-0000-0000-C000-000000000046}, lcid=0, major=1, minor=8
>>> # Use these commands in Python code to auto generate .py support
>>> from win32com.client import gencache
>>> gencache.EnsureModule('{00020813-0000-0000-C000-000000000046}', 0, 1, 8)
此版本的gencache无法成功运行:
Excel = win32com.client.gencache.EnsureModule('{00020813-0000-0000-C000-000000000046}', 0, 1, 8)
源数据 我使用ExcelWriter写入Excel的Pandas数据框中有100行18列
ew = pd.ExcelWriter('c:\devworkspace\SQL-Pandas-Excel\SampleData.xlsx')
sample_data_df.to_excel(ew, sheet_name='Source Data')
ew.save()
ew.close()
Excel = win32com.client.gencache.EnsureDispatch('Excel.Application')
win32c = win32com.client.constants
wb = Excel.Workbooks.Open('c:\devworkspace\SQL-Pandas-Excel\SampleData.xlsx')
src_sheet = wb.Worksheets('Source Data')
rng_row = 100
rng_col = 18
rng_beg = src_sheet.Cells(1,2)
rng_end = src_sheet.Cells(rng_row,rng_col)
pvt_src_rng = src_sheet.Range(rng_beg, rng_end)
pvt_src_rng.Select()
pvt_src = "%s!R1C2:R%dC%d"%(src_sheet.Name,rng_row+1,rng_col+1) #add 1 for header and df index
数据透视缓存 我使用PivotCaches()。Create()而不是.Add(),因此我可以指定Version = win32c.xlPivotTableVersion15,它是Office 2013的正确版本。否则,它似乎默认为版本11。
pc = wb.PivotCaches().Create(SourceType=win32c.xlDatabase, SourceData=pvt_src, Version=win32c.xlPivotTableVersion15)
此更改移动了转盘,但未能解决我的问题-我仍然遇到错误,并且未创建图表:
它无法翻译为人类可读的消息:
print(win32api.FormatMessage(error.excepinfo[5]))
error: (317, 'FormatMessageW', 'The system cannot find message text for message number 0x%1 in the message file for %2.')
搜索此错误代码2146827284,讨论似乎与excel对象正忙有关。但是Excel.Visible设置为0(也是默认值),因此它以无头模式运行。
添加图纸,创建数据透视表,添加字段成功 这些都用实际代码中的try-except包装-为简洁起见,将其删除。
pvt_sheet = wb.Sheets.Add(After=src_sheet)
pvt_sheet.Name = 'Pivot Sheet'
pvt_rng_beg = pvt_sheet.Cells(2,2)
pvt_rng_end = pvt_sheet.Cells(2,2)
pvt_dest_rng = pvt_sheet.Range(pvt_rng_beg, pvt_rng_end)
pt = pc.CreatePivotTable(TableDestination=pvt_dest_rng,TableName='PivotTable1')
pt.AddFields(RowFields="claimant_type_desc" , ColumnFields="claim_cause_desc" )
pt.AddDataField(Field=pt.PivotFields("total_direct_payment"), Caption="Total Incurred")
我可以将工作表或图表添加为“ ChartDestination”,但两个选项都不能改变结果。我可以验证对象是否已成功添加。
#chrt_sheet = wb.Charts.Add(After=pvt_sheet)
chrt_sheet = wb.Sheets.Add(After=pvt_sheet)
chrt_sheet.Name = 'Pivot Chart'
ChartDestination参数是唯一必需的参数,其他参数是可选的:XlChartType,Left,Top,Width,Height
文档here:
基于示例,我将工作表或图表对象的名称作为字符串“数据透视表”传递。应该可以。
pch = pc.CreatePivotChart(ChartDestination='Pivot Chart')
因为参数定义为Variant,所以我将字符串显式分配给Variant对象。我尝试了各种不同的变体类型,但结果却不同。
chrt_sheet_name_variant = win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_BSTR, chrt_sheet.Name)
print(chrt_sheet_name_variant.value)
print(chrt_sheet_name_variant.varianttype)
print(chrt_sheet_name_variant.__class__)
print(type(chrt_sheet_name_variant))
pch = pc.CreatePivotChart(ChartDestination=chrt_sheet_name_variant)
#Output:
#Pivot Chart
#16392
#<class 'win32com.client.VARIANT'>
#<class 'win32com.client.VARIANT'>
这是生成的错误:
File "C:\Users\xxxxxx\AppData\Local\Temp\gen_py\3.6\00020813-0000-0000-C000-000000000046x0x1x8\PivotCache.py", line 36, in CreatePivotChart
, XlChartType, Left, Top, Width, Height
com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146827284), None)
答案 0 :(得分:2)
感谢Boussif找到解决方法。
这是我的工作解决方案:
从数据透视表生成数据透视图
使用我们之前创建的Workbook对象,我们可以将图表“插入”到工作簿中,并为图表指定名称-名称出现在选项卡中。
由于数据透视表是数据透视缓存中的一个对象-它是工作簿中的一个对象,因此将图表对象添加为数据透视图,并使用数据透视表作为其数据。
在此处阅读相关文档:
https://docs.microsoft.com/en-us/office/vba/api/excel.workbook.charts
https://docs.microsoft.com/en-us/office/vba/api/excel.chart(object)
chrt_sheet = wb.Charts.Add()
chrt_sheet.Name = 'Pivot Chart'
指定图表类型
图表类型对应于Excel程序中可用的相同图表类型。
从枚举类型列表中选择。
例如,一个3D柱形图的xl3DColumn值编码如下:
win32c.xl3DColumn
使用先前定义的win32c对象ew来引用所有常量值,包括枚举列表。
此处记录:
https://docs.microsoft.com/en-us/office/vba/api/excel.chart.charttype
https://docs.microsoft.com/en-us/office/vba/api/excel.xlcharttype
chrt_sheet.ChartType = win32c.xl3DColumn
设置图表标题
在将HasTitle属性设置为True之前,工作表对象将没有ChartTitle属性。
chrt_sheet.HasTitle = True
chrt_sheet.ChartTitle.Text = "Chart Title"
设置配色方案
ChartColor值10-26对应于“图表工具”功能区的“设计”选项卡上的“更改颜色”菜单。
chrt_sheet.ChartColor = 13
指定图表布局
布局是可选的
布局与Excel程序中可供选择的布局列表相同。
在这种情况下,它们不作为列举列表提供。因此,您必须提供布局编号。通常为1到10。布局取决于相应的图表类型。要找出选择哪种布局,您将需要运行Excel程序并尝试每一种。如果将鼠标悬停在布局选项上,它将显示带有布局名称的“工具提示”。例如:“版式7”。您需要提供与各自的布局相关联的编号。
您使用ApplyLayout方法选择布局:
ApplyLayout(Layout, Chart Type)
此处记录:
https://docs.microsoft.com/en-us/office/vba/api/excel.chart.applylayout
chrt_sheet.ApplyLayout(7, win32c.xl3DColumn)
指定图表样式
样式是可选的
文档指出1到48是有效值。但是,正确的范围取决于所选的图表类型。
取决于图表类型201到352也有效。
要获取与图表类型可用的样式选择匹配的数字,请执行以下操作:
这将显示适合您情况的正确值
对于3D柱形图类型,范围是286到297
此处的相关文档:
https://docs.microsoft.com/en-us/office/vba/api/excel.chart.chartstyle
xlChartStyle = 294
chrt_sheet.ClearToMatchStyle
chrt_sheet.ChartStyle = xlChartStyle
图表样式实验
如果您好奇并想看看每个人的样子,请运行此代码
提示:删除注释“#”
#import time
#from time import sleep
#for xlChartStyle in range(286, 297):
# try:
# chrt_sheet.ClearToMatchStyle
# chrt_sheet.ChartStyle = xlChartStyle
# chrt_sheet.ChartTitle.Text = "Chart Style = "+str(xlChartStyle)
# sleep(1)
# except pythoncom.com_error as error:
# print("Chart Style = %s" % str(xlChartStyle))
格式化轴标签
XlAxisType枚举指定了三个Axis维度
在此示例中,我们还将删除Z轴刻度标签
chrt_sheet.Axes(win32c.xlCategory).AxisTitle.Text = "X Axis Title"
chrt_sheet.Axes(win32c.xlSeries).TickLabelPosition = win32c.xlNone
chrt_sheet.Axes(win32c.xlSeries).HasTitle = True
chrt_sheet.Axes(win32c.xlSeries).AxisTitle.Text = "Z Axis Title"
chrt_sheet.Axes(win32c.xlValue).AxisTitle.Text = "Y Axis Title"