【问题标题】:Flexibly assign chart bar color according to value - python-pptx根据值灵活分配图表条颜色 - python-pptx
【发布时间】:2018-01-20 14:12:51
【问题描述】:

有人提出了类似的问题,但尽管多次尝试,我仍然无法让它工作。 Python PPTX Bar Chart negative values , Color 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 出色的图书馆以及您对所有其他问题的回答。帮了大忙了。

=======更新=======

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

【问题讨论】:

    标签: python python-pptx


    【解决方案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 中寻找的是像 &lt;c:invertIfNegative val=0&gt; 这样的元素。如果它不存在或具有其他价值,那就可以解释一些事情。

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

    如果您无法解决此问题,我建议您在 GitHub 问题列表中为 python-pptx 打开一个问题,在那里我们可以使用对话模式而不是此处的问答格式更好地挖掘它。

    【讨论】:

    • 该元素确实适应了我分配给它的布尔值以及通过 ppt UI。问题是 powerpoint 似乎没有注册它。如果我设置为 false 我需要检查然后取消选中它才能正确显示。如果我将它设置为 True 那么我只需要取消选中它就可以了。我认为背景颜色不是“可设置的”?只有 fore_color 填充属性允许设置颜色。作为临时解决方案,我使用了图案并将前景色和背景色都设置为所需的颜色。有机会我会开一个github issue!
    • 下一步将比较 python-pptx 生成的 XML 和 PowerPoint 生成的 XML,一旦你来回更改它以使其正常工作。您可以使用相同的series._element.xml 位,只需访问现有图表,而不是像第一次那样添加它。原因很可能是这两个 XML 树之间的不同之处之一。
    【解决方案2】:

    还没有安装 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
    

    【讨论】:

    猜你喜欢
    • 2015-03-25
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多