147 lines
6.8 KiB
Python
147 lines
6.8 KiB
Python
|
|
from PyQt5 import QtCore
|
|||
|
|
from PyQt5.QtCore import pyqtSignal
|
|||
|
|
from pathlib import *
|
|||
|
|
from PyQt5.QtWidgets import QMessageBox
|
|||
|
|
from docxtpl import DocxTemplate, InlineImage
|
|||
|
|
from docx import Document
|
|||
|
|
from docx.table import Table
|
|||
|
|
from docx.text.paragraph import Paragraph
|
|||
|
|
import io
|
|||
|
|
|
|||
|
|
class create_FPGA_JtoS(QtCore.QThread):
|
|||
|
|
sin_out = pyqtSignal(str)
|
|||
|
|
|
|||
|
|
def __init__(self, parent):
|
|||
|
|
super().__init__()
|
|||
|
|
self.parent = parent
|
|||
|
|
|
|||
|
|
def run(self):
|
|||
|
|
self.sin_out.emit("进入测试记录转说明线程......")
|
|||
|
|
self.sin_out.emit("开始转换......")
|
|||
|
|
# 如果没有选择文件路径则退出
|
|||
|
|
if not self.parent.open_file_name:
|
|||
|
|
self.sin_out.emit('nofile')
|
|||
|
|
self.parent.tabWidget.setEnabled(True)
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 打开模板文件进行渲染,然后就是用docxtpl生成用例
|
|||
|
|
try:
|
|||
|
|
tpl_path = Path.cwd() / "need" / "document_templates" / "FPGA记录to说明模板.docx"
|
|||
|
|
self.sin_out.emit('导入模板文件路径为:' + str(tpl_path))
|
|||
|
|
tpl = DocxTemplate(tpl_path) # 模板导入成功
|
|||
|
|
|
|||
|
|
except:
|
|||
|
|
QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
doc = Document(self.parent.open_file_name[0])
|
|||
|
|
self.sin_out.emit('已识别到FPGA测试记录文件...')
|
|||
|
|
except:
|
|||
|
|
self.sin_out.emit('open failed:选择的文档')
|
|||
|
|
self.parent.tabWidget.setEnabled(True)
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
self.sin_out.emit('复制测试说明文档模板到本程序所在目录...')
|
|||
|
|
curpath = Path.cwd() / 'need'
|
|||
|
|
shuoming_path_tmp = curpath / 'document_templates' / 'FPGA记录to说明模板.docx'
|
|||
|
|
print(shuoming_path_tmp)
|
|||
|
|
if shuoming_path_tmp.is_file():
|
|||
|
|
self.sin_out.emit('已检测到有说明模板文件...')
|
|||
|
|
else:
|
|||
|
|
self.sin_out.emit('open failed:选择的文档')
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 获取表格数量
|
|||
|
|
tables = doc.tables
|
|||
|
|
tb_count = len(tables)
|
|||
|
|
self.sin_out.emit('total:' + str(tb_count))
|
|||
|
|
# 创建一个字典来储存单个用例
|
|||
|
|
data_list = []
|
|||
|
|
table_index = 1
|
|||
|
|
# 获取表格数量
|
|||
|
|
for ele in doc._element.body.iter():
|
|||
|
|
data = {'type': ''}
|
|||
|
|
if ele.tag.endswith('}p'):
|
|||
|
|
elePstyle = ele.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}pStyle')
|
|||
|
|
if len(elePstyle) >= 1:
|
|||
|
|
parag = Paragraph(ele, doc)
|
|||
|
|
if parag.style.name.startswith("Heading") or parag.style.name.startswith("标题"):
|
|||
|
|
rank = parag.style.name.split(" ")[-1]
|
|||
|
|
text = parag.text
|
|||
|
|
if text == "" or text.startswith("文档齐套性审查单") \
|
|||
|
|
or text.startswith("软件研制任务书审查单") \
|
|||
|
|
or text.startswith("附录") \
|
|||
|
|
or text.startswith("附件") \
|
|||
|
|
or text.startswith("需求文档审查单"):
|
|||
|
|
pass
|
|||
|
|
else:
|
|||
|
|
data['type'] = rank
|
|||
|
|
data['title'] = text
|
|||
|
|
data_list.append(data)
|
|||
|
|
elif ele.tag.endswith('}tbl'):
|
|||
|
|
data = {'name': '', 'biaoshi': '', 'zhuizong': [], 'zongsu': '', 'init': '', 'qianti': '', 'step': []}
|
|||
|
|
data['type'] = 'table'
|
|||
|
|
table = Table(ele, doc)
|
|||
|
|
if table.cell(0, 0).text == '测试用例名称':
|
|||
|
|
self.sin_out.emit(str(table_index))
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
self.sin_out.emit(str(table_index))
|
|||
|
|
self.sin_out.emit(f'正在处理第{table_index}个表格')
|
|||
|
|
# 1、获取测试用例名称
|
|||
|
|
data['name'] = table.cell(0, 3).text
|
|||
|
|
# 2、获取用例标识
|
|||
|
|
data['biaoshi'] = table.cell(0, 9).text
|
|||
|
|
# 3、获取追踪关系 注意word中换行为\r\x07
|
|||
|
|
temp = table.cell(1, 3)
|
|||
|
|
for tem in temp.paragraphs:
|
|||
|
|
data['zhuizong'].append(tem.text)
|
|||
|
|
# 4、获取综述
|
|||
|
|
data['zongsu'] = table.cell(2, 3).text
|
|||
|
|
# 5、初始化
|
|||
|
|
data['init'] = table.cell(3, 3).text
|
|||
|
|
# 6、获取前提与约束
|
|||
|
|
data['qianti'] = table.cell(4, 3).text
|
|||
|
|
# 7、获取步骤信息-总行数减去12为步骤行数
|
|||
|
|
row_count = len(table.rows)
|
|||
|
|
step_count = row_count - 12
|
|||
|
|
for j in range(step_count):
|
|||
|
|
buzhou = {'shuru': '', 'yuqi': '', 'num': '', 'image': '', 'is_image': '0'}
|
|||
|
|
buzhou['num'] = table.rows[7 + j].cells[0].text
|
|||
|
|
buzhou['shuru'] = table.rows[7 + j].cells[2].text
|
|||
|
|
cel = table.rows[7 + j].cells[2]
|
|||
|
|
if len(
|
|||
|
|
cel._element.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}drawing')
|
|||
|
|
) > 0:
|
|||
|
|
img_ele = cel._element.xpath('.//pic:pic')[0]
|
|||
|
|
embed = img_ele.xpath('.//a:blip/@r:embed')[0]
|
|||
|
|
related_part = doc.part.related_parts[embed]
|
|||
|
|
image = related_part.image
|
|||
|
|
# blob属性就是二进制图片属性
|
|||
|
|
image_bytes = image.blob
|
|||
|
|
buzhou['image'] = InlineImage(tpl, io.BytesIO(image_bytes))
|
|||
|
|
buzhou['is_image'] = '1'
|
|||
|
|
buzhou['yuqi'] = table.rows[7 + j].cells[4].text
|
|||
|
|
data['step'].append(buzhou)
|
|||
|
|
# 8、最后加入data_list
|
|||
|
|
data_list.append(data)
|
|||
|
|
table_index += 1
|
|||
|
|
except:
|
|||
|
|
self.sin_out.emit(f'第{table_index}个表格处理错误!')
|
|||
|
|
table_index += 1
|
|||
|
|
pass
|
|||
|
|
# 开始渲染模板文件
|
|||
|
|
try:
|
|||
|
|
self.sin_out.emit(str(tb_count + 1))
|
|||
|
|
context = {
|
|||
|
|
"tables": data_list,
|
|||
|
|
"renyuan": self.parent.lineEdit_17.text(),
|
|||
|
|
}
|
|||
|
|
tpl.render(context)
|
|||
|
|
tpl.save("FPGA反向生成的说明文档.docx")
|
|||
|
|
self.sin_out.emit('stopsuccess')
|
|||
|
|
except:
|
|||
|
|
self.sin_out.emit('stoperror')
|
|||
|
|
return
|