最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從基礎(chǔ)到進(jìn)階詳解Python處理Word文檔的完全指南

 更新時(shí)間:2026年01月13日 08:30:23   作者:諸神緘默不語(yǔ)  
在Python中處理Word文檔是一項(xiàng)常見(jiàn)且實(shí)用的任務(wù),本文將介紹如何使用幾個(gè)主流的Python庫(kù)來(lái)創(chuàng)建、修改和處理Word文檔,涵蓋從基礎(chǔ)操作到高級(jí)功能的完整流程

所需庫(kù)及安裝

在開始之前,需要安裝以下Python庫(kù):

  • python-docx:用于創(chuàng)建和修改Word文檔
  • docxtpl:用于基于模板填充Word文檔
  • docxcompose:用于合并多個(gè)Word文檔
  • lxml:XML處理庫(kù)

可以通過(guò)pip安裝:

pip install python-docx docxtpl docxcompose lxml  

或者使用uv:

uv add python-docx docxtpl docxcompose lxml  

1. 基礎(chǔ)操作

1.1 創(chuàng)建和保存文檔

使用python-docx創(chuàng)建文檔非常簡(jiǎn)單:

from docx import Document  
doc = Document()  
doc.add_paragraph("Python-docx是一個(gè)用于創(chuàng)建")  
doc.save("文件1.docx")  

1.2 設(shè)置中文字體

默認(rèn)字體對(duì)中文支持不佳,需要單獨(dú)設(shè)置中文字體:

from docx.oxml.ns import qn  
def set_chinese_font(run, zh_font_name="宋體", en_font_name="Times New Roman"):  
    run.font.name = en_font_name  
    run._element.rPr.rFonts.set(qn("w:eastAsia"), zh_font_name)  
doc = Document()  
paragraph = doc.add_paragraph()  
run = paragraph.add_run('這是一段設(shè)置了中文字體的文本。')  
set_chinese_font(run)  
doc.save("文件1.docx")  

注意:保存文件時(shí),文件不能被打開,否則會(huì)報(bào)PermissionError錯(cuò)誤。

1.3 導(dǎo)入現(xiàn)有文檔

doc = Document('example.docx')  

注意事項(xiàng)

  • 必須是標(biāo)準(zhǔn)docx文件,不能是doc文件
  • 不能是strict open XML格式

1.4 遍歷文檔內(nèi)容

# 遍歷段落  
for para in doc.paragraphs[:3]:  
    print(para)  
    print(para.text)  
    print()  
# 遍歷表格  
for table in doc.tables:  
    for row in table.rows:  
        for cell in row.cells:  
            print(cell.text)  

2. 文檔格式設(shè)置

2.1 小標(biāo)題

doc.add_heading("1.1 Transformer整體工作流程", 2)  
doc.add_heading("Transformer整體架構(gòu)", 3)  

注意:需要文檔里有對(duì)應(yīng)的標(biāo)題樣式,否則會(huì)報(bào)錯(cuò)。

2.2 段落處理

添加段落

text = """Transformer 模型由編碼器(Encoder)和解碼器(Decoder)組成。..."""  
paragraph1 = doc.add_paragraph(text)  

首行縮進(jìn)

首行縮進(jìn)2字符:

paragraph_format = paragraph1.paragraph_format  
paragraph_format.first_line_indent = 0  
paragraph_format.element.pPr.ind.set(qn("w:firstLineChars"), '200')  

首行縮進(jìn)固定距離:

para_format.first_line_indent = Pt(10)  

段落對(duì)齊

from docx.enum.text import WD_PARAGRAPH_ALIGNMENT  
paragraph1.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT  

刪除段落

p = paragraph1._element  
p.getparent().remove(p)  

換行處理

# 將文本按換行符分割成多個(gè)段落  
for one_paragraph_text in text.split("\n"):  
    temp_paragraph = doc.add_paragraph(one_paragraph_text)  
    paragraph_format = temp_paragraph.paragraph_format  
    paragraph_format.first_line_indent = 0  
    paragraph_format.element.pPr.ind.set(qn("w:firstLineChars"), "200")  

