10

我正在使用 python-docx 模块自动化创建 Word 文档的过程。特别是,我正在创建一个多项选择测试,其中问题编号为 1.、2.、3.、...,并且在每个问题下有 4 个答案应标记为 A.、B.、C.,和 D. 我使用一种样式来创建编号列表和字母列表。但是,我不知道如何重新启动这些字母。例如,第二个问题的答案范围为 E.、F.、G.、H。有谁知道如何将字母重新重新写回 A?我可以手动指定答案字符串中的字母,但我想知道如何使用样式表来做到这一点。谢谢你。

4

2 回答 2

8

简短的回答是,python-docx 尚不支持此功能,但如果您在项目的 Github 问题列表中询问此问题,我们可能会为您提供解决方法:https ://github.com/python- openxml/python-docx/issues/25

这个特殊的操作在 Word 中比我认识的任何人想象的要困难得多。我认为这与在 Word 的三个十年中的许多版本上保持某些向后兼容性有关。

只是为了给您一个想法,该样式引用了一个编号定义,该定义本身引用了一个抽象编号定义。具有该样式的每个段落都会获得序列中的下一个数字/字母。要重新启动序列,您必须创建一个新的编号定义,该定义引用与前一个相同的抽象编号序列。然后在序列应该重新开始的段落中引用新的编号定义。具有以下样式的段落在重新启动的序列中获得下一个数字/字母。

为了实现这一点,您需要:

  1. 定位样式的编号定义
  2. 找到它指向的抽象编号定义
  3. 创建一个设置了重启位的新编号定义
  4. 调整段落元素以引用新的编号定义

无论如何,既然我已经发泄了所有我可以告诉你的事情,我们实际上已经让它工作了。我们还没有将它添加到 API 中,我想主要是因为它并不完全清楚 API 应该是什么样子,而且它还没有上升到积压的顶部。但是,如果您非常想要它,那么几个解决方法可能会为您完成它。

在你的情况下,我想这将是一个折腾。我想我会强烈考虑在这种情况下将这些位直接放在段落中,但你最好能做出决定。

于 2014-05-05T03:44:24.160 回答
3

我创建了一个拉取请求(#582),在低级别解决了这种情况。我所做的只是定义实现numberingWML 子系统所需的 XML 类型。@scanny 创建了一个名为的子模块,该子模块xmlchemy创建了 XML 的半抽象表示,因此如果您熟悉该标准,则可以处理多级列表和其他编号任务。因此,如果您构建我的 fork,以下代码将起作用:

 #!/usr/bin/python

from docx import Document
from docx import oxml


d = Document()


"""
1. Create an abstract numbering definition for a multi-level numbering style.
"""
numXML = d.part.numbering_part.numbering_definitions._numbering
nextAbstractId = max([ J.abstractNumId for J in numXML.abstractNum_lst ] ) + 1
l = numXML.add_abstractNum()
l.abstractNumId = nextAbstractId
m = l.add_multiLevelType()
m.val = 'multiLevel'


"""
2. Define numbering formats for each (zero-indexed)
    level. N.B. The formatting text is one-indexed.
    The user agent will accept up to nine levels.
"""
formats = {0: "decimal", 1: "upperLetter" }
textFmts = {0: '%1.', 1: '%2.' }
for i in range(2):
    lvl = l.add_lvl()
    lvl.ilvl = i
    n = lvl.add_numFmt()
    n.val = formats[i]
    lt = lvl.add_lvlText()
    lt.val = textFmts[i]

"""
3. Link the abstract numbering definition to a numbering definition.
"""
n = numXML.add_num(nextAbstractId)

"""
4. Define a function to set the (0-indexed) numbering level of a paragraph.
"""
def set_ilvl(p,ilvl):
    pr = p._element._add_pPr()
    np = pr.get_or_add_numPr()
    il = np.get_or_add_ilvl()
    il.val = ilvl
    ni = np.get_or_add_numId()
    ni.val = n.numId
    return(p)

"""
5. Create some content
"""
for x in [1,2,3]:
    p = d.add_paragraph()
    set_ilvl(p,0)
    p.add_run("Question %i" % x)
    for y in [1,2,3,4]:
        p2 = d.add_paragraph()
        set_ilvl(p2,1)
        p2.add_run("Choice %i" % y)


d.save('test.docx')
于 2018-12-01T19:19:37.783 回答