これをpython-docx
で動作させるようにしています:
これを使用して取得できる箇条書きリスト:
from docx import Document
doc = Document()
p = doc.add_paragraph()
p.style = 'List Bullet'
r = p.add_run()
r.add_text("Item 1")
# Something's gotta come here to get the Sub-Item 1
r = p.add_run()
r.add_text("Item 2")
# Something's gotta come here to get the Sub-Item 2
真ん中に別の段落を追加しても、本質的には、親と同じ書式で別のList Bullet
を作成しているので、必要な子のような書式ではないため、役に立ちません。また、同じ段落に別のrun
を追加しても効果はありません(私はこれを試しましたが、全体を台無しにしています。)。それを行う方法はありますか?
それを行う方法はありますが、それはあなたの側で少し余分な作業を伴います。現在、python-docxには、これを行うための「ネイティブ」インターフェースはありません。箇条書きの各項目は、個別の段落でなければなりません。ランはテキスト文字にのみ適用されます。
リストの箇条書きまたは番号付けは、抽象的なスタイルを参照する具体的な箇条書きまたは番号スタイルによって制御されるという考え方です。抽象スタイルは、影響を受ける段落のスタイルを決定し、具体的な番号付けは、抽象シーケンス内の番号/箇条書きを決定します。つまり、箇条書きのない段落と、箇条書きの段落の間に番号を付けることができます。同時に、新しいコンクリートスタイルを作成することで、番号付け/箇条書きのシーケンスをいつでも再開できます。
この情報はすべて Issue#25 でハッシュされます(詳細には失敗します)。これを今すぐ休めるための時間やリソースはありませんが、ディスカッションスレッドの comment に残した関数を作成しました。この関数は、インデントのレベルと必要な段落スタイルに基づいて抽象的なスタイルを検索します。次に、その抽象的なスタイルに基づいて具象スタイルを作成または取得し、それを段落オブジェクトに割り当てます。
def list_number(doc, par, prev=None, level=None, num=True):
"""
Makes a paragraph into a list item with a specific level and
optional restart.
An attempt will be made to retreive an abstract numbering style that
corresponds to the style of the paragraph. If that is not possible,
the default numbering or bullet style will be used based on the
``num`` parameter.
Parameters
----------
doc : docx.document.Document
The document to add the list into.
par : docx.paragraph.Paragraph
The paragraph to turn into a list item.
prev : docx.paragraph.Paragraph or None
The previous paragraph in the list. If specified, the numbering
and styles will be taken as a continuation of this paragraph.
If omitted, a new numbering scheme will be started.
level : int or None
The level of the paragraph within the outline. If ``prev`` is
set, defaults to the same level as in ``prev``. Otherwise,
defaults to zero.
num : bool
If ``prev`` is :py:obj:`None` and the style of the paragraph
does not correspond to an existing numbering style, this will
determine wether or not the list will be numbered or bulleted.
The result is not guaranteed, but is fairly safe for most Word
templates.
"""
xpath_options = {
True: {'single': 'count(w:lvl)=1 and ', 'level': 0},
False: {'single': '', 'level': level},
}
def style_xpath(prefer_single=True):
"""
The style comes from the outer-scope variable ``par.style.name``.
"""
style = par.style.style_id
return (
'w:abstractNum['
'{single}w:lvl[@w:ilvl="{level}"]/w:pStyle[@w:val="{style}"]'
']/@w:abstractNumId'
).format(style=style, **xpath_options[prefer_single])
def type_xpath(prefer_single=True):
"""
The type is from the outer-scope variable ``num``.
"""
type = 'decimal' if num else 'bullet'
return (
'w:abstractNum['
'{single}w:lvl[@w:ilvl="{level}"]/w:numFmt[@w:val="{type}"]'
']/@w:abstractNumId'
).format(type=type, **xpath_options[prefer_single])
def get_abstract_id():
"""
Select as follows:
1. Match single-level by style (get min ID)
2. Match exact style and level (get min ID)
3. Match single-level decimal/bullet types (get min ID)
4. Match decimal/bullet in requested level (get min ID)
3. 0
"""
for fn in (style_xpath, type_xpath):
for prefer_single in (True, False):
xpath = fn(prefer_single)
ids = numbering.xpath(xpath)
if ids:
return min(int(x) for x in ids)
return 0
if (prev is None or
prev._p.pPr is None or
prev._p.pPr.numPr is None or
prev._p.pPr.numPr.numId is None):
if level is None:
level = 0
numbering = doc.part.numbering_part.numbering_definitions._numbering
# Compute the abstract ID first by style, then by num
anum = get_abstract_id()
# Set the concrete numbering based on the abstract numbering ID
num = numbering.add_num(anum)
# Make sure to override the abstract continuation property
num.add_lvlOverride(ilvl=level).add_startOverride(1)
# Extract the newly-allocated concrete numbering ID
num = num.numId
else:
if level is None:
level = prev._p.pPr.numPr.ilvl.val
# Get the previous concrete numbering ID
num = prev._p.pPr.numPr.numId.val
par._p.get_or_add_pPr().get_or_add_numPr().get_or_add_numId().val = num
par._p.get_or_add_pPr().get_or_add_numPr().get_or_add_ilvl().val = level
デフォルトの組み込みドキュメントスタブのスタイルを使用すると、次のようなことができます。
d = docx.Document()
p0 = d.add_paragraph('Item 1', style='List Bullet')
list_number(d, p0, level=0, num=False)
p1 = d.add_paragraph('Item A', style='List Bullet 2')
list_number(d, p1, p0, level=1)
p2 = d.add_paragraph('Item 2', style='List Bullet')
list_number(d, p2, p1, level=0)
p3 = d.add_paragraph('Item B', style='List Bullet 2')
list_number(d, p3, p2, level=1)
スタイルは、段落のタブ位置やその他の表示特性に影響を与えるだけでなく、適切な抽象的な番号付けスキームの検索にも役立ちます。 prev=None
の呼び出しでp0
を暗黙的に設定すると、関数は新しい具象番号付けスキーマを作成します。残りのすべての段落は、prev
パラメーターを取得するため、同じスキームを継承します。 prev
として使用される段落の番号付けが呼び出しの前に設定されている限り、list_number
の呼び出しをadd_paragraph
の呼び出しとインターリーブする必要はありません。