python操作word库 (python读取excel批量生成word)

一、项目开发背景

工作中经常跟合同打过交道的人,可能都有一个比较令人烦躁的问题,合同要素信息重复的填写,一个个的填,很麻烦。当使用固定合同模板时,只是合同要素(比如:甲方名称、乙方名称、合同名称、合同金额、地址信息、财务信息等等)不同,能否考虑率搞个通用的模板,通过Python老操作Word和Excel就直接替换,然后就有了这款软件,可使用Python操作Word读取Excel中的合同要素信息批量生成合同。

考虑到用户的友好体验,引入了GUI界面,同时为了增加一点难度,就引入了数据库,用户登录、注册、密码修改等,同时也适合Python初学者,自动化办公应用方便提高能力。

二、项目整体架构

python读取excel批量生成word,python自动生成销售合同

python读取excel批量生成word,python自动生成销售合同

三、项目整体效果展示

1、生成EXE文件后的文件夹,双击login*ex.e** 即可使用

python读取excel批量生成word,python自动生成销售合同

2、基于Python的tkinter库的用户登录、注册、密码修改等,数据库采用sqlite3是一个轻便型的数据库库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。

self.conn = sqlite3.connect('data/login.db')

python读取excel批量生成word,python自动生成销售合同

python读取excel批量生成word,python自动生成销售合同

python读取excel批量生成word,python自动生成销售合同

3、登录界面同数据库验证密码后,就可以出现登录使用,使用Python操作Word合同模板读取合同信息Excel表中的合同要素信息,批量生成合同。合同要素信息EXCEL表字段信息对应Word合同模板的字段信息,点击开始生成合同,软件自动批量生成对应的合同。

python读取excel批量生成word,python自动生成销售合同

四、项目的代码

from tkinter import *
import sqlite3
import tkinter.messagebox as messagebox
from docx import Document
import xlrd



class LoginPage:
	"""登录界面"""

	def __init__(self, master):
		self.root = master
		self.root.geometry('400x200+600+400')
		self.root.resizable(0, 0)
		self.root.title('合同自动批量生成平台')
		self.root["background"] = "lightgrey"
		self.root.rowconfigure(3, weight=1)
		self.root.columnconfigure(4, weight=1)
		self.root.iconbitmap('image/logo2.ico')
		self.conn = sqlite3.connect('data/login.db')
		self.username = StringVar()
		self.password = StringVar()
		self.page = Frame(self.root)
		self.page["background"] = "lightgrey"
		self.creatapage()

	def creatapage(self):
		"""界面布局"""
		Label(self.page, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=0)
		Label(self.page, text='用户名:', font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=1, stick=W, pady=10)
		Entry(self.page, textvariable=self.username, font=("微软雅黑", 10, "bold")).grid(row=1, column=3, stick=W)
		Label(self.page, text='密  码:', font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=2, stick=W, pady=10)
		Entry(self.page, textvariable=self.password, show='*', font=("微软雅黑", 10, "bold")).grid(row=2, stick=W, column=3)
		Button(self.page, text='登   录', command=self.login, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=3, column=0,columnspan=2,pady=10)
		Button(self.page, text='密码修改', command=self.editpassword, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=3, column=2,columnspan=2, pady=10)
		Button(self.page, text='注册账号', command=self.register, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=3,column=4,columnspan=2, pady=10)
		self.page.pack()

	def login(self):
		"""登录功能"""

		curs = self.conn.cursor()
		query = "select username, password, loginerror from loginuser where username='%s'" % self.username.get()
		curs*ex.e**cute(query)  # 返回一个迭代器
		c = curs.fetchall()  # 接收全部信息
		print(len(c))
		if len(c) == 0:
			messagebox.showerror('登录失败', '账户不存在')
		else:
			us, pw, lerror = c[0]
			if lerror >= 3:
				messagebox.showwarning('登录失败', '账户已被锁定')
			elif us == self.username.get() and pw == self.password.get():
				self.conn.close()
				# messagebox.showinfo('登录成功', '欢迎:%s' % us)
				self.page.destroy()
				MainPage(self.root)
			else:
				messagebox.showwarning('登录失败', '密码错误')


	def register(self):
		"""注册功能跳转"""
		self.conn.close()
		self.page.destroy()
		RegisterPage(self.root)

	def editpassword(self):
		"""重置密码"""
		"""注册功能跳转"""
		self.conn.close()
		self.page.destroy()
		ResetPassword(self.root)


class RegisterPage:
	"""注册界面"""

	def __init__(self, master=None):
		self.root = master
		self.root.title('账号注册')
		self.root.geometry('400x300')
		self.root.resizable(0, 0)
		self.conn = sqlite3.connect('data/login.db')
		self.username = StringVar()
		self.password0 = StringVar()  # 第一次输入密码
		self.password1 = StringVar()  # 第二次输入密码
		self.email = StringVar()
		self.page = Frame(self.root)
		self.page["background"] = "lightgrey"
		self.createpage()

	def createpage(self):
		"""界面布局"""
		Label(self.page, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=0)
		Label(self.page, text="账号:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=1, stick=W, pady=10)
		Entry(self.page, textvariable=self.username).grid(row=1, column=1, stick=E)
		Label(self.page, text="密码:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=2, stick=W, pady=10)
		Entry(self.page, textvariable=self.password0, show='*').grid(row=2, column=1, stick=E)
		Label(self.page, text="再次输入:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=3, stick=W, pady=10)
		Entry(self.page, textvariable=self.password1, show='*').grid(row=3, column=1, stick=E)
		Label(self.page, text="Email*:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=4, stick=W, pady=10)
		Entry(self.page, textvariable=self.email).grid(row=4, column=1, stick=E)
		Button(self.page, text="返回", command=self.repage, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=5, stick=W, pady=10)
		Button(self.page, text="注册", command=self.register, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=5, column=1, stick=E)
		self.page.pack()

	def repage(self):
		"""返回登录界面"""
		self.page.destroy()
		self.conn.close()
		LoginPage(self.root)

	def register(self):
		"""注册"""
		if self.password0.get() != self.password1.get():
			messagebox.showwarning('错误', '密码核对错误')
		elif len(self.username.get()) == 0 or len(self.password0.get()) == 0 or len(self.email.get()) == 0:
			messagebox.showerror("错误", "不能为空")
		else:
			curs = self.conn.cursor()
			query = 'insert into loginuser values (?,?,?,?)'
			val = [self.username.get(), self.password0.get(), self.email.get(), 0]
			try:
				curs*ex.e**cute(query, val)
				self.conn.commit()
				self.conn.close()
				messagebox.showinfo("成功", "注册成功,按确定返回登录界面")
				self.page.destroy()

				LoginPage(self.root)
			except sqlite3.IntegrityError:
				messagebox.showerror("注册失败", "该账户已存在")


class ResetPassword:
	"""重置界面界面"""

	def __init__(self, master=None):
		self.root = master
		self.root.title('重置密码')
		self.root.geometry('400x300')
		self.root.resizable(0, 0)
		self.conn = sqlite3.connect('data/login.db')
		self.username = StringVar()
		self.password = StringVar()  # 原密码
		self.password1 = StringVar()  # 新密码
		self.password2 = StringVar()  # 新密码
		self.page = Frame(self.root)
		self.page["background"] = "lightgrey"
		self.createpage1()

	def createpage1(self):
		"""界面布局"""
		Label(self.page, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=0)
		Label(self.page, text="账号:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=1, stick=W, pady=10)
		Entry(self.page, textvariable=self.username).grid(row=1, column=1, stick=E)
		Label(self.page, text="原密码:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=2, stick=W, pady=10)
		Entry(self.page, textvariable=self.password, show='*').grid(row=2, column=1, stick=E)
		Label(self.page, text="新密码:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=3, stick=W, pady=10)
		Entry(self.page, textvariable=self.password1, show='*').grid(row=3, column=1, stick=E)
		Label(self.page, text="确认新密码:", font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=4, stick=W, pady=10)
		Entry(self.page, textvariable=self.password2, show='*').grid(row=4, column=1, stick=E)
		Button(self.page, text="返回", command=self.repage1, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=5, stick=W, pady=10)
		Button(self.page, text="重置", command=self.register1, font=("微软雅黑", 10, "bold"), background='lightgrey').grid(row=5, column=1, stick=E)
		self.page.pack()

	def repage1(self):
		"""返回登录界面"""
		self.page.destroy()
		self.conn.close()
		LoginPage(self.root)

	def register1(self):
		"""重置"""

		curs = self.conn.cursor()
		query = "select username, password, loginerror from loginuser where username='%s'" % self.username.get()
		curs*ex.e**cute(query)  # 返回一个迭代器
		c = curs.fetchall()  # 接收全部信息
		print(len(c))
		if len(c) == 0:
			messagebox.showerror('登录失败', '账户不存在')
		else:
			us, pw, lerror = c[0]
			print(us,pw,lerror)
			if lerror >= 3:
				messagebox.showwarning('登录失败', '账户已被锁定')
			elif us == self.username.get() and pw == self.password.get():
				if self.password1.get() != self.password2.get():
					messagebox.showwarning('错误', '密码核对错误')
				else:
					curs = self.conn.cursor()
					query = "UPDATE loginuser SET password='%s' WHERE username='%s'" % (self.password1.get(),self.username.get())

					try:
						curs*ex.e**cute(query)
						self.conn.commit()
						self.conn.close()
						messagebox.showinfo("成功", "重置成功,按确定返回登录界面")
						self.page.destroy()

						LoginPage(self.root)
					except sqlite3.IntegrityError:
						messagebox.showerror("重置失败", "该账户不存在")


class MainPage:
	"""登陆后界面"""

	def __init__(self, master=None):
		self.root = master
		self.root.title("合同自动批量生成")
		self.root.geometry("600x550+600+100")
		self.root.resizable(0, 0)
		self.xlsx = xlrd.open_workbook('合同信息表.xlsx')
		self.sheet = self.xlsx.sheet_by_index(0)

		# 合同循环运行
		def MessageID():

			print('合同开始转换')
			text.insert(INSERT, '合同开始转换')
			text.insert(INSERT, "\r\n")
			text.update()
			for table_row in range(2, self.sheet.nrows):  # 合同要素Excel中逐列循环
				image_name = updata()
				# print(image_name)
				document1 = Document("合同模板/%s.docx" % image_name)

				for table_col in range(0, self.sheet.ncols):  # 合同要素Excel中逐行循环
					replace_text(str(self.sheet.cell_value(0, table_col)),
								 str(self.sheet.cell_value(table_row, table_col)), document1)  # 进行替换
				document1.save("%s.docx" % str(self.sheet.cell_value(table_row, 0)))  # 按定义的文件名进行保存
				print("%s合同生成完毕!" % str(self.sheet.cell_value(table_row, 0)))
				str5 = "%s合同生成完毕!" % str(self.sheet.cell_value(table_row, 0))

				text.insert(INSERT, str5)
				text.insert(INSERT, "\r\n")
				text.update()

		'''

		定义替换函数
		'''

		def replace_text(old_text, new_text, document1):
			all_paragraphs = document1.paragraphs  # 读取所有的自然段

			for paragraph in all_paragraphs:
				for run in paragraph.runs:  # 循环读取所有的run,并进行新旧文本的替换
					run_text = run.text.replace(old_text, new_text)
					run.text = run_text
			all_tables = document1.tables  # 读取所有的表格
			for table in all_tables:
				for row in table.rows:
					for cell in row.cells:  # 循环读取表格中所有的cells,并进行新旧文本的替换
						cell_text = cell.text.replace(old_text, new_text)
						cell.text = cell_text

		def updata():
			image_name_numb = ht.get()
			if image_name_numb == 1:
				image_name = "模板-1"
				return image_name
			elif image_name_numb == 2:
				image_name = "模板-2"
				return image_name
			elif image_name_numb == 3:
				image_name = "模板-3"
				return image_name
			elif image_name_numb == 4:
				image_name = "模板-4"
				return image_name
			elif image_name_numb == 5:
				image_name = "模板-5"
				return image_name
			elif image_name_numb == 6:
				image_name = "模板-6"
				return image_name
			elif image_name_numb == 7:
				image_name = "模板-7"
				return image_name
			elif image_name_numb == 8:
				image_name = "模板-8"
				return image_name

		"""界面布局"""
		Label(self.root, text="请选择常用合同模板", font=("微软雅黑", 12, "bold"), background='lightgrey', fg="Black", bg="DeepSkyBlue", width=15).place(x=20, y=30)
		ht = IntVar()  # 给单选框添加variable,用于显示value值
		ht.set(3)
		Radiobutton(self.root, text="模板-1", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', fg="Black", value=1, command=updata).place(x=20, y=60)
		Radiobutton(self.root, text="模板-2", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', value=2, fg="Blue", command=updata).place(x=20, y=90)
		Radiobutton(self.root, text="模板-3", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', value=3, command=updata).place(x=20, y=120)
		Radiobutton(self.root, text="模板-4", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', value=4, fg="Blue", command=updata).place(x=20, y=150)
		Radiobutton(self.root, text="模板-5", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', fg="Black", value=5, command=updata).place(x=20, y=180)
		Radiobutton(self.root, text="模板-6", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', value=6, fg="Blue", command=updata).place(x=20, y=210)
		Radiobutton(self.root, text="模板-7", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', value=7, command=updata).place(x=20, y=240)
		Radiobutton(self.root, text="模板-8", variable=ht, font=("微软雅黑", 12, "bold"), background='lightgrey', value=8, fg="Blue", command=updata).place(x=20, y=270)

		Button(self.root, text='开始生成合同', font=("微软雅黑", 12, "bold"), width=25, fg="Black", bg="DeepSkyBlue", command=MessageID).place(x=240, y=30)

		Button(self.root, text='退出', font=("微软雅黑", 12, "bold"), width=25, fg="Black", bg="DeepSkyBlue",command=root.quit).place(x=240, y=80)

		text = Text(self.root, width=42, height=9.3, font=("微软雅黑", 12), fg="Blue", background='LightGrey')
		text.place(x=200, y=145)
		Label(self.root, text="使用方法", font=("微软雅黑", 12, "bold"), wraplength=400, justify="left", anchor="w", fg="Black",  background='lightgrey', width = 60).place(x=200, y=350)
		str1 = "1、填写“合同信息表”,不要改变表名称 \n"
		str2 = "2、选择对应合同模板,点击开始生成合同 \n"
		str3 = "3、提示合同生成后,可以点击“退出 ”\n"
		Label(self.root, text=str1 + str2 + str3, font=("微软雅黑", 12, "bold"), wraplength=400, justify="left",anchor="w", fg="Black",  background='lightgrey', width=60).place(x=200, y=380)


if __name__ == '__main__':
	root = Tk()
	LoginPage(root)
	root.mainloop()

本文主要介绍了Python操作Word读取Excel中的合同要素信息批量生成合同的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,有问题欢迎大家关注或留言交流讨论共同进步。