常用段落格式

from docx.shared import Pt  
para_format = temp_paragraph.paragraph_format  
para_format.line_spacing = Pt(18)  # 行間距(固定值)  
para_format.space_before = Pt(3)  # 段前距離  
para_format.space_after = Pt(0)  # 段后距離  
para_format.right_indent = Pt(20)  # 右側(cè)縮進(jìn)  
para_format.left_indent = Pt(0)  # 左側(cè)縮進(jìn)  

2.3 字符格式設(shè)置

from docx.shared import RGBColor, Pt  
# 加粗文本  
temp_paragraph.add_run('加粗文本').bold = True  
# 紅色斜體文本  
run = temp_paragraph.add_run('紅色斜體文本')  
run.font.color.rgb = RGBColor(255,0,0)  # 設(shè)置紅色  
run.font.size = Pt(14)  # 字號(hào)14磅  
run.bold = True  # 加粗  
run.italic = True  # 斜體  
run.underline = True  # 下劃線  
# 下標(biāo)和上標(biāo)  
run2 = temp_paragraph.add_run("1")  
run2.font.subscript = True  # 下標(biāo)  
run3 = temp_paragraph.add_run("2")  
run3.font.superscript = True  # 上標(biāo)  

2.4 表格處理

創(chuàng)建表格

table = doc.add_table(rows=4, cols=5)  
table.style = "Grid Table 1 Light"  # 應(yīng)用預(yù)定義樣式  

填充單元格

# 方式1:直接指定單元格  
cell = table.cell(0, 1)  
cell.text = "parrot, possibly dead"  
# 方式2:通過(guò)行獲取單元格  
row = table.rows[1]  
cells = row.cells  
cells[0].text = "Foo bar to you."  
cells[1].text = "And a hearty foo bar to you too sir!"  

獲取可用表格樣式

from docx.enum.style import WD_STYLE_TYPE  
styles = doc.styles  
for s in styles:  
    if s.type == WD_STYLE_TYPE.TABLE:  
        print(s.name)  

增加和刪除行

# 增加一行  
row = table.add_row()  
# 刪除一行  
def remove_row(table, row):  
    tbl = table._tbl  
    tr = row._tr  
    tbl.remove(tr)  
row = table.rows[len(table.rows) - 1]  
remove_row(table, row)  

批量填充數(shù)據(jù)

# 方式1:一行一行添加  
items = (  
    (7, "1024", "Plush kittens"),  
    (3, "2042", "Furbees"),  
    (1, "1288", "French Poodle Collars, Deluxe"),  
)  
for item in items:  
    cells = table.add_row().cells  
    cells[0].text = str(item[0])  
    cells[1].text = item[1]  
    cells[2].text = item[2]  
# 方式2:批量填充  
for row in table.rows:  
    for cell in row.cells:  
        cell.text = "數(shù)據(jù)單元"  

合并單元格

table.cell(0, 0).merge(table.cell(1, 1))  # 跨行列合并  

表格格式設(shè)置

# 表格寬度自適應(yīng)  
table.autofit = True  
# 指定行高  
from docx.shared import Cm  
table.rows[0].height = Cm(0.93)  
# 修改表格字體大小  
table.style.font.size = Pt(15)  
# 設(shè)置單元格對(duì)齊  
from docx.enum.table import WD_ALIGN_VERTICAL  
cell = table.cell(0, 0)  
cell.paragraphs[0].paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER  
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER  
# 復(fù)制表格  
from copy import deepcopy  
table_copy = deepcopy(doc.tables[0])  
para1 = doc.add_paragraph()  
para1._p.addnext(table_copy._element)  

2.5 圖片處理

插入圖片

from io import BytesIO  
import base64  
# 普通插入  
doc.add_picture('圖片1.png')  
doc.add_picture('圖片2.png', width=Inches(2.5), height=Inches(2))  
# 使用base64插入  
picture2_base64 = open("圖片2base64.txt").read()  
img2_buf = base64.b64decode(picture2_base64)  
doc.add_picture(BytesIO(img2_buf))  
# 并排放圖  
run = doc.add_paragraph().add_run()  
run.add_picture("圖片1.png", width=Inches(2.5), height=Inches(2))  
run.add_picture("圖片1.png", width=Inches(2.5), height=Inches(2))  

2.6 分頁(yè)符

doc.add_page_break()  

2.7 樣式管理

# 修改已有樣式  
doc.styles["Normal"].font.size = Pt(14)  
doc.styles['Normal'].font.name = 'Arial'  
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '楷體')  
# 創(chuàng)建自定義段落樣式  
from docx.enum.style import WD_STYLE_TYPE  
UserStyle1 = doc.styles.add_style('UserStyle1', WD_STYLE_TYPE.PARAGRAPH)  
UserStyle1.font.size = Pt(40)  
UserStyle1.font.color.rgb = RGBColor(0xff, 0xde, 0x00)  
UserStyle1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER  
UserStyle1.font.name = '微軟雅黑'  
UserStyle1._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')  
# 使用自定義樣式  
doc.add_paragraph('自定義段落樣式', style=UserStyle1)  

3. 使用docxtpl進(jìn)行模板填充

docxtpl可以將Word文檔制作成模板,實(shí)現(xiàn)數(shù)據(jù)自動(dòng)填充。

3.1 創(chuàng)建模板

首先創(chuàng)建一個(gè)包含占位符的Word模板,占位符使用雙花括號(hào){{}}包裹。

3.2 填充模板

from docxtpl import DocxTemplate, InlineImage, RichText  
tpl = DocxTemplate("docxexample.docx")  
text = """Transformer 模型由編碼器(Encoder)和解碼器(Decoder)組成..."""  
picture1 = InlineImage(tpl, image_descriptor="圖片1.png")  
# 準(zhǔn)備數(shù)據(jù)  
paragraphs1 = [  
    "步驟1:輸入表示(Input Representation)",  
    "步驟2:編碼器處理(Encoder Processing)",  
    "步驟3:解碼器處理(Decoder Processing)",  
]  
paragraphs2 = [  
    {"step": 1, "text": "輸入向量(詞嵌入+位置編碼)進(jìn)入編碼器層。"},  
    {"step": 2, "text": "自注意力子層。"},  
    {"step": 3, "text": "前饋網(wǎng)絡(luò)子層。"},  
]  
table = [  
    {"character": "并行計(jì)算", "description": "編碼器可并行處理整個(gè)序列(與RNN不同)"},  
    {"character": "自注意力", "description": "每個(gè)詞直接關(guān)聯(lián)所有詞,捕獲長(zhǎng)距離依賴"},  
    {"character": "位置編碼", "description": "為無(wú)順序的注意力機(jī)制注入位置信息"},  
]  
alerts = [  
    {  
        "date": "2015-03-10",  
        "desc": RichText("Very critical alert", color="FF0000", bold=True),  
        "type": "CRITICAL",  
        "bg": "FF0000",  
    },  
    # ... 其他數(shù)據(jù)  
]  
# 渲染模板  
context = {  
    "title": "Transformer",  
    "text_body": text,  
    "picture1": picture1,  
    "picture2": picture2,  
    "paragraphs1": paragraphs1,  
    "paragraphs2": paragraphs2,  
    "runs": paragraphs1,  
    "display_paragraph": True,  
    "table1": table,  
    "table2": table,  
    "alerts": alerts,  
}  
tpl.render(context)  
tpl.save("文件3.docx")  

4. 進(jìn)階功能

4.1 表格高級(jí)操作

設(shè)置單元格邊框

from docx.oxml import OxmlElement  
from docx.oxml.ns import qn  
def set_cell_border(cell, **kwargs):  
    tc = cell._tc  
    tcPr = tc.get_or_add_tcPr()  
    tcBorders = tcPr.first_child_found_in("w:tcBorders")  
    if tcBorders is None:  
        tcBorders = OxmlElement("w:tcBorders")  
        tcPr.append(tcBorders)  
      
    for edge in ("left", "top", "right", "bottom", "insideH", "insideV"):  
        edge_data = kwargs.get(edge)  
        if edge_data:  
            tag = "w:{}".format(edge)  
            element = tcBorders.find(qn(tag))  
            if element is None:  
                element = OxmlElement(tag)  
                tcBorders.append(element)  
              
            for key in ["sz", "val", "color", "space", "shadow"]:  
                if key in edge_data:  
                    element.set(qn("w:{}".format(key)), str(edge_data[key]))  
# 使用示例  
set_cell_border(  
    table.cell(0, 0),  
    top={"sz": 4, "val": "single", "color": "#000000", "space": "0"},  
    bottom={"sz": 4, "val": "single", "color": "#000000", "space": "0"},  
    left={"sz": 4, "val": "single", "color": "#000000", "space": "0"},  
    right={"sz": 4, "val": "single", "color": "#000000", "space": "0"},  
)  

4.2 超鏈接

def add_hyperlink(paragraph, url, text):  
    part = paragraph.part  
    r_id = part.relate_to(  
        url,  
        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",  
        is_external=True,  
    )  
    hyperlink = OxmlElement("w:hyperlink")  
    hyperlink.set(qn("r:id"), r_id)  
      
    run = OxmlElement("w:r")  
    run_text = OxmlElement("w:t")  
    run_text.text = text  
    run.append(run_text)  
    hyperlink.append(run)  
      
    paragraph._p.append(hyperlink)  
p = doc.add_paragraph("點(diǎn)擊訪問(wèn): ")  
add_hyperlink(p, "https://www.baidu.com", "示例鏈接")  

4.3 圖片高級(jí)操作

提取文檔中的圖片

import zipfile  
from xml.etree.ElementTree import fromstring  
def extract_images(docx_path, output_dir):  
    with zipfile.ZipFile(docx_path) as z:  
        try:  
            doc_rels = z.read('word/_rels/document.xml.rels').decode('utf-8')  
        except KeyError:  
            return []  
          
        root = fromstring(doc_rels)  
        rels = []  
        for child in root:  
            if 'Type' in child.attrib and child.attrib['Type'] == RT.IMAGE:  
                rels.append((child.attrib['Id'], child.attrib['Target']))  
          
        images = []  
        for rel_id, target in rels:  
            try:  
                image_data = z.read('word/' + target)  
                image_name = target.split('/')[-1]  
                with open(f"{output_dir}/{image_name}", 'wb') as f:  
                    f.write(image_data)  
                images.append(image_name)  
            except KeyError:  
                continue  
        return images  
print(extract_images("Transformer原理純享版.docx", "pictures"))  

插入浮動(dòng)圖片

# 插入“襯于文字下方”的浮動(dòng)圖片  
# 如將 behindDoc="1" 改成0就是“浮于文字上方”了  
# refer to docx.oxml.shape.CT_Inline  
class CT_Anchor(BaseOxmlElement):  
    """  
    ``<w:anchor>`` element, container for a floating image.  
    """  
    extent = OneAndOnlyOne('wp:extent')  
    docPr = OneAndOnlyOne('wp:docPr')  
    graphic = OneAndOnlyOne('a:graphic')  
    @classmethod  
    def new(cls, cx, cy, shape_id, pic, pos_x, pos_y):  
        """  
        Return a new ``<wp:anchor>`` element populated with the values passed  
        as parameters.  
        """  
        anchor = parse_xml(cls._anchor_xml(pos_x, pos_y))  
        anchor.extent.cx = cx  
        anchor.extent.cy = cy  
        anchor.docPr.id = shape_id  
        anchor.docPr.name = 'Picture %d' % shape_id  
        anchor.graphic.graphicData.uri = (  
            'http://schemas.openxmlformats.org/drawingml/2006/picture'  
        )  
        anchor.graphic.graphicData._insert_pic(pic)  
        return anchor  
    @classmethod  
    def new_pic_anchor(cls, shape_id, rId, filename, cx, cy, pos_x, pos_y):  
        """  
        Return a new `wp:anchor` element containing the `pic:pic` element  
        specified by the argument values.  
        """  
        pic_id = 0  # Word doesn't seem to use this, but does not omit it  
        pic = CT_Picture.new(pic_id, filename, rId, cx, cy)  
        anchor = cls.new(cx, cy, shape_id, pic, pos_x, pos_y)  
        anchor.graphic.graphicData._insert_pic(pic)  
        return anchor  
    @classmethod  
    def _anchor_xml(cls, pos_x, pos_y):  
        return (  
            '<wp:anchor distT="0" distB="0" distL="0" distR="0" simplePos="0" relativeHeight="0" \n'  
            '           behindDoc="1" locked="0" layoutInCell="1" allowOverlap="1" \n'  
            '           %s>\n'  
            '  <wp:simplePos x="0" y="0"/>\n'  
            '  <wp:positionH relativeFrom="page">\n'  
            '    <wp:posOffset>%d</wp:posOffset>\n'  
            '  </wp:positionH>\n'  
            '  <wp:positionV relativeFrom="page">\n'  
            '    <wp:posOffset>%d</wp:posOffset>\n'  
            '  </wp:positionV>\n'                      
            '  <wp:extent cx="914400" cy="914400"/>\n'  
            '  <wp:wrapNone/>\n'  
            '  <wp:docPr id="666" name="unnamed"/>\n'  
            '  <wp:cNvGraphicFramePr>\n'  
            '    <a:graphicFrameLocks noChangeAspect="1"/>\n'  
            '  </wp:cNvGraphicFramePr>\n'  
            '  <a:graphic>\n'  
            '    <a:graphicData uri="URI not set"/>\n'  
            '  </a:graphic>\n'  
            '</wp:anchor>' % ( nsdecls('wp', 'a', 'pic', 'r'), int(pos_x), int(pos_y) )  
        )  
# refer to docx.parts.story.BaseStoryPart.new_pic_inline  
def new_pic_anchor(part, image_descriptor, width, height, pos_x, pos_y):  
    """Return a newly-created `w:anchor` element.  
    The element contains the image specified by *image_descriptor* and is scaled  
    based on the values of *width* and *height*.  
    """  
    rId, image = part.get_or_add_image(image_descriptor)  
    cx, cy = image.scaled_dimensions(width, height)  
    shape_id, filename = part.next_id, image.filename      
    return CT_Anchor.new_pic_anchor(shape_id, rId, filename, cx, cy, pos_x, pos_y)  
# refer to docx.text.run.add_picture  
def add_float_picture(p, image_path_or_stream, width=None, height=None, pos_x=0, pos_y=0):  
    """Add float picture at fixed position `pos_x` and `pos_y` to the top-left point of page.  
    """  
    run = p.add_run()  
    anchor = new_pic_anchor(run.part, image_path_or_stream, width, height, pos_x, pos_y)  
    run._r.add_drawing(anchor)  
# refer to docx.oxml.__init__.py  
register_element_cls('wp:anchor', CT_Anchor)  
document = Document()  
# add a floating picture  
p = document.add_paragraph()  
add_float_picture(p, '圖片1.png')  
# add text  
p.add_run('Hello World '*50)  
document.save('文件2.docx')  
# https://www.cnblogs.com/dancesir/p/17788854.html  

4.4 分欄

# 分2欄  
section = doc.sections[0]  
sectPr = section._sectPr  
cols = sectPr.xpath('./w:cols')[0]  
cols.set(qn('w:num'),'2')  

4.5 頁(yè)眉頁(yè)腳

# 普通頁(yè)眉  
doc = Document('Transformer原理純享版.docx')  
doc.sections[0].header.paragraphs[0].text = "這是第1節(jié)頁(yè)眉"  
# 分奇偶設(shè)置頁(yè)眉  
doc.settings.odd_and_even_pages_header_footer = True  
doc.sections[0].even_page_header.paragraphs[0].text = "這是偶數(shù)頁(yè)頁(yè)眉"  
doc.sections[0].header.paragraphs[0].text = "這是奇數(shù)頁(yè)頁(yè)眉"  
# 設(shè)置首頁(yè)頁(yè)眉  
doc.sections[0].different_first_page_header_footer = True  
doc.sections[0].first_page_header.paragraphs[0].text = "這是首頁(yè)頁(yè)眉"  

4.6 目錄

# 插入目錄(不會(huì)更新域)  
paragraph = doc.paragraphs[0].insert_paragraph_before()  
run = paragraph.add_run()  
fldChar = OxmlElement('w:fldChar')  
fldChar.set(qn('w:fldCharType'), 'begin')  
instrText = OxmlElement('w:instrText')  
instrText.set(qn('xml:space'), 'preserve')  
instrText.text = r'TOC \o "1-3" \h \z \u'  
fldChar2 = OxmlElement('w:fldChar')  
fldChar2.set(qn('w:fldCharType'), 'separate')  
fldChar3 = OxmlElement('w:t')  
fldChar3.text = "Right-click to update field."  
fldChar2.append(fldChar3)  
fldChar4 = OxmlElement('w:fldChar')  
fldChar4.set(qn('w:fldCharType'), 'end')  
r_element = run._r  
r_element.append(fldChar)  
r_element.append(instrText)  
r_element.append(fldChar2)  
r_element.append(fldChar4)  
# 自動(dòng)更新目錄  
import lxml  
name_space = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"  
update_name_space = "%supdateFields" % name_space  
val_name_space = "%sval" % name_space  
try:  
    element_update_field_obj = lxml.etree.SubElement(doc.settings.element, update_name_space)  
    element_update_field_obj.set(val_name_space, "true")  
except Exception as e:  
    del e  

4.7 文檔合并

from docxcompose.composer import Composer  
master = Document("文件1.docx")  
composer = Composer(master)  
doc1 = Document("文件2.docx")  
composer.append(doc1)  
doc2 = Document("文件3.docx")  
composer.append(doc2)  
composer.save("combined.docx")  

注意:合并文檔時(shí),后面的文檔會(huì)跟隨第一個(gè)文檔的格式。

總結(jié)

本文介紹了Python處理Word文檔的完整流程,包括:

  • 使用python-docx進(jìn)行基礎(chǔ)的文檔創(chuàng)建、編輯和格式化
  • 使用docxtpl實(shí)現(xiàn)基于模板的自動(dòng)化數(shù)據(jù)填充
  • 使用docxcompose合并多個(gè)Word文檔
  • 各種進(jìn)階功能如設(shè)置單元格邊框、插入超鏈接、提取圖片、設(shè)置頁(yè)眉頁(yè)腳等

這些技術(shù)可以廣泛應(yīng)用于自動(dòng)化報(bào)告生成、批量文檔處理、合同模板填充等場(chǎng)景,大大提高工作效率。

以上就是從基礎(chǔ)到進(jìn)階詳解Python處理Word文檔的完全指南的詳細(xì)內(nèi)容,更多關(guān)于Python處理Word文檔的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

扎兰屯市| 五家渠市| 天津市| 鄂州市| 峨山| 神农架林区| 利辛县| 格尔木市| 射洪县| 简阳市| 新野县| 延长县| 永德县| 遵义县| 广德县| 唐山市| 岐山县| 鄂州市| 普陀区| 宁河县| 陆良县| 修水县| 陵川县| 米易县| 抚顺市| 安宁市| 新余市| 贵定县| 仁怀市| 阿尔山市| 临桂县| 金华市| 巫溪县| 忻州市| 宜章县| 河曲县| 澄江县| 开封县| 米易县| 新宾| 谷城县|