兩種安裝方式:
pip install python-docx
conda install -c conda-forge python-docx
常用到的導入命令:
import docx
from docx import Document
from docx.shared import Pt,Cm,Inches
from docx.oxml.ns import qn #python-docx中設置中文字體
from docx.shared import RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH #設置對齊方式
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_LINE_SPACING
官網文檔:https://python-docx.readthedocs.io/en/latest/index.html
documnet/paragraph/run 的關系

不管是paragraph還是title,它們在python里的type都是docx.text.paragraph.Paragraph
功能簡介:
1.建立標題的方法
document.add_heading()
#方法1 - 用level設置,level為0-9,對應不同級別的標題, 不寫level時,默認level=1
# level =0 是一種特殊的heading(字體1號而且有下划線,但是沒有導航)
document.add_heading('Heading 1', level=1)
#方法2 - 用style來設置不同級別的標題
document.add_paragraph('Heading 1', style="Heading 1")
應用:要設置格式就需要用add_run, add_paragraph()生成的段落不能直接設置字體
#設置大標題level=0,及其格式,先不在add_heading中寫文字,而在add_run中添加,
head0=document.add_heading(level=0)
#設置標題居中,這一句導入 from docx.enum.text import WD_ALIGN_PARAGRAPH
head0.alignment = WD_ALIGN_PARAGRAPH.CENTER
title_run=head0.add_run('90天Cashflow現金流表數據統計',)
title_run.font.size = Pt(20) #14是四號字
# 設置標題英文字體
title_run.font.name = 'Times New Roman'
# 設置標題中文字體
title_run.element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
# 設置字體顏色
title_run.font.color.rgb = RGBColor(54,95,145)
可以對照‘RGB顏色對照表’,設置更多的顏色
2.建立段落
document.add_paragraph() #建立段落
也可以將一個段落用作“光標”,並在其上方直接插入一個新段落:
prior_paragraph = paragraph.insert_paragraph_before('Lorem ipsum') #這里的paragraph.是要插入的paragraph name, 這里的Lorem ipsum是要插入的文字內容。
這樣可以將段落插入文檔的中間,這在修改現有文檔而不是從頭開始生成文檔時通常很重要。
應用:
from docx.shared import Pt,Cm
from docx.oxml.ns import qn
#以下為段落正文的全局設置
document = Document()
style = document.styles['Normal']
# 設置西文字體
style.font.name = 'Times New Roman'
style.font.size = Pt(12)
# 設置中文字體
style.element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
# 設置首行縮進, 先獲取段落樣式
paragraph_format = style.paragraph_format
# 首行縮進0.74厘米,即2個字符
paragraph_format.first_line_indent = Cm(0.74)
段落的對齊方式 WD_ALIGN_PARAGRAPH.LEFT

行距的設置
from docx.shared import Pt
p = file.add_paragraph()
p.paragraph_format.line_spacing = Pt(16) #行距,16磅對應三號字體大小
p.add_run('設置行距的示例文字')
段落間距的設置
from docx.shared import Pt
p = file.add_paragraph()
p.paragraph_format.space_before = Pt(14) #段前間距,14磅對應四號字體大小
p.paragraph_format.space_after = Pt(14) #段后間距
p.add_run('設置段前/段后的示例文字')
段落還可以使用style設置風格:
# 圓點列表
document.add_paragraph('first item in unordered list', style='List Bullet')
# 序號列表
document.add_paragraph( 'first item in ordered list', style='List Number')
# 引用
document.add_paragraph('Intense quote', style='Intense Quote')
運行如下:

