項目官方文檔
項目官方git
docxtpl 軟件包使用兩個主要軟件包:
- python docx,用于讀取、寫入和創建子文檔
- jinja2用于管理插入到模板docx中的標記。jinja官網,?jinja中文網站
簡單示例
from docxtpl import DocxTemplatetpl = DocxTemplate('test.docx')context = {'template': '123'
}tpl.render(context)
tpl.save('test1.docx')
安裝
pip install docxtpl
導言
python-docx-template被開發出來,是因為python-docx的強大在于創建文檔,而不是修改它們。
這個想法是開始于創建一個需要用MicrosoftWord生成的文檔的示例,它可以像我們想要的那樣復雜:如圖片、索引表、頁腳、頁眉、變量,以及我們可以用Word做的任何事情。然后,當我們使用MicrosoftWord編輯文檔時,直接在文檔中插入類似于Jinja 2的標記。將文檔保存為.docx文件(XML格式):它將是.docx模板文件。
現在,我們可以使用python-docx-template從這個.docx模板和將關聯的上下文變量生成您想要的多個Word文檔。
注意:python-docx-template是測試的是MS Word 97格式,它可能不適用于其他版本.
Jinja 2類語法
因Jinja 2包被使用,可以使用Word文檔中的所有Jinja 2標記和過濾器。然而,要使它在Word文檔中工作,進行了些限制和擴展:
限制
通常的Jinja 2標簽,只能在同一個段落的同一個‘’run’中使用,它不能跨幾個段落使用,表行、‘run’。如果您想要管理段落、表行和整個‘run’的樣式,您必須使用特殊的標記語法,如下一章所述。
注意:MicrosoftWord的“Run”是一個具有相同風格的字符序列。例如,如果您創建一個具有相同風格的所有字符的段落:Word將在內部創建一個段落中的“Run”。現在,如果你在這段中間加了一個粗體,單詞會把前面的“Run”轉換成3‘Run’(普通-粗體-正常)。
擴展
為了管理段落、表行、表列、run,必須使用特殊的語法。(區別于jinja2)
{%p jinja2_tag %} for paragraphs
{%tr jinja2_tag %} for table rows
{%tc jinja2_tag %} for table columns
{%r jinja2_tag %} for runs
通過使用這些標記,python-docx-template將真正的Jinja 2標記放入文檔的XML源代碼中的正確位置。此外,這些標記還告訴python-docx-template移除位于開始和結束標記的位置的段落、表行、表列或run,只注意中間的位置。
重要*不要使用2次{%p, {%tr、`{%tc‘、{%r在同一段落、行、列或run中。例子:
不要用這個
{%p if display_paragraph %}Here is my paragraph {%p endif %}
而是使用
{%p if display_paragraph %}
Here is my paragraph
{%p endif %}
這種語法是可能是因為Microsoft word將每一行都看作是一個新的段落,{%p標簽不在同一段中
顯示變量
作為Jinja 2的一部分,可以使用雙括弧:{{ <var> }}。但如果 <var> 是RichText對象,必須指定要更改實際的“Run”。{{r <var> }}注意’r緊跟左括弧。
重要*不要使用?r?變量出現在模板中,因為{{r}} 可以解釋為 {{r 沒有指定變量。不過,您可以使用以‘r’開頭的更大的變量名。例如{{render_color}}將被解釋為{{ render_color }}不像{{r ender_color}}.
重要*不要使用2次 {{r 在同一run上。使用RichText.add()方法在python端連接多個字符串和樣式,并且只有一個字符串和樣式 {{r 在模板邊。
當您想要更改表格單元格的背景色時,有一種特殊情況,您必須在單元格的開頭放置以下標記
{% cellbg <var> %}
<var>必須包含顏色的十六進制代碼無散列符號
如果您想在多個列上動態地跨越一個表單元格(當您有一個具有動態列計數的表時,這是很有用的),您必須在單元格的最開始處放置下面的標記來跨越
{% colspan <var> %}
<var>必須包含要跨越的列數的整數。有關示例,請參見下一篇示例操作
為了展示{%, %}, {{或}},你可以用
{%, %}, {{ or }}
當你使用{{ <var> }}標記,它將被包含在 var 變量的字符串替換。但它將保持目前的格式。如果要添加動態變化的樣式,則必須同時使用以下兩種方式:{{r <var> }}標簽一個 RichText對象在 var 變量。您可以更改顏色、粗體、斜體、大小等,但最好的方法是使用microsoft word來定義自己的字符樣式(主頁選項卡->修改樣式->管理樣式按鈕->新建樣式,在窗體中選擇“字符樣式”),請參見tests/richtext.py,除了使用RichText(),您可以使用它的快捷方式:R()
重要*當你使用{{r }}它從docx模板中移除當前字符樣式,這意味著如果你沒有在RichText()設置字體樣式,樣式將返回到Microsoft Word默認樣式。這只會影響字符樣式,而不會影響段落樣式(MSWord管理的這2種樣式)。
可以通過Richtext將超鏈接添加到文本中。
tpl=DocxTemplate(‘your_template.docx’)
rt = RichText('You can add an hyperlink, here to ')
rt.add(‘google’,url_id=tpl.build_url_id(‘http://google.com’))
將rt放在您的語境中,然后使用{{r rt}}在你的模板中
您可以動態地將一個或多個圖像添加到文檔中(使用JPEG和PNG文件進行測試)。只要在你的模板中加上{{ <var> }},標記<var>是doxtpl.inlineImage的實例。
myimage=InlineImage(tpl,‘test_files/python_logo.png’,width=Mm(20))
您只需指定模板對象、圖像文件路徑和可選寬度和/或高度即可。對于高度和寬度,您必須使用毫米(毫米),英寸(英寸)或點(Pt)類。有關示例,請參見test/inlineImage.py。
模板變量可以包含使用python-docxWord文檔從頭開始構建的復雜變量。為此,首先從模板對象獲取子文檔對象,并將其用作python-docx文檔對象,參見tests/subdoc.py.
轉義,換行符,新段落,列表
當您使用{{ <var> }},您正在修改XMLWord文檔,這意味著您不能使用所有字符,特別是<, >和&。為了使用它們,你必須轉義它們。有四種方式:
context = { ‘var’:R(‘my text’) }和在模板中{{r <var> }}(注意r),
context = { ‘var’:‘my text’}和在模板中{{ <var>|e }}
context = { ‘var’:escape(‘my text’)}和在模板中{{ <var> }}。
在調用呈現方法時啟用自動轉義:tpl.render(context, autoescape=True)(默認值autoescape=false)
RichText()或R()提供換行符和新段落功能:只需使用\n或\a在文本中,它們將作相應的轉換。
有關更多信息,請參見tests/escape.py?。
另一個解決方案,如果要將列表包含到文檔中,即轉義文本并管理n和a,則可以使用’Listing’ class:
在python代碼中
context = { 'mylisting':Listing('the listing\nwith\nsome\nlines \a and some paragraph \a and special chars : <>&') }
在docx模板中只需使用{{ mylisting }}帶著Listing(),您將保持當前字符的樣式(除非在一個\a之后你開始新的一段落)。
在頁眉/頁腳中動態添加圖像是不可能的,但您可以更改它們。這樣做的目的是在模板中放置一個虛擬圖片,像往常一樣渲染模板,然后用另一個模板替換虛擬圖片。你可以同時為所有媒體做到這一點。Note1:縱橫比將與替換的圖像相同 Note 2:指定用于在docx模板中插入圖像的文件名(只要其basename,而不是完整路徑)。
替換dummy_header_pic.jpg的語法:
tpl.replace_pic('dummy_header_pic.jpg','header_pic_i_want.jpg')
替換發生在頁眉、頁腳和整個文檔正文中。
在頁眉/頁腳中動態添加圖片以外的其他媒體是不可能的,但您可以更改它們。這樣做的目的是在模板中放置一個虛擬媒體,像往常一樣呈現模板,然后用另一個模板替換虛擬媒體。你可以同時為所有媒體做到這一點。注意:對于圖像,高寬比將與替換的圖像注釋2相同:重要的是要有源媒體文件,因為它們需要計算它們的CRC才能在docx中找到它們。(虛擬文件名不重要)
替換dummy_header_pic.jpg的語法:
tpl.replace_media('dummy_header_pic.jpg','header_pic_i_want.jpg')
警告:與replace_pic() 方法不同,dummy_header_pic.jpg 必須存在模板目錄中,當在渲染和保存生成docx時。它必須與手動插入在docx模板的文件相同。替換可以發生在頁眉、頁腳和整個文檔正文中。
它的工作方式類似于媒體替換,只是它適用于嵌入式docx這樣的嵌入式對象。
替換embedded_dummy.docx的語法:
tpl.replace_embedded('embdded_dummy.docx','embdded_docx_i_want.docx')
警告:與REPLE_PIC()方法不同,embdded_dumy.docx必須存在于模板目錄中,在渲染和保存生成的docx時。它必須與手動插入docx模板的文件相同。替換發生在頁眉、頁腳和整個文檔正文中。
MS Word 2016將忽略表格的 \t。這對這個版本來說是特別的。但是LibreOffice或Wordpad沒有這個問題。對于以jinja2標記產生空格來開頭的行,也會出現同樣的情況:它們將被忽略。要解決這些問題,解決方案是使用Richtext:
tpl.render({'test_space_r' : RichText(' '),'test_tabs_r': RichText(5*'\t'),
})
在模板中,使用 {r 表示法:
{{r test_space_r}} Spaces will be preserved
{{r test_tabs_r}} Tabs will be displayed
可以兩種方式水平地跨表格單元格,一是利用colspan標記(請參閱tests/dynamic_table.py):
{% colspan %}
或者在for循環中(請參閱tests/horizontal_merge.py)):
{% hm %}
還可以在for循環中垂直合并單元格(請參閱 tests/vertical_merge.py):
{% vm %}
render() 接受 jinja_env 選項參數:您可以傳遞一個jinja環境對象。通過這種方式,您可以添加一些定制的jinja過濾器:
from docxtpl import DocxTemplate
import jinja2
def multiply_by(value, by):return value * bydoc = DocxTemplate("my_word_template.docx")
context = { 'price_dollars' : 5.00 }
jinja_env = jinja2.Environment()
jinja_env.filters['multiply_by'] = multiply_by
doc.render(context,jinja_env)
doc.save("generated_doc.docx")
然后在模板中,您將能夠使用
Euros price : {{ price_dollars|multiply_by(0.88) }}
查看其工作原理的最佳方法是閱讀示例,它們位于 tests/ 目錄。Docx測試模板在tests/templates/目錄。要生成最終的docx文件:
cd tests/
python runtests.py
生成的文件位于tests/output 目錄。
想要真正學會對應包,趕緊自己下載,根據測試文件測試吧!