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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM