在当今的商业世界中,合同是不可或缺的。但是,反复修改和生成合同可能会是一个耗时且容易出错的过程。今天,我们将探讨如何使用Python创建一个简单但强大的合同生成器,它不仅可以节省时间,还能减少人为错误。
项目概述
我们将创建一个图形用户界面(GUI)应用程序,允许用户:
- 选择一个Word模板文件
- 输入合同详细信息,如甲方、乙方、日期、总金额等
- 自动生成一个新的、定制的合同文档
这个项目将展示如何结合使用wxPython(用于创建GUI)和Python-docx(用于处理Word文档)来创建一个实用的业务工具。
C:\pythoncode\new\contacttodoct.py
技术栈
- Python 3.x
- wxPython: 用于创建跨平台的GUI应用程序
- Python-docx: 用于读取和修改Word文档
全部代码
import wx
import os
from docx import Document
from docx.shared import Pt
from datetime import datetime
class ContractFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Contract Generator', size=(500, 600))
# 创建主面板
main_panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
# 创建滚动窗口
self.scrolled_window = wx.ScrolledWindow(main_panel)
self.scrolled_window.SetScrollRate(0, 10)
# 创建控件
self.template_path = wx.TextCtrl(self.scrolled_window)
browse_button = wx.Button(self.scrolled_window, label='Browse')
browse_button.Bind(wx.EVT_BUTTON, self.on_browse)
self.party_a = wx.TextCtrl(self.scrolled_window)
self.party_b = wx.TextCtrl(self.scrolled_window)
self.date = wx.TextCtrl(self.scrolled_window)
self.total_amount = wx.TextCtrl(self.scrolled_window)
self.payment_dates = [wx.TextCtrl(self.scrolled_window) for _ in range(3)]
self.payment_amounts = [wx.TextCtrl(self.scrolled_window) for _ in range(3)]
self.payment_percentages = [wx.TextCtrl(self.scrolled_window) for _ in range(3)]
generate_button = wx.Button(main_panel, label='Generate Contract')
generate_button.Bind(wx.EVT_BUTTON, self.on_generate)
# 创建滚动窗口内的布局
scroll_sizer = wx.BoxSizer(wx.VERTICAL)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Template File:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.template_path, 0, wx.EXPAND|wx.ALL, 5)
scroll_sizer.Add(browse_button, 0, wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Party A:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.party_a, 0, wx.EXPAND|wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Party B:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.party_b, 0, wx.EXPAND|wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Date:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.date, 0, wx.EXPAND|wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Total Amount:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.total_amount, 0, wx.EXPAND|wx.ALL, 5)
for i in range(3):
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label=f"Payment {i+1}:"), 0, wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Date:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.payment_dates[i], 0, wx.EXPAND|wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Amount:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.payment_amounts[i], 0, wx.EXPAND|wx.ALL, 5)
scroll_sizer.Add(wx.StaticText(self.scrolled_window, label="Percentage:"), 0, wx.ALL, 5)
scroll_sizer.Add(self.payment_percentages[i], 0, wx.EXPAND|wx.ALL, 5)
self.scrolled_window.SetSizer(scroll_sizer)
# 设置主布局
main_sizer.Add(self.scrolled_window, 1, wx.EXPAND|wx.ALL, 5)
main_sizer.Add(generate_button, 0, wx.ALL|wx.CENTER, 5)
main_panel.SetSizer(main_sizer)
# 计算滚动窗口的虚拟大小
self.scrolled_window.SetVirtualSize(scroll_sizer.GetMinSize())
self.Show()
def on_browse(self, event):
with wx.FileDialog(self, "Choose the template file", wildcard="Word files (*.docx)|*.docx",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return
self.template_path.SetValue(fileDialog.GetPath())
def on_generate(self, event):
if not os.path.exists(self.template_path.GetValue()):
wx.MessageBox("Please select a valid template file", "Error", wx.OK | wx.ICON_ERROR)
return
# 读取模板文件
doc = Document(self.template_path.GetValue())
# 替换内容
for paragraph in doc.paragraphs:
paragraph.text = paragraph.text.replace("{PartyA}", self.party_a.GetValue())
paragraph.text = paragraph.text.replace("{PartyB}", self.party_b.GetValue())
paragraph.text = paragraph.text.replace("{Date}", self.date.GetValue())
paragraph.text = paragraph.text.replace("{TotalAmount}", self.total_amount.GetValue())
for i in range(3):
paragraph.text = paragraph.text.replace(f"{{PaymentDate{i+1}}}", self.payment_dates[i].GetValue())
paragraph.text = paragraph.text.replace(f"{{PaymentAmount{i+1}}}", self.payment_amounts[i].GetValue())
paragraph.text = paragraph.text.replace(f"{{PaymentPercentage{i+1}}}", self.payment_percentages[i].GetValue())
# 保存新文件
save_path = f"Contract_{datetime.now().strftime('%Y%m%d_%H%M%S')}.docx"
doc.save(save_path)
wx.MessageBox(f"Contract generated and saved as {save_path}", "Success", wx.OK | wx.ICON_INFORMATION)
if __name__ == '__main__':
app = wx.App()
frame = ContractFrame()
app.MainLoop()
步骤1: 设置环境
首先,确保您已经安装了所需的库:
pip install wxPython python-docx
步骤2: 创建基本GUI结构
我们首先创建一个基本的GUI框架,包括一个主窗口和一个滚动面板:
import wx
import os
from docx import Document
from datetime import datetime
class ContractFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Contract Generator', size=(500, 600))
main_panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_window = wx.ScrolledWindow(main_panel)
self.scrolled_window.SetScrollRate(0, 10)
# 这里将添加更多的控件
self.Show()
if __name__ == '__main__':
app = wx.App()
frame = ContractFrame()
app.MainLoop()
步骤3: 添加输入字段
接下来,我们添加各种输入字段,如模板文件路径、甲方、乙方、日期等:
class ContractFrame(wx.Frame):
def __init__(self):
# ... 前面的代码 ...
self.template_path = wx.TextCtrl(self.scrolled_window)
browse_button = wx.Button(self.scrolled_window, label='Browse')
browse_button.Bind(wx.EVT_BUTTON, self.on_browse)
self.party_a = wx.TextCtrl(self.scrolled_window)
self.party_b = wx.TextCtrl(self.scrolled_window)
self.date = wx.TextCtrl(self.scrolled_window)
self.total_amount = wx.TextCtrl(self.scrolled_window)
self.payment_dates = [wx.TextCtrl(self.scrolled_window) for _ in range(3)]
self.payment_amounts = [wx.TextCtrl(self.scrolled_window) for _ in range(3)]
self.payment_percentages = [wx.TextCtrl(self.scrolled_window) for _ in range(3)]
generate_button = wx.Button(main_panel, label='Generate Contract')
generate_button.Bind(wx.EVT_BUTTON, self.on_generate)
# 添加到sizer并设置布局
# ...
步骤4: 实现文件浏览功能
我们需要一个方法来允许用户选择模板文件:
def on_browse(self, event):
with wx.FileDialog(self, "Choose the template file", wildcard="Word files (*.docx)|*.docx",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return
self.template_path.SetValue(fileDialog.GetPath())
步骤5: 实现合同生成功能
这是我们程序的核心,我们将使用Python-docx来读取模板,替换占位符,并生成新的合同文档:
def on_generate(self, event):
if not os.path.exists(self.template_path.GetValue()):
wx.MessageBox("Please select a valid template file", "Error", wx.OK | wx.ICON_ERROR)
return
doc = Document(self.template_path.GetValue())
for paragraph in doc.paragraphs:
paragraph.text = paragraph.text.replace("{PartyA}", self.party_a.GetValue())
paragraph.text = paragraph.text.replace("{PartyB}", self.party_b.GetValue())
paragraph.text = paragraph.text.replace("{Date}", self.date.GetValue())
paragraph.text = paragraph.text.replace("{TotalAmount}", self.total_amount.GetValue())
for i in range(3):
paragraph.text = paragraph.text.replace(f"{{PaymentDate{i+1}}}", self.payment_dates[i].GetValue())
paragraph.text = paragraph.text.replace(f"{{PaymentAmount{i+1}}}", self.payment_amounts[i].GetValue())
paragraph.text = paragraph.text.replace(f"{{PaymentPercentage{i+1}}}", self.payment_percentages[i].GetValue())
save_path = f"Contract_{datetime.now().strftime('%Y%m%d_%H%M%S')}.docx"
doc.save(save_path)
wx.MessageBox(f"Contract generated and saved as {save_path}", "Success", wx.OK | wx.ICON_INFORMATION)
合同模板
为了使这个程序工作,我们需要一个包含占位符的Word模板。这里是一个简单的示例:
合作协议
本协议由以下双方于{Date}签订:
甲方:{PartyA}
乙方:{PartyB}
...
2.1 本合同总金额为人民币{TotalAmount}元整。
2.2 付款方式如下:
第一期付款:于{PaymentDate1}支付{PaymentAmount1}元,占总金额的{PaymentPercentage1}。
第二期付款:于{PaymentDate2}支付{PaymentAmount2}元,占总金额的{PaymentPercentage2}。
第三期付款:于{PaymentDate3}支付{PaymentAmount3}元,占总金额的{PaymentPercentage3}。
...
结果如下
结论
通过这个项目,我们创建了一个实用的合同生成器,它展示了如何:
- 使用wxPython创建用户友好的GUI应用程序
- 使用Python-docx处理Word文档
- 将GUI与文档处理功能结合,创建一个实用的业务工具
这个应用程序可以显著提高合同生成的效率,减少人为错误,并为进一步的自动化和定制提供了基础。
你可以进一步改进这个项目,例如添加更多的输入验证,支持更复杂的模板,或者集成数据库来存储和检索合同信息。
希望这个教程能够帮助你开始使用Python创建实用的业务应用程序。祝编码愉快!