Python 生态中有多个用于操作 Word 文档的库,每个库都有其特点和适用场景。
1. docx2python
特点:
-
专注于从 Word 文档中提取内容
-
保留文档结构信息
-
支持表格、文本、图片等元素的提取
安装:
pip install docx2python
2. pywin32 (仅Windows)
特点:
-
通过 COM 接口直接操作 Microsoft Word
-
功能最全面,可以调用 Word 的所有功能
-
仅适用于 Windows 系统
-
需要安装 Microsoft Word
安装:
pip install pywin32
3. docx-mailmerge
特点:
-
专注于邮件合并功能
-
简化了模板填充操作
-
基于 python-docx 构建
安装:
pip install docx-mailmerge
4. python-docx-template
特点:
-
支持类似Jinja2的模板语法
-
可以处理条件语句、循环等复杂逻辑
-
支持图片、表格等复杂元素的替换
安装:
pip install docxtpl
5. mammoth (转换工具)
特点:
-
专注于 Word 到 HTML 的转换
-
保留基本格式和结构
-
支持自定义样式映射
安装:
pip install mammoth
6. aspose-words
特点:
-
商业库,功能强大
-
支持多种文档格式互转
-
跨平台支持
安装:
pip install aspose-words
库对比总结
| 库名称 | 主要功能 | 平台要求 | 许可证 | 适合场景 |
|---|---|---|---|---|
| python-docx | 创建/修改docx | 跨平台 | MIT | 基本Word操作 |
| docx2python | 内容提取 | 跨平台 | MIT | 数据提取 |
| pywin32 | 全功能Word操作 | Windows | MIT | 高级自动化 |
| docx-mailmerge | 邮件合并 | 跨平台 | MIT | 模板填充 |
| docxtpl | 模板渲染 | 跨平台 | MIT | 复杂模板 |
| mammoth | Word转HTML | 跨平台 | BSD | 内容发布 |
| aspose-words | 全功能文档处理 | 跨平台 | 商业 | 企业级应用 |
选择建议
-
基本文档生成:
python-docx是最佳选择 -
内容提取:使用
docx2python -
Windows环境高级操作:
pywin32提供最全面的功能 -
模板填充:
docx-mailmerge或python-docx-template -
文档转换:
mammoth或aspose-words -
企业级应用:考虑商业库
aspose-words
高级技巧:结合使用多个库
from docx import Document
from docx2python import docx2python
from docxtpl import DocxTemplate
# 1. 使用docx2python提取模板结构
doc_content = docx2python('template.docx')
print("模板包含以下段落:", doc_content.text)
# 2. 使用python-docx创建新文档
doc = Document()
doc.add_heading('合并后的文档', level=1)
# 3. 使用docxtpl渲染复杂部分
tpl = DocxTemplate('complex_part.docx')
context = {'data': [...]}
tpl.render(context)
tpl.save('temp.docx')
# 4. 将渲染结果合并到主文档
temp_doc = Document('temp.docx')
for para in temp_doc.paragraphs:
doc.add_paragraph(para.text)
# 保存最终文档
doc.save('final_output.docx')
Python-docx 库
python-docx 是一个用于创建和修改 Microsoft Word (.docx) 文件的 Python 库。下面是该库的全面介绍和使用指南。
1. 安装与基本使用
安装
pip install python-docx
创建新文档
from docx import Document
# 创建新文档
doc = Document()
doc.add_paragraph('Hello, Word!')
doc.save('hello.docx')
2. 文档结构操作
2.1 段落操作
# 添加段落
paragraph = doc.add_paragraph('这是一个段落')
# 添加带样式的段落
paragraph = doc.add_paragraph('这是一个标题', style='Heading 1')
# 分段添加文本
paragraph.add_run('加粗文本').bold = True
paragraph.add_run('普通文本')
paragraph.add_run('斜体文本').italic = True
# 获取所有段落
for para in doc.paragraphs:
print(para.text)
2.2 标题设置
# 添加各级标题
doc.add_heading('一级标题', level=1)
doc.add_heading('二级标题', level=2)
doc.add_heading('三级标题', level=3)
3. 文本格式设置
3.1 字体格式
from docx.shared import Pt, RGBColor
from docx.oxml.ns import qn
# 设置中文字体
paragraph = doc.add_paragraph()
run = paragraph.add_run('中文字体测试')
run.font.name = '微软雅黑'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
# 设置字体大小
run.font.size = Pt(14)
# 设置字体颜色
run.font.color.rgb = RGBColor(255, 0, 0) # 红色
# 其他格式
run.bold = True # 加粗
run.italic = True # 斜体
run.underline = True # 下划线
3.2 段落格式
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import Inches
paragraph = doc.add_paragraph('对齐和缩进示例')
# 对齐方式
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 居中
# 其他选项: LEFT, RIGHT, JUSTIFY, DISTRIBUTE
# 缩进
paragraph.paragraph_format.left_indent = Inches(0.5) # 左缩进0.5英寸
paragraph.paragraph_format.right_indent = Inches(0.5) # 右缩进
paragraph.paragraph_format.first_line_indent = Inches(0.5) # 首行缩进
# 行距
paragraph.paragraph_format.line_spacing = 1.5 # 1.5倍行距
paragraph.paragraph_format.space_after = Pt(12) # 段后间距12磅
paragraph.paragraph_format.space_before = Pt(12) # 段前间距
4. 表格操作
4.1 创建表格
# 添加3行4列的表格
table = doc.add_table(rows=3, cols=4)
# 填充表格数据
for i in range(3):
for j in range(4):
table.cell(i, j).text = f'行{i+1}列{j+1}'
# 另一种添加表格的方式(推荐)
data = [
['姓名', '年龄', '性别'],
['张三', '25', '男'],
['李四', '30', '女']
]
table = doc.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
for i in range(3):
hdr_cells[i].text = data[0][i]
for row_data in data[1:]:
row_cells = table.add_row().cells
for i in range(3):
row_cells[i].text = row_data[i]
4.2 表格样式
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
from docx.enum.table import WD_ROW_HEIGHT_RULE
# 表格对齐
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# 设置行高
table.rows[0].height_rule = WD_ROW_HEIGHT_RULE.EXACTLY
table.rows[0].height = Pt(30)
# 单元格垂直对齐
for row in table.rows:
for cell in row.cells:
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
# 应用表格样式
table.style = 'Light Shading Accent 1'
# 其他内置样式: 'Table Grid', 'Light List', 'Medium Shading 1' 等
5. 图片与形状
5.1 插入图片
from docx.shared import Cm
doc.add_picture('image.png', width=Cm(10)) # 宽度10厘米
# 也可以使用 Inches(4) 表示4英寸
# 设置图片居中对齐
last_paragraph = doc.paragraphs[-1]
last_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
5.2 插入形状
from docx.enum.shape import MSO_SHAPE
# 添加一个矩形
shape = doc.add_shape(MSO_SHAPE.RECTANGLE, left=Cm(5), top=Cm(5),
width=Cm(5), height=Cm(3))
shape.text = '这是一个矩形'
# 添加线条
doc.add_shape(MSO_SHAPE.LINE_INVERSE,
left=Cm(2), top=Cm(2),
width=Cm(10), height=Cm(0))
6. 页眉页脚与分节
6.1 页眉页脚
# 添加页眉
header = doc.sections[0].header
header_para = header.paragraphs[0]
header_para.text = "这是页眉 - 左对齐"
header_para.add_run("右对齐部分").alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
# 添加页脚
footer = doc.sections[0].footer
footer_para = footer.paragraphs[0]
footer_para.text = "页码: "
footer_para.add_run("1").bold = True
6.2 分节与页面设置
from docx.enum.section import WD_SECTION # 添加新节 doc.add_section(WD_SECTION.NEW_PAGE) # 新页分节 # 其他选项: NEW_PAGE, CONTINUOUS, EVEN_PAGE, ODD_PAGE # 页面设置 section = doc.sections[0] section.page_height = Cm(29.7) # A4高度 section.page_width = Cm(21) # A4宽度 section.left_margin = Cm(2.54) # 左边距 section.right_margin = Cm(2.54) # 右边距 section.top_margin = Cm(2.54) # 上边距 section.bottom_margin = Cm(2.54) # 下边距 section.header_distance = Cm(1.25) # 页眉距离 section.footer_distance = Cm(1.25) # 页脚距离
7. 高级功能
7.1 样式管理
from docx.enum.style import WD_STYLE_TYPE
# 创建新样式
styles = doc.styles
new_style = styles.add_style('MyStyle', WD_STYLE_TYPE.PARAGRAPH)
new_style.font.name = '微软雅黑'
new_style.font.size = Pt(12)
new_style.font.color.rgb = RGBColor(0x42, 0x24, 0xE9)
new_style.paragraph_format.line_spacing = 1.5
# 应用样式
doc.add_paragraph('自定义样式文本', style='MyStyle')
7.2 目录生成
# 添加目录(需要Word在打开文档后更新字段)
doc.add_paragraph().add_run().add_field('TOC \\o "1-3" \\h \\z \\u')
# 添加分页符
doc.add_page_break()
7.3 超链接
from docx.oxml.shared import OxmlElement
from docx.oxml.ns import qn
def add_hyperlink(paragraph, text, url):
"""添加超链接"""
part = paragraph.part
r_id = part.relate_to(
url,
docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK,
is_external=True
)
hyperlink = OxmlElement('w:hyperlink')
hyperlink.set(qn('r:id'), r_id)
new_run = OxmlElement('w:r')
rPr = OxmlElement('w:rPr')
new_run.append(rPr)
new_run.text = text
hyperlink.append(new_run)
paragraph._p.append(hyperlink)
return hyperlink
# 使用示例
para = doc.add_paragraph()
add_hyperlink(para, "百度", "https://www.baidu.com")
8. 读取现有文档
doc = Document('existing.docx')
# 读取段落
for para in doc.paragraphs:
print(para.text)
# 读取表格
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
print(cell.text)
# 读取页眉页脚
for section in doc.sections:
print("页眉:", section.header.paragraphs[0].text)
print("页脚:", section.footer.paragraphs[0].text)
9. 实际应用示例
9.1 生成报告
def generate_report(data):
doc = Document()
# 标题
doc.add_heading('销售报告', level=1)
# 基本信息
doc.add_paragraph(f'生成日期: {datetime.now().strftime("%Y-%m-%d")}')
doc.add_paragraph(f'报告周期: {data["start_date"]} 至 {data["end_date"]}')
# 摘要
doc.add_heading('执行摘要', level=2)
doc.add_paragraph(data['summary'])
# 销售数据表格
doc.add_heading('销售数据', level=2)
table = doc.add_table(rows=1, cols=4)
table.style = 'Light Shading Accent 1'
# 表头
hdr_cells = table.rows[0].cells
hdr_cells[0].text = '产品'
hdr_cells[1].text = '数量'
hdr_cells[2].text = '单价'
hdr_cells[3].text = '总额'
# 表格数据
for item in data['sales']:
row_cells = table.add_row().cells
row_cells[0].text = item['product']
row_cells[1].text = str(item['quantity'])
row_cells[2].text = f"¥{item['price']:.2f}"
row_cells[3].text = f"¥{item['quantity'] * item['price']:.2f}"
# 图表
doc.add_heading('销售趋势图', level=2)
doc.add_paragraph('下图显示了销售趋势:')
doc.add_picture('sales_chart.png', width=Cm(12))
# 结论
doc.add_heading('结论与建议', level=2)
doc.add_paragraph(data['conclusion'])
# 保存
doc.save('sales_report.docx')
9.2 批量生成合同
def generate_contracts(template_path, clients):
for client in clients:
doc = Document(template_path)
# 替换占位符
replacements = {
'{{client_name}}': client['name'],
'{{date}}': datetime.now().strftime('%Y年%m月%d日'),
'{{amount}}': f"¥{client['amount']:,.2f}",
'{{service}}': client['service']
}
for para in doc.paragraphs:
for key, value in replacements.items():
if key in para.text:
para.text = para.text.replace(key, value)
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for key, value in replacements.items():
if key in cell.text:
cell.text = cell.text.replace(key, value)
# 保存
doc.save(f"contract_{client['id']}.docx")
注意事项
-
兼容性:python-docx 只支持 .docx 格式(Word 2007及以后版本),不支持旧的 .doc 格式
-
样式限制:某些复杂的Word功能可能无法完全支持
-
文档打开:生成的文档需要在Word中打开后才能正确显示某些元素(如目录、页码等)
-
性能问题:处理大型文档时可能会有性能问题,建议分批处理
-
字体问题:中文字体需要特殊处理,确保同时设置西文和中文字体
通过 python-docx,您可以实现绝大多数常见的Word文档操作需求,从简单的文档生成到复杂的报告自动化都能胜任。
Word文档编辑器实现
下面介绍如何使用Python创建Word文档编辑器,主要使用python-docx库来处理Word文档,并结合PyQt5构建图形用户界面。
1. 环境准备
首先安装必要的库:
pip install python-docx PyQt5
2. 基本Word编辑器实现
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTextEdit,
QFileDialog, QVBoxLayout, QWidget,
QPushButton, QMessageBox, QFontComboBox,
QSpinBox, QHBoxLayout, QAction, QToolBar)
from PyQt5.QtGui import QTextCursor, QIcon
from PyQt5.QtCore import Qt
from docx import Document
from docx.shared import Pt
import os
class WordEditor(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Word编辑器")
self.setGeometry(100, 100, 800, 600)
self.current_file = None
self.initUI()
def initUI(self):
# 主窗口部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
# 主布局
self.main_layout = QVBoxLayout()
# 创建工具栏
self.create_toolbar()
# 格式工具栏
self.format_toolbar = QToolBar("格式工具栏")
self.addToolBar(Qt.TopToolBarArea, self.format_toolbar)
# 字体选择
self.font_combo = QFontComboBox()
self.font_combo.currentFontChanged.connect(self.change_font)
self.format_toolbar.addWidget(self.font_combo)
# 字号选择
self.font_size = QSpinBox()
self.font_size.setRange(8, 72)
self.font_size.setValue(12)
self.font_size.valueChanged.connect(self.change_font_size)
self.format_toolbar.addWidget(self.font_size)
# 加粗按钮
self.bold_action = QAction(QIcon.fromTheme('format-text-bold'), "加粗", self)
self.bold_action.setCheckable(True)
self.bold_action.triggered.connect(self.toggle_bold)
self.format_toolbar.addAction(self.bold_action)
# 斜体按钮
self.italic_action = QAction(QIcon.fromTheme('format-text-italic'), "斜体", self)
self.italic_action.setCheckable(True)
self.italic_action.triggered.connect(self.toggle_italic)
self.format_toolbar.addAction(self.italic_action)
# 下划线按钮
self.underline_action = QAction(QIcon.fromTheme('format-text-underline'), "下划线", self)
self.underline_action.setCheckable(True)
self.underline_action.triggered.connect(self.toggle_underline)
self.format_toolbar.addAction(self.underline_action)
# 文本编辑区
self.text_edit = QTextEdit()
self.text_edit.cursorPositionChanged.connect(self.update_format_buttons)
# 添加到布局
self.main_layout.addWidget(self.text_edit)
self.central_widget.setLayout(self.main_layout)
# 状态栏
self.statusBar().showMessage("就绪")
# 创建菜单
self.create_menus()
def create_toolbar(self):
toolbar = QToolBar("主工具栏")
self.addToolBar(Qt.TopToolBarArea, toolbar)
# 新建
new_action = QAction(QIcon.fromTheme('document-new'), "新建", self)
new_action.setShortcut("Ctrl+N")
new_action.triggered.connect(self.new_file)
toolbar.addAction(new_action)
# 打开
open_action = QAction(QIcon.fromTheme('document-open'), "打开", self)
open_action.setShortcut("Ctrl+O")
open_action.triggered.connect(self.open_file)
toolbar.addAction(open_action)
# 保存
self.save_action = QAction(QIcon.fromTheme('document-save'), "保存", self)
self.save_action.setShortcut("Ctrl+S")
self.save_action.triggered.connect(self.save_file)
self.save_action.setEnabled(False)
toolbar.addAction(self.save_action)
# 另存为
save_as_action = QAction(QIcon.fromTheme('document-save-as'), "另存为", self)
save_as_action.triggered.connect(self.save_file_as)
toolbar.addAction(save_as_action)
toolbar.addSeparator()
# 打印
print_action = QAction(QIcon.fromTheme('document-print'), "打印", self)
print_action.setShortcut("Ctrl+P")
print_action.triggered.connect(self.print_document)
toolbar.addAction(print_action)
def create_menus(self):
menubar = self.menuBar()
# 文件菜单
file_menu = menubar.addMenu("文件")
new_action = QAction("新建", self)
new_action.setShortcut("Ctrl+N")
new_action.triggered.connect(self.new_file)
file_menu.addAction(new_action)
open_action = QAction("打开...", self)
open_action.setShortcut("Ctrl+O")
open_action.triggered.connect(self.open_file)
file_menu.addAction(open_action)
file_menu.addSeparator()
save_action = QAction("保存", self)
save_action.setShortcut("Ctrl+S")
save_action.triggered.connect(self.save_file)
file_menu.addAction(save_action)
save_as_action = QAction("另存为...", self)
save_as_action.triggered.connect(self.save_file_as)
file_menu.addAction(save_as_action)
file_menu.addSeparator()
print_action = QAction("打印...", self)
print_action.setShortcut("Ctrl+P")
print_action.triggered.connect(self.print_document)
file_menu.addAction(print_action)
file_menu.addSeparator()
exit_action = QAction("退出", self)
exit_action.setShortcut("Ctrl+Q")
exit_action.triggered.connect(self.close)
file_menu.addAction(exit_action)
# 编辑菜单
edit_menu = menubar.addMenu("编辑")
undo_action = QAction("撤销", self)
undo_action.setShortcut("Ctrl+Z")
undo_action.triggered.connect(self.text_edit.undo)
edit_menu.addAction(undo_action)
redo_action = QAction("重做", self)
redo_action.setShortcut("Ctrl+Y")
redo_action.triggered.connect(self.text_edit.redo)
edit_menu.addAction(redo_action)
edit_menu.addSeparator()
cut_action = QAction("剪切", self)
cut_action.setShortcut("Ctrl+X")
cut_action.triggered.connect(self.text_edit.cut)
edit_menu.addAction(cut_action)
copy_action = QAction("复制", self)
copy_action.setShortcut("Ctrl+C")
copy_action.triggered.connect(self.text_edit.copy)
edit_menu.addAction(copy_action)
paste_action = QAction("粘贴", self)
paste_action.setShortcut("Ctrl+V")
paste_action.triggered.connect(self.text_edit.paste)
edit_menu.addAction(paste_action)
# 格式菜单
format_menu = menubar.addMenu("格式")
bold_action = QAction("加粗", self)
bold_action.setShortcut("Ctrl+B")
bold_action.setCheckable(True)
bold_action.triggered.connect(self.toggle_bold)
format_menu.addAction(bold_action)
italic_action = QAction("斜体", self)
italic_action.setShortcut("Ctrl+I")
italic_action.setCheckable(True)
italic_action.triggered.connect(self.toggle_italic)
format_menu.addAction(italic_action)
underline_action = QAction("下划线", self)
underline_action.setShortcut("Ctrl+U")
underline_action.setCheckable(True)
underline_action.triggered.connect(self.toggle_underline)
format_menu.addAction(underline_action)
def new_file(self):
self.text_edit.clear()
self.current_file = None
self.save_action.setEnabled(False)
self.statusBar().showMessage("新建文档", 2000)
def open_file(self):
file_path, _ = QFileDialog.getOpenFileName(
self, "打开Word文档", "",
"Word文档 (*.docx);;所有文件 (*)"
)
if file_path:
try:
doc = Document(file_path)
self.text_edit.clear()
full_text = []
for para in doc.paragraphs:
full_text.append(para.text)
self.text_edit.setPlainText("\n".join(full_text))
self.current_file = file_path
self.save_action.setEnabled(True)
self.statusBar().showMessage(f"已打开: {file_path}", 3000)
except Exception as e:
QMessageBox.critical(self, "错误", f"无法打开文件:\n{str(e)}")
self.statusBar().showMessage(f"打开文件失败: {str(e)}", 5000)
def save_file(self):
if not self.current_file:
self.save_file_as()
return
try:
doc = Document()
text = self.text_edit.toPlainText()
# 保存为段落
for line in text.split('\n'):
doc.add_paragraph(line)
doc.save(self.current_file)
self.statusBar().showMessage(f"文件已保存: {self.current_file}", 3000)
except Exception as e:
QMessageBox.critical(self, "错误", f"保存失败:\n{str(e)}")
self.statusBar().showMessage(f"保存失败: {str(e)}", 5000)
def save_file_as(self):
file_path, _ = QFileDialog.getSaveFileName(
self, "另存为Word文档", "",
"Word文档 (*.docx);;所有文件 (*)"
)
if file_path:
# 确保扩展名是.docx
if not file_path.endswith('.docx'):
file_path += '.docx'
self.current_file = file_path
self.save_file()
self.save_action.setEnabled(True)
def print_document(self):
# 简单打印功能
printer = QPrinter()
print_dialog = QPrintDialog(printer, self)
if print_dialog.exec_() == QPrintDialog.Accepted:
self.text_edit.print_(printer)
def change_font(self, font):
cursor = self.text_edit.textCursor()
if not cursor.hasSelection():
cursor.select(QTextCursor.WordUnderCursor)
format = cursor.charFormat()
format.setFontFamily(font.family())
cursor.mergeCharFormat(format)
def change_font_size(self, size):
cursor = self.text_edit.textCursor()
if not cursor.hasSelection():
cursor.select(QTextCursor.WordUnderCursor)
format = cursor.charFormat()
format.setFontPointSize(size)
cursor.mergeCharFormat(format)
def toggle_bold(self):
cursor = self.text_edit.textCursor()
if not cursor.hasSelection():
cursor.select(QTextCursor.WordUnderCursor)
format = cursor.charFormat()
format.setFontWeight(QFont.Bold if self.bold_action.isChecked() else QFont.Normal)
cursor.mergeCharFormat(format)
def toggle_italic(self):
cursor = self.text_edit.textCursor()
if not cursor.hasSelection():
cursor.select(QTextCursor.WordUnderCursor)
format = cursor.charFormat()
format.setFontItalic(self.italic_action.isChecked())
cursor.mergeCharFormat(format)
def toggle_underline(self):
cursor = self.text_edit.textCursor()
if not cursor.hasSelection():
cursor.select(QTextCursor.WordUnderCursor)
format = cursor.charFormat()
format.setFontUnderline(self.underline_action.isChecked())
cursor.mergeCharFormat(format)
def update_format_buttons(self):
cursor = self.text_edit.textCursor()
format = cursor.charFormat()
# 更新字体组合框
self.font_combo.setCurrentFont(QFont(format.fontFamily()))
# 更新字号
self.font_size.setValue(format.fontPointSize())
# 更新加粗、斜体、下划线按钮状态
self.bold_action.setChecked(format.fontWeight() == QFont.Bold)
self.italic_action.setChecked(format.fontItalic())
self.underline_action.setChecked(format.fontUnderline())
if __name__ == "__main__":
app = QApplication(sys.argv)
editor = WordEditor()
editor.show()
sys.exit(app.exec_())
3. 功能扩展实现
3.1 添加图片支持
def insert_image(self):
file_path, _ = QFileDialog.getOpenFileName(
self, "插入图片", "",
"图片文件 (*.png *.jpg *.jpeg *.bmp *.gif)"
)
if file_path:
cursor = self.text_edit.textCursor()
cursor.insertHtml(f'<img src="{file_path}" />')
3.2 添加表格支持
def insert_table(self):
rows, ok1 = QInputDialog.getInt(self, "插入表格", "行数:", 3, 1, 20)
cols, ok2 = QInputDialog.getInt(self, "插入表格", "列数:", 3, 1, 20)
if ok1 and ok2:
cursor = self.text_edit.textCursor()
table_html = "<table border='1'>"
for _ in range(rows):
table_html += "<tr>"
for _ in range(cols):
table_html += "<td> </td>"
table_html += "</tr>"
table_html += "</table>"
cursor.insertHtml(table_html)
3.3 添加页眉页脚支持
def add_header_footer(self):
doc = Document()
# 添加页眉
header = doc.sections[0].header
header_para = header.paragraphs[0]
header_para.text = "这是页眉"
# 添加正文
doc.add_paragraph(self.text_edit.toPlainText())
# 添加页脚
footer = doc.sections[0].footer
footer_para = footer.paragraphs[0]
footer_para.text = "这是页脚"
# 保存临时文件并打开
temp_file = "temp_with_header_footer.docx"
doc.save(temp_file)
os.startfile(temp_file) # Windows
# 在macOS上使用: os.system(f"open {temp_file}")
# 在Linux上使用: os.system(f"xdg-open {temp_file}")
4. 高级功能实现
4.1 文档格式转换
def convert_to_pdf(self):
if not self.current_file:
QMessageBox.warning(self, "警告", "请先保存Word文档")
return
try:
from docx2pdf import convert
pdf_path = os.path.splitext(self.current_file)[0] + ".pdf"
convert(self.current_file, pdf_path)
QMessageBox.information(self, "成功", f"已转换为PDF: {pdf_path}")
except ImportError:
QMessageBox.critical(self, "错误", "请先安装docx2pdf库: pip install docx2pdf")
except Exception as e:
QMessageBox.critical(self, "错误", f"转换失败:\n{str(e)}")
4.2 文档合并
def merge_documents(self):
files, _ = QFileDialog.getOpenFileNames(
self, "选择要合并的Word文档", "",
"Word文档 (*.docx)"
)
if len(files) < 2:
QMessageBox.warning(self, "警告", "请至少选择两个文档进行合并")
return
try:
merged = Document()
for file in files:
doc = Document(file)
for element in doc.element.body:
merged.element.body.append(element)
save_path, _ = QFileDialog.getSaveFileName(
self, "保存合并后的文档", "",
"Word文档 (*.docx)"
)
if save_path:
if not save_path.endswith('.docx'):
save_path += '.docx'
merged.save(save_path)
QMessageBox.information(self, "成功", f"文档已合并保存到: {save_path}")
except Exception as e:
QMessageBox.critical(self, "错误", f"合并失败:\n{str(e)}")
5. 部署为独立应用
可以使用PyInstaller将应用打包为独立可执行文件:
pip install pyinstaller pyinstaller --onefile --windowed word_editor.py
这将在dist目录下生成可执行文件,可以在没有Python环境的电脑上运行。
6. 总结
这个Word编辑器实现了以下功能:
-
基本的文档创建、打开、保存和另存为
-
文本格式设置(字体、字号、加粗、斜体、下划线)
-
图片和表格插入
-
页眉页脚支持
-
文档格式转换(如转PDF)
-
文档合并功能
进一步扩展功能,例如:
-
添加更多格式选项(文本颜色、背景色、对齐方式等)
-
实现目录生成功能
-
添加批注和修订功能
-
实现邮件合并功能
-
添加文档加密/解密功能
-
集成拼写检查功能
4792

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



