python读写word文档 -- python-docx从入门到精通
两种安装方式:
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
用docx生成多个文档:https://zhuanlan.zhihu.com/p/398846110