設置中文字體
設置標題heading的中文字體類型 + 設置正文的中文字體類型
#依賴包:
from docx import Document
from docx.shared import Pt
from docx.shared import Inches
from docx.oxml.ns import qn
#修改正文的中文字體類型,示例代碼:(全局設置)中文字體設置好象不加u也可以
document=Document()
document.styles['Normal'].font.name=u'微軟雅黑'
document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'微軟雅黑')
#修改3級標題的字體類型,示例代碼:
run = document.add_heading('',level=3).add_run(u"應用場景示例: ")#應用場景示例標題
run.font.name=u'微軟雅黑'
run._element.rPr.rFonts.set(qn('w:eastAsia'), u'微軟雅黑')
更詳細的字體設置指引:http://www.jhanmath.com/?p=130
設置中文字體與西文字體不同,可能是word內部處理方式不同,主要是通過以下這句:
style.element.rPr.rFonts.set(qn('w:eastAsia'), '宋體') # style中
r._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋_GB2312') # run中
以下給出在style和run中設置的代碼。
style中的設置
更改現有style
style = document.styles['Normal']
style.font.name = 'Times New Roman' # 必須先設置font.name
style.font.size = Pt(14)
style.element.rPr.rFonts.set(qn('w:eastAsia'), '宋體')
創建新style
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.text import WD_LINE_SPACING
mystyle = document.styles.add_style('titlepage_title', WD_STYLE_TYPE.PARAGRAPH)
mystyle.font.name = 'Times New Roman' # 必須先設置font.name
mystyle.font.size = Pt(16)
mystyle.font.bold = True
mystyle.element.rPr.rFonts.set(qn('w:eastAsia'), '宋體')
mystyle.paragraph_format.space_after = Pt(0)
# mystyle.paragraph_format.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE
mystyle.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
mystyle.paragraph_format.line_spacing = 1.8
對創建的段落應用設置好的style即可改變中文字體。
run中的格式設置
p = document.add_paragraph()
r = p.add_run('文字')
r.font.name = '仿宋_GB2312' # 必須先設置font.name
r._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋_GB2312')
r.font.size = Pt(14)
3.追加文字,設定粗體或斜體等等特殊格式
add_run(),他是屬於 paragraph 之下的方法,所以必須搭配 paragraph 對象使用。
#插入段落, 同時設置粗體和斜體~
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 #斜體
運行得到:

設置字體大小
from docx.shared impore Pt
p = document.add_paragraph()
run = p.add_run('我喜歡你')
font = run.font #調用font屬性
font.size = Pt(26)
設置其它字體格式
font.italic = True #設置斜體
font.underline = True #設置下划線
font.bold = True #設置粗體
設置首行縮進
from docx.shared import Inches
p = document.add_paragraph()
p.paragraph_format_line_indent = Inches(0.32) #假設這里的文本大小是小四,0.16英寸,縮進2個就是0.32
p.add_run('設置首行縮進的文字')
字體大小對照表:

插入空行:
document.add_paragraph() #相當於插入一個回車
document.add_paragraph('\n') #相當於插入一個下箭頭
4.插入圖片
document.add_picture()
#插入寬度設定好的圖片
from docx.shared import Inches
document.add_picture('image-filename.png', width=Inches(1.0))
5.建立表格
document.add_table(rows=?, cols=?) ,表格傳入參數為行數與列數,並且透過 tuple 指定數據。要注意,表格的行列都是從0開始的,如cell(0,0)表示第1行第一列的數,cell(0,1)表示第1行第2列的數。
add_table() # 新建表格
add_row() # 添加行
add_col() # 添加列
table.cell(i, j).text() # 往表格中添加內容
table.rows() # 行數
table.cols() # 列數
6.插入換頁符號
document.add_page_break()
7.儲存 docx 檔案到 demo.docx
document.save('demo.docx')
或
document.save(path) # 指定路徑
象這樣:
document.save(r"d:\demo.docx")
會在D:根目錄下生成demo.docx
先上一段代碼
from docx import Document
from docx.shared import Inches
#透過 Document()建構函數聲明一個 Document 對象
document = Document()
#add_heading() 是建立標題的方法
document.add_heading('Document Title', 0)
#document.add_paragraph()則是建立段落
p = document.add_paragraph('A plain paragraph having some ')
#add_run() 可以設定粗體或斜體等等特殊格式,他是屬於 paragraph 之下的方法,所以必須搭配 paragraph 對象使用。
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() 用來插入圖片
#document.add_picture('monty-truth.png', width=Inches(1.25))
records = (
(3, '101', 'Spam'),
(7, '422', 'Eggs'),
(4, '631', 'Spam, spam, eggs, and spam')
)
#document.add_table(rows=?, cols=?) 用來建立表格,表格傳入參數為行數與列數,並且透過 tuple 指定數據。
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.add_page_break()
#document.save('demo.docx') 儲存 docx 檔案到 demo.docx
document.save('demo.docx')
得到這樣一個WORD文檔 (默認位於C:\Users\YourName 下):

結合pandas的iloc函數,將dataframe寫入word
import pandas as pd
from docx import Document # 輸出docx
from docx.shared import Pt # 設置字號
document = Document()
df = pd.read_csv(a.csv, sep="\t")
rowNum = df.shape[0] + 1 # 行數,加標題欄
colNum = df.shape[1] # 列數
table = document.add_table(rows=rowNum, cols=colNum, style = "Light Grid")
table.cell(0,0).text = "a"
table.cell(0,1).text = "b"
table.cell(0,2).text = "c"
table.cell(0,3).text = "d"
for i in range(1, rowNum):
for j in range(colNum):
cell = table.cell(i,j)
cell.text = str(df.iloc[i-1,j])
table.autofit = True
table.style.font.name = u'等線'
table.style.font.size = Pt(12)
document.save(outPutDocx)
得到:

TIPS
1.生成Dataframe的docx代碼函數:
#以下為公共設置區域---打印df的函數
def add_df2docx(df):
rowNum = df.shape[0] + 1 # 行數,加標題欄
colNum = df.shape[1] # 列數
table = document.add_table(rows=rowNum, cols=colNum, style = "Table Grid")
columns=list(df.columns)
for i in range(0,colNum):
table.cell(0,i).text = columns[i]
for i in range(1, rowNum):
for j in range(colNum):
cell = table.cell(i,j)
cell.text = str(df.iloc[i-1,j])
table.autofit = True
table.style.font.name = u'仿宋'
table.style.font.size = Pt(12)
2.設置一個加title的函數 my_add_head('tilename',1,WD_ALIGN_PARAGRAPH.CENTER,20,'仿宋')
def my_add_head(name,level_num,align,font_size,cfont):
head0=document.add_heading(level=level_num)
#設置標題居中
head0.alignment = align
title_run=head0.add_run(name)
title_run.font.size = Pt(font_size) #14是四號字
# 設置標題英文字體
title_run.font.name = 'Times New Roman'
# 設置標題中文字體
title_run.element.rPr.rFonts.set(qn('w:eastAsia'), cfont)
return
3.為段落正文的全局設置
document = Document()
style = document.styles['Normal']
# 設置西文字體
style.font.name = 'Times New Roman'
style.font.size = Pt(12)
# 設置中文字體
style.element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
# 設置首行縮進, 先獲取段落樣式
paragraph_format = style.paragraph_format
# 首行縮進0.74厘米,即2個字符
paragraph_format.first_line_indent = Cm(0.74)
具體的一些表格設計可以參考:https://zhuanlan.zhihu.com/p/82880510
以及官網:https://python-docx.readthedocs.io/en/latest/user/text.html
還有一些更加詳細的命令可以參考:http://www.ityouknow.com/python/2019/12/31/python-word-105.html
如果想要獲得所有的表樣,可以參考:https://blog.csdn.net/ibiao/article/details/78595295
下列代碼可以將所有表樣導出到文件
from docx.enum.style import WD_STYLE_TYPE
from docx import *
document = Document()
styles = document.styles
#生成所有表樣式
for s in styles:
if s.type == WD_STYLE_TYPE.TABLE:
document.add_paragraph("表格樣式 : "+ s.name)
table = document.add_table(3,3, style = s)
heading_cells = table.rows[0].cells
heading_cells[0].text = '第一列內容'
heading_cells[1].text = '第二列內容'
heading_cells[2].text = '第三列內容'
document.add_paragraph("\n")
document.save('demo2.docx')
得到:

插入超級鏈接的函數
def add_hyperlink(paragraph, url, text, color, underline):
"""
A function that places a hyperlink within a paragraph object.
:param paragraph: The paragraph we are adding the hyperlink to.
:param url: A string containing the required url
:param text: The text displayed for the url
:return: The hyperlink object
"""
# This gets access to the document.xml.rels file and gets a new relation id value
part = paragraph.part
r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
# Create the w:hyperlink tag and add needed values
hyperlink = docx.oxml.shared.OxmlElement('w:hyperlink')
hyperlink.set(docx.oxml.shared.qn('r:id'), r_id, )
# Create a w:r element
new_run = docx.oxml.shared.OxmlElement('w:r')
# Create a new w:rPr element
rPr = docx.oxml.shared.OxmlElement('w:rPr')
# Add color if it is given
if not color is None:
c = docx.oxml.shared.OxmlElement('w:color')
c.set(docx.oxml.shared.qn('w:val'), color)
rPr.append(c)
# Remove underlining if it is requested
if not underline:
u = docx.oxml.shared.OxmlElement('w:u')
u.set(docx.oxml.shared.qn('w:val'), 'none')
rPr.append(u)
# Join all the xml elements together add add the required text to the w:r element
new_run.append(rPr)
new_run.text = text
hyperlink.append(new_run)
paragraph._p.append(hyperlink)
return hyperlink
pp=document.add_paragraph()
#add a hyperlink with the normal formatting (blue underline)
hyperlink = add_hyperlink(pp, 'http://www.google.com', 'Google', None, True)
qq=document.add_paragraph()
#add a hyperlink with a custom color and no underline
hyperlink = add_hyperlink(qq, 'http://www.google.com', 'Google', 'FF8822', False)
讀取 docx 文件
文件如下圖:

