Python 透過python-docx操作Microsoft Word — docx文件

Sean Yeh
Python Everywhere -from Beginner to Advanced
15 min readSep 8, 2022

--

Matcha mountain, Yi-lan, Taiwan, photo by Sean Yeh

身為上班族的大多數人,想必都曾經使用過Microsoft Word軟體來編輯各式各樣的辦公室文件。並且大家應該都是徒手的打開Microsoft Word軟體,在裡面編輯各式各樣的docx文件。你是否曾經想過,透過程式的幫助讓我們快速建立某些常用的文件,以省去透過徒手複製貼上的繁複步驟?

雖然我們以前學過利用Python中的with open等方式來建立txt文件,但是Word文件的處理與一般純文字txt文件的處理不一樣。由於Word文件屬於2進位(binary)檔,無法只是透過open函式就讀取裡面的資料,處理起來會比文字txt文件要複雜得多了。

即便如此,並不表示Python就無法處理Word文件。實際上只要透過Python的第三方函式python-docx,就可以輕鬆處理Word檔案。

python-docx是一個函式庫,它被設計用來建立與更新副檔名為docx的Microsoft Word文件。從這裡也可以看到Python具有強大的第三方函式庫支援,可以完成各項不同的任務。

安裝python-docx

python-docx的程式碼放在PyPI上面,可以透過pip來安裝。

PYPI

輸入下面指令安裝python-docx套件(目前版本為0.8.11)。

pip install python-docx

開始體驗:建立docx文件

安裝完畢後,就可以開始體驗python-docx程式。在python-docx文件中,開宗明義就告訴我們這個套件可以用來建立以及更新微軟Microsoft Word的docx文件。

python-docx is a Python library for creating and updating Microsoft Word (.docx) files.

從範例暸解python-docx

python-docx文件中,我們還可以找到如下的範例,此範例告訴我們可以透過python-doc套件完成什麼樣子的工作:

from docx import Document
from docx.shared import Inches
document = Document()document.add_heading('Document Title', 0)p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='Intense Quote')
document.add_paragraph(
'first item in unordered list', style='List Bullet'
)
document.add_paragraph(
'first item in ordered list', style='List Number'
)
document.add_picture('monty-truth.png', width=Inches(1.25))records = (
(3, '101', 'Spam'),
(7, '422', 'Eggs'),
(4, '631', 'Spam, spam, eggs, and spam')
)
table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'
for qty, id, desc in records:
row_cells = table.add_row().cells
row_cells[0].text = str(qty)
row_cells[1].text = id
row_cells[2].text = desc
document.add_page_break()document.save('demo.docx')

先不考慮其他,直接執行此範例,看看會得到什麼樣的結果?

範例程式執行後,會得到一個demo.docx檔案,該檔案位於專案的資料夾裡面。

demo.docx檔

換句話說,我們透過上面的範例程式碼,建立了一個微軟Microsoft Word的.docx檔案。以下的範例程式碼已經分成幾個區塊,並且標上數字,我們接下來就透過這個檔案來觀察套件的程式碼。

建立(寫入)docx文件

要編寫一個docx文件,必須先建立一個文件的物件,才可以執行編寫的各種程序。因此,我們需要先匯入Document(紅字1)。匯入套件後就可以呼叫docx中的Document()方法,此方法會返回一個新的空白的docx文件。如紅字2的地方,我們利用建立Document()一個Document物件。

from docx import Documentdocument = Document()

透過上面的方式建立的空白文件,乃是基於Microsoft Word預設的版型而建立。該過程就像我們平常打開Microsoft Word軟體,並且執行「檔案 \ 新增文件」一樣。

建立一個Document物件後,就可以透過Document物件裡面的其他方法控制各個段落。最後再使用save()方法,將Document物件儲存起來(紅字9),及可完成一個doc檔案。

docx文件檔案結構

與純文字比較,docx檔並不單純,檔案中含有很多結構。這些結構表現在python-docx中是透過三種不同的類型表示。

  • Document物件:代表docx整個文件。
  • Paragraph物件:代表文件中的段落。
  • Run物件:以相同樣式連續鄰接的文字。當文字的樣式有變化時,就需要一個新的Run物件。

