Python-pptx:“显示与图表重叠的图例”

Python-pptx: “Show legend overlapping the chart”

我正在使用 Office 2007。 我发现如果我想在 office2007 中显示与图表重叠的图例。 XML 应该如下所示。

`-<c:legend>
   <c:overlay val="1"/>` 

但无论我使用 python-pptx 'chart.legend.include_in_layout = True' 中的 API 还是将其保留为默认值。生成的 XML 将始终如下所示。

`-<c:legend>
   <c:overlay/>` 

如果没有val=1,office2007 将无法正确显示格式。 我该怎么做才能强制 python-pptx 写入 val=1?谢谢。

说明

简而言之,True值没有明确设置(与False相反),因为True对应于overlay的默认值val属性。

要更详细地解释它 - 您可以按照 python-pptx 层次结构,如下所示:overlaymapped to CT_Boolean (all overlay oxml elements are instantiated from CT_Boolean). The actual val parameter is then mapped via OptionalAttribute 并且使用默认值 [=17= 定义]:

class CT_Boolean(BaseOxmlElement):
    """
    Common complex type used for elements having a True/False value.
    """
    val = OptionalAttribute('val', XsdBoolean, default=True)

现在,当将可选属性设置为其默认值时,它实际上是 skipped/deleted,如您所见 here if value == self._default:

class OptionalAttribute(BaseAttribute):
    """
    Defines an optional attribute on a custom element class. An optional
    attribute returns a default value when not present for reading. When
    assigned |None|, the attribute is removed.
    """

    @property
    def _setter(self):
        def set_attr_value(obj, value):
            if value == self._default:
                if self._clark_name in obj.attrib:
                    del obj.attrib[self._clark_name]
                return
            str_value = self._simple_type.to_xml(value)
            obj.set(self._clark_name, str_value)
        return set_attr_value

修复 - 提供自定义 CT_Boolean class

在需要使用叠加层之前在某处添加这些行。它将用自定义 CT_Boolean_NoDefault class:

覆盖 python-pptx overlay 映射
from pptx.oxml import register_element_cls
from pptx.oxml.xmlchemy import BaseOxmlElement, OptionalAttribute
from pptx.oxml.simpletypes import XsdBoolean


class CT_Boolean_NoDefault(BaseOxmlElement):
    """
    Common complex type used for elements having a True/False value with no
    default value.
    """
    val = OptionalAttribute('val', XsdBoolean)

register_element_cls('c:overlay', CT_Boolean_NoDefault)

这对我有用,最后我得到了:

<c:legend>
    <c:overlay val="1"/>
</c:legend>

修复 - 永久修改 python-pptx

不推荐这样做,但您可能想要修改 python-pptx,而不是从上面为您 运行.

的每个脚本添加解决方案

首先,将以下内容添加到 pptx/oxml/chart/shared.py 中,它定义了一个没有默认值的新 bool class:

class CT_Boolean_NoDefault(BaseOxmlElement):
    """
    Common complex type used for elements having a True/False value.
    """
    val = OptionalAttribute('val', XsdBoolean)

其次,修改pptx/oxml/__init__.py添加新的boolclass:

from .chart.shared import (
    CT_Boolean, CT_Double, CT_Layout, CT_LayoutMode, CT_ManualLayout,
    CT_NumFmt, CT_Tx, CT_UnsignedInt, CT_Boolean_NoDefault
)

三、修改pptx/oxml/__init__.py,将overlay元素的映射改为新的bool class:

register_element_cls('c:overlay', CT_Boolean_NoDefault)

更好的解决方案

如果你有时间,请提交工单here so it might become a permanent fix. In case @scanny找个时间,他会看这个。也许对此也有更好的解决方案,我完全错过了一些东西。

@pansen 的分析很到位。这是在您的情况下使用此方法的另一种方法,它的重量可能会轻一些:

def include_in_layout(legend):
    legend_element = legend._element
    overlay = legend_element.get_or_add_overlay()
    overlay.set('val', '1')

这似乎是该版本的 PowerPoint 与 ISO/IEC 29500 规范的局部不一致性。正如 pansen 正确指出的那样,缺少 val 属性的解释与 val=1 (True) 相同。我很想知道这种不符合项的范围有多广,即其他哪些元素表现出同样的行为。 CT_Boolean 类型在 PowerPoint 中使用得非常频繁,例如粗体、斜体、varyColors、平滑等等。因此,需要谨慎应用 "compensating" 修复,以避免报告其他元素的错误结果。

我想我会接受潘森的提示,只为这个元素使用一个专门的元素 class。对于没有 val 属性的元素,它仍会报告 True,这与在此版本的 PowerPoint 上观察到的行为不一致;但假设其他版本行为正确(根据规范),不一致将被本地化并且至少将 True 分配给 属性 将使图例以您想要的方式显示。