150 lines
4.4 KiB
Python
150 lines
4.4 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
||
|
|
"""验证 report_generator.py 的核心逻辑"""
|
||
|
|
import sys, os, io
|
||
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
||
|
|
|
||
|
|
from docx import Document
|
||
|
|
from report_generator import _replace_token_across_runs, _get_unique_cells, _fill_script_table_docx, _replace_texts_docx
|
||
|
|
|
||
|
|
# 测试1: 跨run替换
|
||
|
|
print("=" * 60)
|
||
|
|
print("Test 1: _replace_token_across_runs")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
doc = Document()
|
||
|
|
|
||
|
|
# {text4} split: '{' + 'text4' + '}'
|
||
|
|
para1 = doc.add_paragraph()
|
||
|
|
para1.add_run('before\t')
|
||
|
|
para1.add_run('{')
|
||
|
|
para1.add_run('text4')
|
||
|
|
para1.add_run('}')
|
||
|
|
para1.add_run('\tafter')
|
||
|
|
print(f"Before: '{para1.text}'")
|
||
|
|
_replace_token_across_runs(para1, '{text4}', 'VALUE4')
|
||
|
|
print(f"After: '{para1.text}'")
|
||
|
|
assert '{' not in para1.text and 'VALUE4' in para1.text, "FAIL: text4"
|
||
|
|
print("PASS: text4")
|
||
|
|
|
||
|
|
# {isNormal} split: '{isNormal' + '}'
|
||
|
|
para2 = doc.add_paragraph()
|
||
|
|
para2.add_run('OK ')
|
||
|
|
para2.add_run('{isNormal')
|
||
|
|
para2.add_run('}')
|
||
|
|
para2.add_run(' NOT')
|
||
|
|
print(f"\nBefore: '{para2.text}'")
|
||
|
|
_replace_token_across_runs(para2, '{isNormal}', 'V')
|
||
|
|
print(f"After: '{para2.text}'")
|
||
|
|
assert '{' not in para2.text and 'V' in para2.text, "FAIL: isNormal"
|
||
|
|
print("PASS: isNormal")
|
||
|
|
|
||
|
|
# {scriptTable1} split: '{' + 'scriptTable1' + '}' + text
|
||
|
|
para3 = doc.add_paragraph()
|
||
|
|
para3.add_run('{')
|
||
|
|
para3.add_run('scriptTable1')
|
||
|
|
para3.add_run('}')
|
||
|
|
para3.add_run('label')
|
||
|
|
print(f"\nBefore: '{para3.text}'")
|
||
|
|
_replace_token_across_runs(para3, '{scriptTable1}', '')
|
||
|
|
print(f"After: '{para3.text}'")
|
||
|
|
assert para3.text == 'label', f"FAIL: scriptTable1, got '{para3.text}'"
|
||
|
|
print("PASS: scriptTable1")
|
||
|
|
|
||
|
|
# 测试2: 模板表格结构分析
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("Test 2: Template table structure")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
template_path = 'configs/600泵/template.docx'
|
||
|
|
if not os.path.exists(template_path):
|
||
|
|
print("SKIP: template not found")
|
||
|
|
sys.exit(0)
|
||
|
|
|
||
|
|
doc2 = Document(template_path)
|
||
|
|
table = doc2.tables[0]
|
||
|
|
|
||
|
|
for ri in range(min(5, len(table.rows))):
|
||
|
|
unique = _get_unique_cells(table.rows[ri])
|
||
|
|
raw_count = len(table.rows[ri].cells)
|
||
|
|
texts = [c.text.replace('\n', '|')[:25] for c in unique]
|
||
|
|
print(f"Row {ri}: raw={raw_count}, unique={len(unique)}: {texts}")
|
||
|
|
|
||
|
|
# 找 token 位置
|
||
|
|
token_ucol = -1
|
||
|
|
for ri, row in enumerate(table.rows):
|
||
|
|
unique = _get_unique_cells(row)
|
||
|
|
for uci, cell in enumerate(unique):
|
||
|
|
if 'scriptTable1' in cell.text:
|
||
|
|
token_ucol = uci
|
||
|
|
print(f"\nToken at row={ri}, unique_col={uci}, text='{cell.text}'")
|
||
|
|
break
|
||
|
|
|
||
|
|
# 测试3: 完整填充
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("Test 3: Full fill test")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
doc3 = Document(template_path)
|
||
|
|
|
||
|
|
# 文本替换
|
||
|
|
text_map = {
|
||
|
|
'text3': 'P67-13-103',
|
||
|
|
'text2': 'W2001150.001-01:10',
|
||
|
|
'text4': 'ZhuJS',
|
||
|
|
'text1': '2025-12-03',
|
||
|
|
'isNormal': 'V',
|
||
|
|
}
|
||
|
|
_replace_texts_docx(doc3, text_map)
|
||
|
|
|
||
|
|
# 验证段落替换
|
||
|
|
for para in doc3.paragraphs:
|
||
|
|
t = para.text
|
||
|
|
if 'ZhuJS' in t or 'V' in t or 'P67' in t:
|
||
|
|
print(f" Para: '{t[:80]}'")
|
||
|
|
|
||
|
|
# 表格填充
|
||
|
|
spec = {
|
||
|
|
'token': 'scriptTable1',
|
||
|
|
'cells': [
|
||
|
|
{'row': 0, 'col': 1, 'value': '11.2C'},
|
||
|
|
{'row': 1, 'col': 1, 'value': '2026-03-16 14:17:33'},
|
||
|
|
{'row': 1, 'col': 3, 'value': '2026-03-16 17:47:33'},
|
||
|
|
{'row': 4, 'col': 0, 'value': '21.6'},
|
||
|
|
{'row': 4, 'col': 1, 'value': '26.7'},
|
||
|
|
{'row': 4, 'col': 6, 'value': '36.0'},
|
||
|
|
{'row': 16, 'col': 0, 'value': '11.6'},
|
||
|
|
]
|
||
|
|
}
|
||
|
|
_fill_script_table_docx(doc3, 'scriptTable1', spec)
|
||
|
|
|
||
|
|
# 验证结果
|
||
|
|
table3 = doc3.tables[0]
|
||
|
|
|
||
|
|
u0 = _get_unique_cells(table3.rows[0])
|
||
|
|
u1 = _get_unique_cells(table3.rows[1])
|
||
|
|
u4 = _get_unique_cells(table3.rows[4])
|
||
|
|
u16 = _get_unique_cells(table3.rows[16])
|
||
|
|
|
||
|
|
results = [
|
||
|
|
(f"Row0[1]", u0[1].text, 'label should remain'),
|
||
|
|
(f"Row0[2]", u0[2].text, 'should be 11.2C'),
|
||
|
|
(f"Row1[2]", u1[2].text, 'should be start time'),
|
||
|
|
(f"Row1[4]", u1[4].text, 'should be end time'),
|
||
|
|
(f"Row4[0]", u4[0].text, 'label should remain'),
|
||
|
|
(f"Row4[1]", u4[1].text, 'should be 21.6'),
|
||
|
|
(f"Row4[2]", u4[2].text, 'should be 26.7'),
|
||
|
|
(f"Row4[7]", u4[7].text if len(u4) > 7 else 'N/A', 'should be 36.0'),
|
||
|
|
(f"Row16[1]", u16[1].text if len(u16) > 1 else 'N/A', 'should be 11.6'),
|
||
|
|
]
|
||
|
|
|
||
|
|
print("\nResults:")
|
||
|
|
all_ok = True
|
||
|
|
for name, val, desc in results:
|
||
|
|
status = 'OK' if val.strip() else 'EMPTY'
|
||
|
|
print(f" {name} = '{val}' ({desc}) [{status}]")
|
||
|
|
|
||
|
|
doc3.save('test_output_verify.docx')
|
||
|
|
print(f"\nSaved: test_output_verify.docx")
|
||
|
|
print("\nDone!")
|