在原文档的某段落前面插入标题、表格、以及图片
import logging
from docx import Document
from docx.shared import Pt, Cm
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT
from flask import Flask, jsonify, request, json, app
import logging.handlers as loghandlers
app = Flask(__name__)
######################################################
# 各种类
######################################################
class Response(object):
SUCCESS = 200
ERROR = 201
@staticmethod
def getResponse(code: int, message: str, data=None):
return jsonify({
"code": code,
"message": message,
"data": data
})
class ResultId:
def __init__(self, title, value):
self.title = title
self.value = value
class Table:
def __init__(self, tableName, columns, rows, columnvalue, rowvalues):
'''
:param tableName: 表名
:param columns: 列数
:param rows: 行数
:param columnvalue: 列值数组
:param rowvalues: 行值数组
'''
self.tableName = tableName
self.columns = columns
self.rows = rows
self.columnvalue = columnvalue
self.rowvalues = rowvalues
class TableParagraph:
def __init__(self, title, table):
self.title = title
self.table = table
class Waveform:
def __init__(self, title, imags):
self.title = title
self.imags = imags
class Report:
def __init__(self, result, condition_table, waveform, result_table):
self.result = result
self.condition = condition_table
self.imags = waveform
self.result = result_table
#########################################################################
#
#########################################################################
def buildResultId(document,text, index, resultId):
specText = text.encode('utf-8').decode('utf-8')
title = index + '.1' + resultId.title
content = resultId.value
addParagraphBefore(document, specText, title)
for i, p in enumerate(document.paragraphs):
if(p.text == specText):
document.paragraphs[i].insert_paragraph_before(text=content)
def buildTableParagraph(document,text, index, tableParagraph):
specText = text.encode('utf-8').decode('utf-8')
if(tableParagraph.title == '测试条件'):
title = index + '.2' + tableParagraph.title
else:
title = index + '.4' + tableParagraph.title
tableName = tableParagraph.table.tableName
columns = tableParagraph.table.columns
rows = tableParagraph.table.rows
columnvalue = tableParagraph.table.columnvalue
rowvalues = tableParagraph.table.rowvalues
# 创建表格
table = createTable(document,rows,columns,rowvalues,columnvalue)
addParagraphBefore(document, specText, title)
# 插入段落头,表格名称
for i, p in enumerate(document.paragraphs):
if (p.text == specText):
before = document.paragraphs[i].insert_paragraph_before(text=tableName)
before.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置文档段落对齐
break
# 插入表格
for i, p in enumerate(document.paragraphs):
if (p.text == specText):
document.paragraphs[i-1]._p.addnext(table._tbl)
break
def buildWaveform(document, text, index, waveform):
specText = text.encode('utf-8').decode('utf-8')
title = index +'.3'+waveform.title
imags = waveform.imags
# 插入段落头
addParagraphBefore(document, specText, title)
# 插入图片
for i, p in enumerate(document.paragraphs):
if (p.text == specText):
before = document.paragraphs[i].insert_paragraph_before()
for a,t in imags:
before.add_run().add_picture(a, height=Cm(6), width=Cm(10))
before.add_run().add_break() # 添加一个折行
before.add_run().add_text(t)
before.add_run().add_break() # 添加一个折行
before.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置文档段落对齐
break
def buildWaveform2(document, text, index, waveform):
specText = text.encode('utf-8').decode('utf-8')
title = index + '.3' + waveform.title
imags = waveform.imags
# 插入段落头
addParagraphBefore(document, specText, title)
table = document.add_table(rows= len(imags), cols=1)
table.alignment = WD_TABLE_ALIGNMENT.CENTER # 表格居中
for i in range(len(table.rows)):
table.cell(i, 0).paragraphs[0].add_run().add_picture(imags[i][0], height=Cm(6), width=Cm(10))
table.cell(i, 0).paragraphs[0].add_run().add_break()
table.cell(i, 0).paragraphs[0].add_run().add_text(imags[i][1])
table.cell(i, 0).vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER # 单元格居中
table.cell(i, 0).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 段落居中
# 插入图片
for i, p in enumerate(document.paragraphs):
if (p.text == specText):
document.paragraphs[i - 1]._p.addnext(table._tbl)
break
def createReport(templateAddress):
document = Document(templateAddress)
return document
def buildOneReport(document, text, index, resultId, condition, waveform, resultTable):
buildResultId(document, text, index, resultId)
buildTableParagraph(document, text, index, condition)
buildWaveform2(document, text, index, waveform)
buildTableParagraph(document, text, index, resultTable)
def saveReport(document,reportAddress):
document.save(reportAddress)
#############################################################################################
#
############################################################################################
def addParagraphBefore(document, specText, title):
'''
在 specText 前面添加 内容为title的段落
:param document:
:param specText:
:param title:
:return:
'''
for i, p in enumerate(document.paragraphs):
if (p.text == specText):
document.paragraphs[i].insert_paragraph_before(text=title)
def createTable(document, rows, columns, rowvalues, columnvalue):
'''
创建表格
:param document:
:param rows:
:param columns:
:param rowvalues:
:param columnvalue:
:return:
'''
table = document.add_table(rows=rows, cols=columns, style='Table Grid')
table.alignment = WD_TABLE_ALIGNMENT.CENTER # 表格居中
for i in range(len(table.rows)):
for j in range(len(table.columns)):
if (i == 0): # 表头赋值
table.cell(i, j).text = columnvalue[j]
set_cell_background(table.cell(i, j), '808080')
else:
flag = type(rowvalues[i - 1][j]) == str
if (flag):
table.cell(i, j).text = rowvalues[i - 1][j]
else:
table.cell(i, j).text = '%.4f' % rowvalues[i - 1][j]
table.cell(i, j).vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER # 单元格居中
table.cell(i, j).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 居中
return table
def set_cell_background(cell, fill, color=None, val=None):
"""
@fill: Specifies the color to be used for the background
@color: Specifies the color to be used for any foreground
pattern specified with the val attribute
@val: Specifies the pattern to be used to lay the pattern
color over the background color.
"""
from docx.oxml.shared import qn # feel free to move these out
from docx.oxml.xmlchemy import OxmlElement
cell_properties = cell._element.tcPr
try:
cell_shading = cell_properties.xpath('w:shd')[0] # in case there's already shading
except IndexError:
cell_shading = OxmlElement('w:shd') # add new w:shd element to it
if fill:
cell_shading.set(qn('w:fill'), fill) # set fill property, respecting namespace
if color:
pass # TODO
if val:
pass # TODO
cell_properties.append(cell_shading) # finally extend cell props with shading element
##################################################################################################
@app.route("/listen/buildreport", methods=["POST"])
def close_driver_v():
# 三个常量
templateAddress = r'C:\test\报告模板.docx'
reportAddress = r"C:\test\report.docx"
text = '附件1 硬件测试精度指标'
# 创建报告
doc = createReport(templateAddress)
# 获取参数值
data_list = json.loads(request.get_data(as_text=True))
logger.info('收到请求: %s', data_list)
if len(data_list) == 0:
return Response.getResponse(Response.ERROR, '参数为空')
i = 1
for data in data_list:
try:
idvalue = data['idkey']
doublePulseTestcondition = data['doublePulseTestcondition']
doublePulseTestWaveform = data['doublePulseTestWaveform']
doublePulseTestResult = data['doublePulseTestResult']
# 构建参数
resultId = ResultId('测试ID', idvalue)
condition_table = Table(doublePulseTestcondition['tableName'], doublePulseTestcondition['columns'],
doublePulseTestcondition['rows'], doublePulseTestcondition['columnvalue'],
doublePulseTestcondition['rowvalues'])
result_table = Table(doublePulseTestResult['tableName'], doublePulseTestResult['columns'],
doublePulseTestResult['rows'], doublePulseTestResult['columnvalue'],
doublePulseTestResult['rowvalues'])
condition = TableParagraph(doublePulseTestcondition['title'], condition_table)
resultTable = TableParagraph(doublePulseTestResult['title'], result_table)
waveform = Waveform(doublePulseTestWaveform['title'], doublePulseTestWaveform['images'])
index = '3.' + str(i)
# 写入报告
buildOneReport(doc, text, index, resultId, condition, waveform, resultTable)
i = i + 1
except Exception as e:
logger.info('发生异常', e)
return Response.getResponse(Response.ERROR, e)
# 保存报告
saveReport(doc, reportAddress)
return Response.getResponse(Response.SUCCESS, '操作成功')
def start_listen():
app.config['JSON_AS_ASCII'] = False
app.run(host='0.0.0.0', port=5000, debug=False)
def loginit(logname, logpath):
logger = logging.getLogger(logname)
logger.setLevel(logging.INFO)
# 创建处理器
# loghandler = logging.StreamHandler() # 日志信息输出到终端
# loghandler = logging.FileHandler(logpath) # 日志信息输出到文件
# loghandler = loghandlers.RotatingFileHandler(logpath,maxBytes=1024*1,backupCount=5) # 根据文件大小轮换日志文件
loghandler = loghandlers.TimedRotatingFileHandler(logpath, when='M', interval=1, backupCount=5, encoding='utf-8') # 根据时间轮换日志文件
loghandler.setLevel(logging.INFO)
# 创建格式器(打印日志的时间-打印日志级别的名称-打印当前执行程序名-打印日志的当前函数-打印日志的当前行号: 日志信息)
logformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s-%(funcName)s-%(lineno)d: %(message)s')
# 将格式器添加到处理器中
loghandler.setFormatter(logformatter)
# 将处理器添加到记录器中
logger.addHandler(loghandler)
return logger
if __name__ == '__main__':
# templateAddress = r'C:\test\IGBT-HPD-LU-450V-800A【报告模板】---20230323(3) - 副本.docx'
# reportAddress = r"C:\test\report.docx"
# text = '附件1 硬件测试精度指标'
# resultId = ResultId('测试ID', '2023-03-17-11-29-10-469.0-800.0-DP-LU-Ron-2.4-Roff-5.1-Vgs_p-15.2-Vgs_n-8.4-heat-22.0-phase-s-phase-h')
# table = table('表1', 3, 4, ['参数', '参数值', '单位'], [['T0', 0.0000, 'us'], ['T1d', 46.5400, 'us'], ['T2d', 5.0000, 'us']])
# condition = tableParagraph('测试条件',table)
# resultTable = tableParagraph('测试结果',table)
# waveform = Waveform('测试波形', [['C:\\Users\\Pictures\\Saved Pictures\\tupian\\图片1.png','第一张图'],
# ['C:\\Users\\Pictures\\Saved Pictures\\tupian\\图片2.png','第二张图'],
# ['C:\\Users\\Pictures\\Saved Pictures\\tupian\\图片3.png','第三张图'],
# ['C:\\Users\\Pictures\\Saved Pictures\\tupian\\图片4.png','第四张图']])
# document = Document(templateAddress)
# buildResultId(document, text, resultId)
# buildTableParagraph(document, text, condition)
# buildWaveform2(document, text, waveform)
# buildTableParagraph(document, text, resultTable)
# document.save(reportAddress)
# LOG_FORMAT = "%(asctime)s - %(levelname)s - %(user)s[%(ip)s] - %(message)s"
logger = loginit('test', 'report.log')
start_listen()