以上三種類型之間的關係為:Document物件含有一個Paragraph物件的串列,Paragraph物件含有一個Run物件的串列。

以範例來說(如下圖),整份文件為Document物件,而句子 A plain paragraph having some bold and some italic. 為Paragraph物件。該句子中又可以分為四個不同的Run物件。

新增文件段落

段落(paragraph)是 Word 的基礎。除了用於本文之外,也用於標題和項目表列上,如項目符號。

add_paragraph

建立一個段落最簡單的方法就是透過add_paragraph()來建立:

p = document.add_paragraph('A plain paragraph having some ')

透過上面的方式,會在文件的「末尾」增加新的段落。請注意 add_paragraph() 是在「末尾」添加段落,而不是在前面插入段落。

如果需要兩個段落,可以再次呼叫 add_paragraph() 方法來新增段落。例如紅字5與紅字6。

在這裡,我們使用 p 作為該段落的變數。然而我們在實際使用時,通常增加段落之後不會再對它做任何事情,但因此未必需要將該段落指定給任何變數。可以像下面這樣子處理:

document.add_paragraph('Intense quote', style='Intense Quote')

insert_paragraph_before

當然,將段落指定給一個變數也不是完全沒有用途,使用它的好處是,可以將該段落作為一個基準點,在該段落的上方插入一個新的段落。

例如下面的程式碼:

prior_paragraph = paragraph.insert_paragraph_before('Lorem ipsum')

在這個程式碼中,透過insert_paragraph_before讓我們可以在paragraph的上方插入一個段落。這功能對於有修改現有文件的需求時,就變得很重要。

新增文件標題

一般來說,文件都會分為幾個部分,而每個部分都以標題開頭。可以透過呼叫add_heading的方法來新增標題:

document.add_heading('Document Title')

