一、需求介绍
因为我的毕设需要设计一个系统,然后把结果生成检测报告供企业下载。模型大概已经训练好了,也就差个导出word功能,把模型识别的数据结果输入到word导出即可。
二、最终实现效果
这里随便整个模板来对所需要的函数进行说明,单行、双行、标题、图片基本上所需要的需求都有了,进行了开始进行详细的讲解
三、分析
1,标题:陕西省功能面料重点实验室
2,段落(正文):织物起球等级检测报告
3,表格:31行18列
将俩表格一对比家人们应该就差不多明白了吧,将对角的单元格合并即可
一共分为六个块
四、实战
ⅠQt界面
就先简单设计一个页面,点击button然后生成word
页面文件名称为:word_test.ui
button的名称为:pushButton
ⅡPython代码
1,准备工作
创建一个python文件,例如:_test.py
,这个文件待会要进行代码编写
将ui文件与py文件放到同一个路径下
我的是这样
然后我这边添加一个logo图片,三张测试样本图片
最终的目录结构如图所示:
2,我使用的是PyCharm,当然其他的IDE都可以
选择一个环境空间,看个人需求,这个环境空间得有相应的包
3,导包
缺啥包直接pip install安装,这里就不再赘述
from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
from PySide2.QtGui import QIcon
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches,Cm,Pt
4,主函数以及控件绑定
详细pyqt可参考博文:二、页面布局
主函数
if __name__=="__main__":
app = QApplication([])
app.setWindowIcon(QIcon('./yyy.png')) #logo图片位置
gui = test_word() #初始化
gui.window_init()
gui.ui.show() #将窗口控件显示在屏幕上
app.exit(app.exec_())
控件绑定
self.ui.pushButton.clicked.connect(self.word)
,当控件被点击的时候,调用word函数即可,主要难点在于word函数的逻辑编写
class test_word():
def __init__(self):
# 从文件中加载UI定义
# 从 UI 定义中动态 创建一个相应的窗口对象
# 注意:里面的控件对象也成为窗口对象的属性了
# 比如 self.ui.button , self.ui.textEdit
self.ui = QUiLoader().load('word_test.ui') # 这里的参数为ui的路径,对这个ui文件创建对象ui
"""
对某个控件进行操作会产生一个signal,常通过slot来进行处理signal
slot就是通过clicked.connect来绑定某个函数,这个函数用于处理signal
"""
self.output_size = 320
def window_init(self):
self.ui.pushButton.clicked.connect(self.word)
5,word函数功能实现详细讲解
①初始化参数
为了简便问题,这里使用字符串代替word里面的内容
print("正在生成word检测报告...") # 方便调试使用
name = "yanyu"
product_name = "新型隐身作战服"
testing_department = "西安工程大学"
test_category = "棉织物"
production_unit = "咸阳际华新三零"
number_of_samples = "1张"
sample_price = "512.32 $"
test_instrument = "万能耐磨仪"
sample_grade = "3级"
②添加标题
document = Document()
,首先定义一个文档对象
document.styles['Normal'].font.name = u'宋体'
,设置字体为宋体
document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
,汉字是宋体
,字母是eastAsia
title = document.add_heading(u'陕西省功能面料重点实验室', 0)
,创建标题,这里的参数0是标题,其他的数字分别表示对应的标题等级
title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
,标题居中
添加标题完整代码
document = Document()
document.styles['Normal'].font.name = u'宋体'
document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
#添加标题
title = document.add_heading(u'陕西省功能面料重点实验室', 0)#0级标题
# 标题居中
title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
④添加段落
p = document.add_paragraph()
,定义一个段落对象
p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
,段落居中
r = p.add_run('织物起球等级检测报告')
,显示内容
r.font.size = Pt(24)
,字体大小设置
需要添加几个段落就加几个就行,这里以俩段落为例
添加段落完整代码
#添加段落1
p = document.add_paragraph()
p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER #添加的段落都居中
r = p.add_run('织物起球等级检测报告')
r.font.size = Pt(24)
r.bold = True
# 添加段落2
p1 = document.add_paragraph()
p1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER # 添加的段落都居中
r1 = p1.add_run('author:yanyu')
r1.font.size = Pt(12)
r1.bold = True
⑤添加表格
根据我上面分析的,然后进行合并即可
之后添加内容
table = document.add_table(rows=31, cols=18, style='Table Grid')
,创建31行28列的表格
table.autofit = False
,不需要根据内容来自适应
table.columns[0].width = Inches(0.49)
,列宽0.49英寸
由上述分析可得,表格可分为六个块组成,接下来一块一块的来进行讲解
第一块:
table.cell(0, 0).merge(table.cell(2, 2))
,将(0,0)
和(2,2)
单元合并
table.cell(0, 3).merge(table.cell(2, 17))
,同理,将(0,3)
和(2,17)
单元合并
block_1 = table.rows[0].cells
,获得第一块对象。整个表格一共分为六块,第一块是从第0行开始的,故通过table.rows[0].cells
来进行获取
block_1[0].add_paragraph('产品名称\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第一块对象是block_1
,需要在第0
列出添加内容
block_1[3].add_paragraph(product_name).alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第3列添加内容
第二块:
table.cell(3, 0).merge(table.cell(5, 2))
,将(3,0)
和(5,2)
单元合并
table.cell(3, 3).merge(table.cell(5, 8))
,将(3,3)
和(5,8)
单元合并
table.cell(3, 9).merge(table.cell(5, 11))
,将(3,9)
和(5,11)
单元合并
table.cell(3, 12).merge(table.cell(5, 17))
,将(3,12)
和(5,17)
单元合并
block_2 = table.rows[3].cells
,获得第二块对象。第二块是从第3行开始的,故通过table.rows[3].cells
来进行获取
block_2[0].add_paragraph('测试部门\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第二块对象是block_2
,需要在第0
列出添加内容
block_2[3].add_paragraph(testing_department).alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第3
列出添加内容
block_2[9].add_paragraph('检验类别\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第9
列出添加内容
block_2[12].add_paragraph(test_category).alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第12
列出添加内容
第三块:
table.cell(6, 0).merge(table.cell(8, 2))
,将(6,0)
和(8,2)
单元合并
table.cell(6, 3).merge(table.cell(8, 8))
,将(6,3)
和(8,8)
单元合并
table.cell(6, 9).merge(table.cell(8, 11))
,将(6,9)
和(8,11)
单元合并
table.cell(6, 12).merge(table.cell(8, 17))
,将(6,12)
和(8,17)
单元合并
block_3 = table.rows[6].cells
,获得第三块对象。第三块是从第6行开始的,故通过table.rows[6].cells
来进行获取
block_3[0].add_paragraph('生产单位\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第三块对象是block_3
,需要在第0
列出添加内容
block_3[3].add_paragraph(production_unit).alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第3
列出添加内容
block_3[9].add_paragraph('样品数量\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第9
列出添加内容
block_3[12].add_paragraph(number_of_samples).alignment = WD_ALIGN_PARAGRAPH.CENTER
,在第12
列出添加内容
第四块:
table.cell(9, 0).merge(table.cell(11, 2))
,将(9,0)
和(11,2)
单元合并
table.cell(9, 3).merge(table.cell(11, 8))
,将(9,3)
和(11,8)
单元合并
table.cell(9, 8).merge(table.cell(11, 11))
,将(9,8)
和(11,11)
单元合并
table.cell(9, 12).merge(table.cell(11, 17))
,将(9,12)
和(11,17)
单元合并
block_4 = table.rows[9].cells
,获得第四块对象,第四块是从第9行开始的,故通过table.rows[9].cells
来进行获取
block_4[0].add_paragraph('测试仪器\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第四大行对象是block_4
,需要在第0
列出添加内容
block_4[3].add_paragraph(test_instrument).alignment = WD_ALIGN_PARAGRAPH.CENTER
,第四块的对象是block_4
,需要在第3
列出添加内容
block_4[9].add_paragraph('样品价格\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第四块对象的是block_4
,需要在第9
列出添加内容
block_4[12].add_paragraph(sample_price).alignment = WD_ALIGN_PARAGRAPH.CENTER
,第四块的对象是block_4
,需要在第12
列出添加内容
第五块:
table.cell(12, 0).merge(table.cell(14, 2))
,将(12,0)
和(14,2)
单元合并
table.cell(12, 3).merge(table.cell(14, 17))
,将(12,3)
和(14,17)
单元合并
block_5 = table.rows[12].cells
,获得第五块对象,第五块是从第12行开始的,故通过table.rows[12].cells
来进行获取
block_5[0].add_paragraph('最终评定等级结果\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第五块对象是block_5
,需要在第0
列出添加内容
block_5[3].add_paragraph(sample_grade).alignment = WD_ALIGN_PARAGRAPH.CENTER
,第五块的对象是block_5
,需要在第3
列出添加内容
第六块
左边部分
table.cell(15, 0).merge(table.cell(30, 2))
,将(15,0)
和(30,2)
单元合并
table.cell(15, 3).merge(table.cell(20, 7))
,将(15,3)
和(20,7)
单元合并
table.cell(15, 8).merge(table.cell(20, 12))
,将(15,8)
和(20,12)
单元合并
table.cell(15, 13).merge(table.cell(20, 17))
,将(15,13)
和(20,17)
单元合并
table.cell(21, 3).merge(table.cell(21, 7))
,将(21,3)
和(21,7)
单元合并
table.cell(21, 8).merge(table.cell(21, 12))
,将(21,8)
和(21,12)
单元合并
table.cell(21, 13).merge(table.cell(21, 17))
,将(21,13)
和(21,17)
单元合并
table.cell(22, 3).merge(table.cell(30, 17))
,将(22,3)
和(30,17)
单元合并
block_6 = table.rows[15].cells
,获得第六块对象,第六块是从第15行开始的,故通过table.rows[15].cells
来进行获取
block_6[0].add_paragraph('测试结果\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
,第六块对象是block_6
,需要在第0
列出添加内容
接着添加图片
picture_origin = table.cell(15, 3).paragraphs[0].add_run()
,在(15,3)
出添加一个文本块
origin = picture_origin.add_picture("./1.jpg")
,加入图片
origin.height = Cm(3.83)
,设置图片高度
origin.width = Cm(3.83)
,设置图片宽度
picture_predict = table.cell(15, 8).paragraphs[0].add_run()
,在(15,8)
出添加一个文本块
predict = picture_predict.add_picture("./2.jpg")
,加入图片
predict.height = Cm(3.83)
,设置图片高度
predict.width = Cm(3.83)
,设置图片宽度
picture_statistics = table.cell(15, 13).paragraphs[0].add_run()
,在(15,13)
出添加一个文本块
statistics = picture_statistics.add_picture("./3.jpg")
,加入图片
statistics.height = Cm(3.83)
,设置图片高度
statistics.width = Cm(3.83)
,设置图片宽度
两行字
block_6_1 = table.rows[21].cells
block_6_1[3].add_paragraph('origin').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_1[8].add_paragraph('predict').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_1[13].add_paragraph('statistics').alignment = WD_ALIGN_PARAGRAPH.CENTER
最后一个文本框
block_6_2 = table.rows[22].cells
block_6_2[3].add_paragraph('制作不易,点个赞呗').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_2[3].add_paragraph('制作不易,点个赞呗').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_2[3].add_paragraph('制作不易,点个赞呗').alignment = WD_ALIGN_PARAGRAPH.CENTER
最终结果
添加表格完整代码
#添加表格
table = document.add_table(rows=32, cols=16, style='Table Grid')
table.autofit = False
table.columns[0].width = Inches(0.49)
table.cell(0, 0).merge(table.cell(2, 2))
table.cell(0, 3).merge(table.cell(2, 15))
row_0 = table.rows[0].cells
row_0[0].add_paragraph('产品名称\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
table.cell(3, 0).merge(table.cell(5, 2))
table.cell(3, 3).merge(table.cell(5, 7))
table.cell(3, 8).merge(table.cell(5, 10))
table.cell(3, 11).merge(table.cell(5, 15))
row_1 = table.rows[3].cells
row_1[0].add_paragraph('测试部门\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
row_1[8].add_paragraph('检验类别\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
table.cell(6, 0).merge(table.cell(8, 2))
table.cell(6, 3).merge(table.cell(8, 7))
table.cell(6, 8).merge(table.cell(8, 10))
table.cell(6, 11).merge(table.cell(8, 15))
row_2 = table.rows[6].cells
row_2[0].add_paragraph('生产单位\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
row_2[8].add_paragraph('样品数量\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
table.cell(9, 0).merge(table.cell(11, 2))
table.cell(9, 3).merge(table.cell(11, 7))
table.cell(9, 8).merge(table.cell(11, 10))
table.cell(9, 11).merge(table.cell(11, 15))
row_3 = table.rows[9].cells
row_3[0].add_paragraph('测试仪器\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
row_3[8].add_paragraph('样品等级\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
table.cell(12, 0).merge(table.cell(31, 2))
table.cell(12, 3).merge(table.cell(31, 15))
row_4 = table.rows[12].cells
row_4[0].add_paragraph('测试结果\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
五、完整代码
from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
from PySide2.QtGui import QIcon
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches,Cm,Pt
class test_word():
def __init__(self):
# 从文件中加载UI定义
# 从 UI 定义中动态 创建一个相应的窗口对象
# 注意:里面的控件对象也成为窗口对象的属性了
# 比如 self.ui.button , self.ui.textEdit
self.ui = QUiLoader().load('word_test.ui') # 这里的参数为ui的路径,对这个ui文件创建对象ui
"""
对某个控件进行操作会产生一个signal,常通过slot来进行处理signal
slot就是通过clicked.connect来绑定某个函数,这个函数用于处理signal
"""
self.output_size = 320
def window_init(self):
self.ui.pushButton.clicked.connect(self.word)
def word(self):
print("正在生成word检测报告...")
name = "yanyu"
product_name = "新型隐身作战服"
testing_department = "西安工程大学"
test_category = "棉织物"
production_unit = "咸阳际华新三零"
number_of_samples = "1张"
sample_price = "512.32 $"
test_instrument = "万能耐磨仪"
sample_grade = "3级"
document = Document()
document.styles['Normal'].font.name = u'宋体'
document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
#添加标题
title = document.add_heading(u'陕西省功能面料重点实验室', 0) #0级标题
# 标题居中
title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
#添加段落1
p = document.add_paragraph()
p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER #添加的段落都居中
r = p.add_run('织物起球等级检测报告')
r.font.size = Pt(24)
r.bold = True
# 添加段落2
p1 = document.add_paragraph()
p1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER # 添加的段落都居中
r1 = p1.add_run('author:yanyu')
r1.font.size = Pt(12)
r1.bold = True
#添加表格
table = document.add_table(rows=31, cols=18, style='Table Grid')
table.autofit = False
table.columns[0].width = Inches(0.49)
# 第一块
table.cell(0, 0).merge(table.cell(2, 2))
table.cell(0, 3).merge(table.cell(2, 17))
block_1 = table.rows[0].cells
block_1[0].add_paragraph('产品名称\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_1[3].add_paragraph(product_name).alignment = WD_ALIGN_PARAGRAPH.CENTER
# 第二块
table.cell(3, 0).merge(table.cell(5, 2))
table.cell(3, 3).merge(table.cell(5, 8))
table.cell(3, 9).merge(table.cell(5, 11))
table.cell(3, 12).merge(table.cell(5, 17))
block_2 = table.rows[3].cells
block_2[0].add_paragraph('测试部门\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_2[3].add_paragraph(testing_department).alignment = WD_ALIGN_PARAGRAPH.CENTER
block_2[9].add_paragraph('检验类别\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_2[12].add_paragraph(test_category).alignment = WD_ALIGN_PARAGRAPH.CENTER
# 第三块
table.cell(6, 0).merge(table.cell(8, 2))
table.cell(6, 3).merge(table.cell(8, 8))
table.cell(6, 9).merge(table.cell(8, 11))
table.cell(6, 12).merge(table.cell(8, 17))
block_3 = table.rows[6].cells
block_3[0].add_paragraph('生产单位\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_3[3].add_paragraph(production_unit).alignment = WD_ALIGN_PARAGRAPH.CENTER
block_3[9].add_paragraph('样品数量\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_3[12].add_paragraph(number_of_samples).alignment = WD_ALIGN_PARAGRAPH.CENTER
# 第四块
table.cell(9, 0).merge(table.cell(11, 2))
table.cell(9, 3).merge(table.cell(11, 8))
table.cell(9, 9).merge(table.cell(11, 11))
table.cell(9, 12).merge(table.cell(11, 17))
block_4 = table.rows[9].cells
block_4[0].add_paragraph('测试仪器\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_4[3].add_paragraph(test_instrument).alignment = WD_ALIGN_PARAGRAPH.CENTER
block_4[9].add_paragraph('样品价格\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_4[12].add_paragraph(sample_price).alignment = WD_ALIGN_PARAGRAPH.CENTER
# 第五块
table.cell(12, 0).merge(table.cell(14, 2))
table.cell(12, 3).merge(table.cell(14, 17))
block_5 = table.rows[12].cells
block_5[0].add_paragraph('最终评定等级结果\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_5[3].add_paragraph(sample_grade).alignment = WD_ALIGN_PARAGRAPH.CENTER
# 第六块
table.cell(15, 0).merge(table.cell(30, 2))
table.cell(15, 3).merge(table.cell(20, 7))
table.cell(15, 8).merge(table.cell(20, 12))
table.cell(15, 13).merge(table.cell(20, 17))
table.cell(21, 3).merge(table.cell(21, 7))
table.cell(21, 8).merge(table.cell(21, 12))
table.cell(21, 13).merge(table.cell(21, 17))
table.cell(22, 3).merge(table.cell(30, 17))
block_6 = table.rows[15].cells
block_6[0].add_paragraph('测试结果\n').alignment = WD_ALIGN_PARAGRAPH.CENTER
picture_origin = table.cell(15, 3).paragraphs[0].add_run()
origin = picture_origin.add_picture("./1.jpg")
origin.height = Cm(3.83)
origin.width = Cm(3.83)
picture_predict = table.cell(15, 8).paragraphs[0].add_run()
predict = picture_predict.add_picture("./2.jpg")
predict.height = Cm(3.83)
predict.width = Cm(3.83)
picture_statistics = table.cell(15, 13).paragraphs[0].add_run()
statistics = picture_statistics.add_picture("./3.jpg")
statistics.height = Cm(3.83)
statistics.width = Cm(3.83)
block_6_1 = table.rows[21].cells
block_6_1[3].add_paragraph('origin').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_1[8].add_paragraph('predict').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_1[13].add_paragraph('statistics').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_2 = table.rows[22].cells
block_6_2[3].add_paragraph('制作不易,点个赞呗').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_2[3].add_paragraph('制作不易,点个赞呗').alignment = WD_ALIGN_PARAGRAPH.CENTER
block_6_2[3].add_paragraph('制作不易,点个赞呗').alignment = WD_ALIGN_PARAGRAPH.CENTER
document.save(name+'finish.docx')
print("检测报告生成完毕")
if __name__=="__main__":
app = QApplication([])
app.setWindowIcon(QIcon('./yyy.png')) #logo图片位置
gui = test_word() #初始化
gui.window_init()
gui.ui.show() #将窗口控件显示在屏幕上
app.exit(app.exec_())
最终效果如下: