直接上代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/5/7 9:37
# @Author : BeiMo
# @File : 操作Word.py
# @Software: PyCharm
from docx import Document
from docx.shared import Inches
import re
from docx.oxml.ns import qn
# 创建一个新的 Word 文档
def create_new_document():
return Document()
# 打开一个现有的 Word 文档
# :param file_path: 要打开的 Word 文档的文件路径
# :return: 如果成功打开文档,返回文档对象;如果出现错误,打印错误信息并返回 None
def open_existing_document(file_path):
try:
return Document(file_path)
except Exception as e:
print(f"打开文档时出错: {e}")
return None
# 向文档中添加一个标题
# :param doc: 要添加标题的文档对象
# :param title_text: 标题的文本内容
# :param level: 标题的级别,默认为 1 级标题
# :return: 添加标题后的文档对象
def add_title(doc, title_text, level=1):
doc.add_heading(title_text, level=level)
return doc
# 从文档中删除指定标题
# :param doc: 要删除标题的文档对象
# :param title_text: 要删除的标题的文本内容
# :return: 删除标题后的文档对象
def delete_title(doc, title_text):
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 检查段落是否为标题,并且标题文本是否匹配
if paragraph.style.name.startswith('Heading') and paragraph.text == title_text:
p = paragraph._element
p.getparent().remove(p)
p._element = None
return doc
# 更新文档中指定标题的文本内容
# :param doc: 要更新标题的文档对象
# :param old_title: 要更新的旧标题文本内容
# :param new_title: 新的标题文本内容
# :return: 更新标题后的文档对象
def update_title(doc, old_title, new_title):
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 检查段落是否为标题,并且标题文本是否匹配旧标题
if paragraph.style.name.startswith('Heading') and paragraph.text == old_title:
paragraph.text = new_title
return doc
# 在文档中查找指定标题
# :param doc: 要查找标题的文档对象
# :param title_text: 要查找的标题的文本内容
# :return: 如果找到标题,返回标题段落对象;如果未找到,返回 None
def find_title(doc, title_text):
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 检查段落是否为标题,并且标题文本是否匹配
if paragraph.style.name.startswith('Heading') and paragraph.text == title_text:
return paragraph
return None
# 向文档中添加一个段落
# :param doc: 要添加段落的文档对象
# :param paragraph_text: 段落的文本内容
# :return: 添加段落后的文档对象
def add_paragraph(doc, paragraph_text):
doc.add_paragraph(paragraph_text)
return doc
# 从文档中删除指定段落
# :param doc: 要删除段落的文档对象
# :param paragraph_text: 要删除的段落的文本内容
# :return: 删除段落后的文档对象
def delete_paragraph(doc, paragraph_text):
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 检查段落文本是否匹配要删除的段落文本
if paragraph.text == paragraph_text:
p = paragraph._element
p.getparent().remove(p)
p._element = None
return doc
# 更新文档中指定段落的文本内容
# :param doc: 要更新段落的文档对象
# :param old_paragraph: 要更新的旧段落文本内容
# :param new_paragraph: 新的段落文本内容
# :return: 更新段落后的文档对象
def update_paragraph(doc, old_paragraph, new_paragraph):
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 检查段落文本是否匹配旧段落文本
if paragraph.text == old_paragraph:
paragraph.text = new_paragraph
return doc
# 在文档中查找指定段落
# :param doc: 要查找段落的文档对象
# :param paragraph_text: 要查找的段落的文本内容
# :return: 如果找到段落,返回段落对象;如果未找到,返回 None
def find_paragraph(doc, paragraph_text):
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 检查段落文本是否匹配要查找的段落文本
if paragraph.text == paragraph_text:
return paragraph
return None
# 替换文档中所有 {{}} 包含的指定内容
# :param doc: 要进行内容替换的文档对象
# :param placeholder_text: 要替换的占位符文本内容
# :param replacement_text: 替换后的文本内容
# :return: 替换内容后的文档对象
def replace_content(doc, placeholder_text, replacement_text):
pattern = re.compile(rf'\{{{{{placeholder_text}}}}}')
# 遍历文档中的每个段落
for paragraph in doc.paragraphs:
# 遍历段落中的每个运行对象
for run in paragraph.runs:
run.text = pattern.sub(replacement_text, run.text)
# 遍历文档中的每个表格
for table in doc.tables:
# 遍历表格中的每一行
for row in table.rows:
# 遍历行中的每个单元格
for cell in row.cells:
# 遍历单元格中的每个段落
for paragraph in cell.paragraphs:
# 遍历段落中的每个运行对象
for run in paragraph.runs:
run.text = pattern.sub(replacement_text, run.text)
return doc
# 获取文档中所有的表格
# :param doc: 要获取表格的文档对象
# :return: 包含文档中所有表格的列表
def get_all_tables(doc):
return doc.tables
# 复制文档中指定索引的表格
# :param doc: 要复制表格的文档对象
# :param table_index: 要复制的表格的索引
# :return: 复制表格后的文档对象
def copy_table(doc, table_index):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
original_table = tables[table_index]
new_table = doc.add_table(rows=len(original_table.rows), cols=len(original_table.columns))
# 遍历原表格的每一行
for i, row in enumerate(original_table.rows):
# 遍历行中的每个单元格
for j, cell in enumerate(row.cells):
new_table.cell(i, j).text = cell.text
return doc
# 更新文档中指定表格的指定单元格的文本内容
# :param doc: 要更新单元格文本的文档对象
# :param table_index: 要更新的表格的索引
# :param row_index: 要更新的单元格所在的行索引
# :param col_index: 要更新的单元格所在的列索引
# :param new_text: 新的单元格文本内容
# :return: 更新单元格文本后的文档对象
def update_table_cell_text(doc, table_index, row_index, col_index, new_text):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
table = tables[table_index]
# 检查行索引和列索引是否在有效范围内
if row_index < len(table.rows) and col_index < len(table.columns):
table.cell(row_index, col_index).text = new_text
return doc
# 向文档中指定表格的指定单元格添加图片
# :param doc: 要添加图片的文档对象
# :param table_index: 要添加图片的表格的索引
# :param row_index: 要添加图片的单元格所在的行索引
# :param col_index: 要添加图片的单元格所在的列索引
# :param image_path: 图片的文件路径
# :return: 添加图片后的文档对象
def add_image_to_table_cell(doc, table_index, row_index, col_index, image_path):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
table = tables[table_index]
# 检查行索引和列索引是否在有效范围内
if row_index < len(table.rows) and col_index < len(table.columns):
cell = table.cell(row_index, col_index)
paragraph = cell.paragraphs[0]
run = paragraph.add_run()
run.add_picture(image_path, width=Inches(2))
return doc
# 删除文档中指定表格的指定单元格的内容
# :param doc: 要删除单元格内容的文档对象
# :param table_index: 要删除单元格内容的表格的索引
# :param row_index: 要删除内容的单元格所在的行索引
# :param col_index: 要删除内容的单元格所在的列索引
# :return: 删除单元格内容后的文档对象
def delete_table_cell_content(doc, table_index, row_index, col_index):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
table = tables[table_index]
# 检查行索引和列索引是否在有效范围内
if row_index < len(table.rows) and col_index < len(table.columns):
cell = table.cell(row_index, col_index)
# 遍历单元格中的每个段落
for paragraph in cell.paragraphs:
p = paragraph._element
p.getparent().remove(p)
p._element = None
return doc
# 合并文档中指定表格的指定单元格范围
# :param doc: 要合并单元格的文档对象
# :param table_index: 要合并单元格的表格的索引
# :param start_row: 合并范围的起始行索引
# :param start_col: 合并范围的起始列索引
# :param end_row: 合并范围的结束行索引
# :param end_col: 合并范围的结束列索引
# :return: 合并单元格后的文档对象
def merge_table_cells(doc, table_index, start_row, start_col, end_row, end_col):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
table = tables[table_index]
# 检查起始行、结束行、起始列和结束列是否在有效范围内
if start_row < len(table.rows) and end_row < len(table.rows) and start_col < len(
table.columns) and end_col < len(table.columns):
table.cell(start_row, start_col).merge(table.cell(end_row, end_col))
return doc
# 拆分文档中指定表格的指定单元格
# :param doc: 要拆分单元格的文档对象
# :param table_index: 要拆分单元格的表格的索引
# :param row_index: 要拆分的单元格所在的行索引
# :param col_index: 要拆分的单元格所在的列索引
# :param num_rows: 拆分后的行数
# :param num_cols: 拆分后的列数
# :return: 拆分单元格后的文档对象
def split_table_cell(doc, table_index, row_index, col_index, num_rows, num_cols):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
table = tables[table_index]
# 检查行索引和列索引是否在有效范围内
if row_index < len(table.rows) and col_index < len(table.columns):
cell = table.cell(row_index, col_index)
tc = cell._element
# 拆分单元格
for i in range(num_rows - 1):
new_tc = tc.makeelement(qn('w:tc'))
tc.addnext(new_tc)
for j in range(num_cols - 1):
for i in range(num_rows):
new_tc = tc.makeelement(qn('w:tc'))
tc.addnext(new_tc)
return doc
# 对文档中指定表格的指定列进行排序
# :param doc: 要排序表格的文档对象
# :param table_index: 要排序的表格的索引
# :param column_index: 要排序的列的索引
# :param ascending: 是否按升序排序,默认为 True
# :return: 排序表格后的文档对象
def sort_table(doc, table_index, column_index, ascending=True):
tables = doc.tables
# 检查表格索引是否在有效范围内
if table_index < len(tables):
table = tables[table_index]
# 检查表格是否有数据
if len(table.rows) == 0:
return doc
# 检查列索引是否在有效范围内
if column_index >= len(table.columns):
print(f"列索引 {column_index} 超出范围,表格只有 {len(table.columns)} 列。")
return doc
# 提取表格数据
data = []
# 遍历表格的每一行
for row in table.rows:
row_data = [cell.text for cell in row.cells]
data.append(row_data)
# 对数据进行排序
header = data[0] # 假设第一行是表头
body = data[1:]
sorted_body = sorted(body, key=lambda x: x[column_index], reverse=not ascending)
# 清空原表格内容
for i in range(len(table.rows)):
for j in range(len(table.columns)):
cell = table.cell(i, j)
p = cell.paragraphs[0]
p.clear()
# 将排序后的数据写回表格
for i, row_data in enumerate([header] + sorted_body):
for j, cell_text in enumerate(row_data):
table.cell(i, j).text = cell_text
return doc
if __name__ == "__main__":
# 新建文档
doc = create_new_document()
# 添加标题
doc = add_title(doc, "测试标题", level=1)
# 添加段落
doc = add_paragraph(doc, "这是一个测试段落。")
# 替换内容
doc = replace_content(doc, "MissionNumber", "QTYM-ZJ/ST-2024-003")
# 添加表格
table = doc.add_table(rows=3, cols=2)
table.cell(0, 0).text = "姓名"
table.cell(0, 1).text = "年龄"
table.cell(1, 0).text = "张三"
table.cell(1, 1).text = "25"
table.cell(2, 0).text = "李四"
table.cell(2, 1).text = "20"
# 复制表格
doc = copy_table(doc, 0)
# 更新表格单元格文本
doc = update_table_cell_text(doc, 0, 0, 0, "新的单元格内容")
# 合并单元格
doc = merge_table_cells(doc, 0, 0, 0, 0, 1)
# 拆分单元格
doc = split_table_cell(doc, 0, 0, 0, 2, 2)
# 对表格进行排序
# doc = sort_table(doc, 0, 1, ascending=True)
# 保存文档
doc.save("test.docx")

740

被折叠的 条评论
为什么被折叠?