上代碼:
import docx
Doc = docx.Document(r"D:\oxygen\Desktop\鐵人挑戰-程式教學\tmp\test.docx")
print("檔案內含段落數:",len(Doc.paragraphs),"\n")
#Doc.paragraphs 會回傳讀取到的段落,以 list 回傳,所以我們先用 len(Doc.paragraphs) 來取得總段落數
#再用for循環讀取Doc中的所有paragraphs,並存在我們新建的testList中,再print
testList = []
for text in Doc.paragraphs:
testList.append(text)
for pg in testList:
print(pg.text)
實現對word內段落文本及表格的讀取
在以下方法中用到的三方庫是:python-docx
from docx import Document
#獲取指定段落的文本
def get_paragraph_text(path, n):
"""
獲取指定段落的文本
:param path: word路徑
:param n: 第幾段落,從0開始計數
:return: word文本
"""
document = Document(path)
all_paragraphs = len(document.paragraphs)
if all_paragraphs > n:
paragraph_text = document.paragraphs[n].text
return paragraph_text
else:
raise IndexError('paragraph index (%s) out of range, in total %s' % (n, all_paragraphs))
#獲取全部段落的文本
def get_paragraphs_text(path):
"""
獲取所有段落的文本
:param path: word路徑
:return: list類型,如:
['Test', 'hello world', ...]
"""
document = Document(path)
all_paragraphs = document.paragraphs
paragraphs_text = []
for paragraph in all_paragraphs:
paragraphs_text.append(paragraph.text)
return paragraphs_text
#獲取所有表格的文本
def get_all_tables_text(path):
"""
獲取word中所有表格的文本
:param path: word路徑
:return: list類型的二維數組
如:[['年齡', '排序'], ['23', '00',], ...]
"""
document = Document(path)
all_tables = document.tables
text_list = []
for table in all_tables:
for row in table.rows:
text = []
for cell in row.cells:
text.append(cell.text)
text_list.append(text)
return text_list
獲取指定表格的文本
def get_table_text(path, n=0):
"""
獲取word中的第n個表格的文本
:param path: word路徑
:param n: 第幾個表格,從0開始計算
:return: list類型的二維數組
如:[['年齡', '排序'], ['23', '00',], ...]
"""
document = Document(path)
all_tables = len(document.tables)
if all_tables > n:
table = document.tables[n]
text_list = []
for row in table.rows:
text = []
for cell in row.cells:
text.append(cell.text)
text_list.append(text)
return text_list
else:
raise IndexError('table index (%s) out of range, in total %s' % (n, all_tables))
獲取指定表格內指定單元格文本
def get_cell_text(path, n=0, row=0, col=0):
"""
獲取某個表格的某個單元格的值
:param path: word路徑
:param n: 第幾個表格,從0開始計算
:param row: 第幾行,從0開始計算
:param col: 第幾列,從0開始計算
:return: 單元格的值,str類型
"""
document = Document(path)
all_tables = len(document.tables)
if all_tables > n:
rows = len(document.tables[n].rows)
cols = len(document.tables[n].columns)
if rows > row and cols > col:
tab = document.tables[n].rows[row].cells[col]
return tab.text
else:
raise IndexError('cell index out of range, %s;%s' % (row, col))
else:
raise IndexError('table index (%s) out of range, in toatl %s' % (n, all_tables))
官網樣式:
https://python-docx.readthedocs.io/en/latest/user/styles-understanding.html#understanding-styles