在預設的情況下,上面的方法這會新增一個最高等級的標題。它在Microsoft Word中會顯示「階層1」。因此,當你需要一個較小的標題時,只需要對該標題指定等級。等級的範圍有九種,可以選擇1到9之間的整數。例如下面選擇的等級為一( level=1

document.add_heading('Heading, level 1', level=1)

但如果將等級指定為 0,則會增加「標題」段落。適合用在文件剛開始的部分(紅字3)。其中第二個引數,我們可以選擇0~4的數字,分別代表不同層級的標題,數字越少代表標題等級越高。

document.add_heading('Document Title', 0)

增加段落風格

基本上,Word 段落樣式很像網站的CSS 樣式,讓您可以將一整套格式選項一次性的套用在段落上面。

您可以在add_paragraph建立段落時運用段落樣式style。例如:Intense Quote為引用段落、List Bullet為圓點符號而List Number為數字項目符號(紅字5):

document.add_paragraph('Intense quote', style='Intense Quote')document.add_paragraph('first item in unordered list', style='List Bullet')document.add_paragraph('first item in ordered list', style='List Number')

常見的樣式如下表:

增加字元風格

以Word文件來說,樣式可以分為三種類型:

  • 段落樣式
  • 字元樣式
  • 連結樣式

其中,段落樣式可以套入Paragrath物件;字元樣式可以套入Run物件,連結樣式則以上兩種都可以套入。

以下為常見的字元樣式如下表:

Run屬性

我們可以在Run物件的後面設定各種text的屬性以改變字元的樣式。每個屬性都可以被設定為三個不同狀態,True(啟用)、False(停用)或None。如紅字4的地方,我們可以設定段落p中的某個run物件屬性為粗體(bold)以及另一個run的物件屬性為斜體(italic)

p.add_run('bold').bold = True
p.add_run('italic.').italic = True

以下為Run物件中較常用的text屬性:

新增換頁符號

如紅字8,當我們想要在一段文章的後面加上換頁符號,讓接著的另一段文章可以從另外一個新的頁面開始,可以使用add_page_break來新增換頁符號。

document.add_page_break()

建立表格

我們常常會需要在Word文件中建立表格來呈現某些內容,python-docx 也可以幫助我們在文件中建立表格。(如紅字7)

table = document.add_table(rows=2, cols=5)

操作儲存格

建立表格時有幾個屬性與方法需要暸解。以表格的最小單位儲存格cell來說,我們可以透過指定Row(列)與Column(行)的方式來觸及它。例如下面的程式碼:

cell = table.cell(0, 1)

透過這個程式碼可以觸及到最上面的一個Row(列)。Column(行)與Row(列)的開始值都是0。當有了儲存格之後,就可以對該儲存格進行其他的操作。例如,我們可以在該儲存格中添加文字。

cell.text = 'Hi, hello World'

通常來說,一次操作一格儲存格是比較容易的。此外,也可以透過.row 屬性對一整列進行操作,每一個列都有一個.cells 屬性就像串列一樣,可以指定位置來觸及每一個Row(列)上面不同位置的cell儲存格。例如變數row代表第一個Row(列):

row = table.rows[1]
row.cells[0].text = 'for you.'
row.cells[1].text = 'And this is for you, too'

row.cells[0] 可以觸及到第一個儲存格,row.cells[0] 則可以觸及到第二個儲存格。上面的方式對於行來說也是一樣的。只要將.row 屬性改為.column屬性,就可以對一整行進行操作。

行列的迭代

表格上面的.rows.columns 都是可以迭代的。因此,可以透過for迴圈進行迭代。此外,在Column(行)與Row(列)裡面的 .cells 也是可以被迭代的。例如透過下面方式可以把所有的儲存格內容印出來:

table = document.add_table(rows=2, cols=5)for row in table.rows:
for cell in row.cells:
print(cell.text)

行列的數量

如果想要知道表格內有多少行與列,可以透過 len() 的使用得到結果。

row_count = len(table.rows)col_count = len(table.columns)

嗣後追加行列

如果在建立表格之後,想要追加某一列的話,可以使用.add_row()的方式增加。

row = table.add_row()

新增圖片

就像在Word中透過「插入 \ 圖片 \ 從檔案插入圖片… 」的方式添加圖片一樣,我們可以在Python python-docx 中,透過.add_picture的方式,替文件插入圖片。

document.add_picture('image-file_name.jpg')

上面例子的圖片放在開發環境系統的目錄中,該圖片會插入文件的尾端。

調整圖片尺寸

如果不做其他特別的設定,插入的圖片會以它原本的尺寸插入文件中。有時候插入圖片的大小尺寸不太適用時,可以透過指定圖片的寬度或高度來調整插入圖片的尺寸。但在調整尺寸之前需要進行以下的匯入作業:

from docx.shared import Inches

從docx裡面Inches匯入此後,就可以讓我們指定長寬的尺寸,其單位為英吋(Inches)。如下程式碼,我們在.add_picture的第二個引數中指定圖片的寬度為1英寸。

document.add_picture('image-file_name.jpg', width=Inches(1.0))

你可以同時指定圖片的寬度與長度,但是依照經驗,只要指定長度或寬度ㄧ邊的尺寸,就可以讓另外一邊自動達到適當的尺寸。

讀取 docx 文件

除了建立新的docx文件外,我們也可以透過python-docx讀取已經存在的docx檔案。

如果只需要文件裡面的文字資訊而不需要其他的樣式的話,可以透過for迴圈,巡迴讀取docx文件,並將裡面的文字字串取出。

for迴圈可以尋遍文件的paragraphs物件,將裡面的文字逐一新增(append)到_full_text串列中。

from docx import Documentfilename = 'demo.docx'
document = Document(filename)
_full_text = []
for paragraph in document.paragraphs:
_full_text.append(paragraph.text)
print(fullText)

迴圈結束後,可以使用join的方式,把 _full_text串列中搜集到的字串,中間加上換行符號加( \\n ),並顯示出來。

print('\\n'.join(_full_text))

結語

以上說明為透過Python的第三方函式python-docx,建立Microsoft Word軟體的docx檔案與讀取docx檔案的操作方式。學會了如何使用這個套件後,就可以利用它來解決各種不同的實務上需求。下一篇將會透過這個套件,實際的建立一個文件套版的程式。

--

--

Sean Yeh
Python Everywhere -from Beginner to Advanced

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。