根据值灵活分配图表栏颜色 - python-pptx

时间:2018-01-20 14:12:51

标签: python python-pptx

已经提出了类似的问题,但尽管多次尝试,我仍然无法使其发挥作用。 Python PPTX Bar Chart negative valuesColor Specific Bar Chart Differently in Python PPTX

这是一个简单的例子:

from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Cm
from pptx.dml.color import RGBColor

_red = RGBColor(255, 0, 0)
_green = RGBColor(0, 128, 0)

# create presentation with 1 slide ------
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[5])
x = ['one','two','three', 'four']
y = [-257.0, 1920.0, 2809.0, 500.0]
specs = {
    'height': Cm(7.82),
    'width': Cm(14.8),
    'left': Cm(2.53),
    'top': Cm(5.72)}

data = ChartData()
data.categories = x
label_values = tuple(y)
data.add_series('Series 1', label_values)
frame = slide.shapes.add_chart(XL_CHART_TYPE.BAR_CLUSTERED,                 
specs['left'],specs['top'], specs['width'],specs['height'], data)
chart = frame.chart
series = chart.series[0]

for i in range(0,len(y)):
    point = series.points[i]
    fill = point.format.fill
    fill.solid()
    fill.fore_color.rgb = _red if y[i]<0 else _green
series.invert_if_negative = False

prs.save('chart-01.pptx')

What I want

What I'm getting

我尝试了很多不同的配置。 Python-pptx正在工作,因为通过在我的代码中使用series.invert_if_negative将布尔值设置为true或false,当我打开powerpoint演示文稿时,复选框会相应地起作用,如第二张图片所示。如果我在生成演示文稿后手动切换它几次,它只能在powerpoint中正确显示。我尝试更改语句的位置,将其设置为true或false,甚至在将其设置为false之前将其交替多次。

有趣的是,这只发生在负条形图上,即正值,我可以随意更改颜色。即使所有值都是负数。我无法将它们全部设置为某种颜色。他们唯一有颜色并且不显示为白色框的时候是我根本不尝试改变颜色而他们默认为演示主题颜色。

我怀疑这是一个powerpoint问题,而不是pptx-python问题,但是解决这个问题的任何帮助都将非常感激!

Powerpoint版本:Mac上的15.36 Python-pptx版本:0.6.7

感谢神奇的图书馆Scanny以及您对所有其他问题的回答。它有很多帮助。

======= UPDATE =======

这个问题有一个解决方法,就是使用图案填充并将back_color和fore_color设置为相同的颜色以达到相同的效果。

2 个答案:

答案 0 :(得分:1)

这可能是由python-pptx生成的默认XML与PowerPoint生成(后来解释)的默认XML之间的差异。

您应首先检查您的版本,以确保您使用最新版本。有一些案例反过来,PowerPoint不遵守规范中规定的默认值,可能c:invertIfNegative默认为True。我们添加了一些代码来解决这些问题。

以下是对您的代码的一些调整:

chart = slide.shapes.add_chart(
    XL_CHART_TYPE.BAR_CLUSTERED, specs['left'], specs['top'], 
    specs['width'], specs['height'], data
).chart
series = chart.series[0]
series.invert_if_negative = False

for idx, point in enumerate(series.points):
    fill = point.format.fill
    fill.solid()
    fill.fore_color.rgb = _red if y[idx]<0 else _green

print(series._element.xml)

prs.save('chart-01.pptx')

我认为这不会解决任何问题,但可能会使意图更加清晰,并且大部分打印出系列的XML。例如,您可以在设置反转选项之前和之后移动该线。

您在XML中寻找的是像<c:invertIfNegative val=0>这样的元素。如果它不存在或具有其他价值,那将解释一些事情。

负值上的“白色”更准确地说是“没有颜色”,现在我想到它可能是因为没有背景颜色集。假设PowerPoint在“反转”时交换前景和背景是合理的。所以要尝试的一件事是设置负面项目的背景颜色而不是前景,看看是否有任何有趣的东西。

如果您无法解决此问题,我建议您在python-pptx的GitHub问题列表中打开一个问题,我们可以在那里使用对话模式而不是Q&amp;这里的格式。

答案 1 :(得分:0)

Haven没有安装pptx模块,所以我无法测试我的答案。但我可以看到你的if语句格式不正确。

试试这个:

from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Cm
from pptx.dml.color import RGBColor

_red = RGBColor(255, 0, 0)
_green = RGBColor(0, 128, 0)

# create presentation with 1 slide ------
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[5])
x = ['one','two','three', 'four']
y = [-257.0, 1920.0, 2809.0, 500.0]
specs = {
    'height': Cm(7.82),
    'width': Cm(14.8),
    'left': Cm(2.53),
    'top': Cm(5.72)}

data = ChartData()
data.categories = x
label_values = tuple(y)
data.add_series('Series 1', label_values)
frame = slide.shapes.add_chart(XL_CHART_TYPE.BAR_CLUSTERED,                 
specs['left'],specs['top'], specs['width'],specs['height'], data)
chart = frame.chart
series = chart.series[0]

for i in range(0,len(y)):
    point = series.points[i]
    fill = point.format.fill
    fill.solid()
    if y[i]<0:
        fill.fore_color.rgb = _red  
    else:
        fill.fore_color.rgb = _green
series.invert_if_negative = False