修复归档路径错误,添加公式单元格缓存值支持
- fill 命令生成 Excel 后正确移动到归档目录而非保留在报销输出 - 新增 build_formula_cached_values 支持填充公式单元格的缓存值 - 完成后清理报销输出目录避免残留临时文件 - .gitignore 移除 *.json 使 analyzed_result.json 可被追踪
This commit is contained in:
parent
240d8534fd
commit
04e1592fe3
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,7 +3,6 @@
|
|||
*.jpeg
|
||||
*.png
|
||||
*.txt
|
||||
*.json
|
||||
*.xlsx
|
||||
报销输出/
|
||||
__pycache__/
|
||||
|
|
|
|||
49
差旅报销.py
49
差旅报销.py
|
|
@ -221,10 +221,11 @@ def command_fill(args):
|
|||
output_dir = json_path.parent
|
||||
archive_dir = output_dir.parent if output_dir.name == OUTPUT_DIR_NAME else Path(".")
|
||||
|
||||
output_file = fill_template(result, output_dir)
|
||||
output_file = fill_template(result, archive_dir)
|
||||
verify_output(output_file, result)
|
||||
final_archive_dir = finalize_archive_dir(archive_dir, result)
|
||||
final_output_file = final_archive_dir / OUTPUT_DIR_NAME / output_file.name
|
||||
final_output_file = final_archive_dir / output_file.name
|
||||
cleanup_output_dir(final_archive_dir / OUTPUT_DIR_NAME)
|
||||
cleanup_pycache()
|
||||
|
||||
print(f"完成:{final_output_file}")
|
||||
|
|
@ -314,7 +315,7 @@ def fill_template(result, output_dir):
|
|||
output_file = output_dir / build_output_filename(meta)
|
||||
|
||||
shutil.copy(TEMPLATE_FILE, output_file)
|
||||
update_xlsx_cells(output_file, build_cell_values(result))
|
||||
update_xlsx_cells(output_file, build_cell_values(result), build_formula_cached_values(result))
|
||||
return output_file
|
||||
|
||||
|
||||
|
|
@ -327,6 +328,7 @@ def build_cell_values(result):
|
|||
"B6": f'{meta["出发地"]}-{meta["目的地"]}',
|
||||
"C6": f'{meta["出差天数"]}天',
|
||||
"D6": meta["出行方式"],
|
||||
"F6": meta["出差天数"],
|
||||
"H6": expenses["住宿"]["单据张数"],
|
||||
"I6": expenses["住宿"]["金额"],
|
||||
"H7": expenses["饮食"]["单据张数"],
|
||||
|
|
@ -338,7 +340,20 @@ def build_cell_values(result):
|
|||
}
|
||||
|
||||
|
||||
def update_xlsx_cells(xlsx_path, cell_values):
|
||||
def build_formula_cached_values(result):
|
||||
summary = result["summary"]
|
||||
advance = summary["预借差旅费"]
|
||||
total = summary["报销总额"]
|
||||
return {
|
||||
"H2": summary["附件总张数"],
|
||||
"F9": result["meta"]["出差天数"],
|
||||
"C10": total,
|
||||
"H10": max(total - advance, 0),
|
||||
"H11": max(advance - total, 0),
|
||||
}
|
||||
|
||||
|
||||
def update_xlsx_cells(xlsx_path, cell_values, formula_cached_values):
|
||||
temp_file = NamedTemporaryFile(delete=False, suffix=".xlsx", dir=xlsx_path.parent)
|
||||
temp_path = Path(temp_file.name)
|
||||
temp_file.close()
|
||||
|
|
@ -349,7 +364,7 @@ def update_xlsx_cells(xlsx_path, cell_values):
|
|||
for item in source.infolist():
|
||||
data = source.read(item.filename)
|
||||
if item.filename == "xl/worksheets/sheet1.xml":
|
||||
data = update_sheet_xml(data, cell_values)
|
||||
data = update_sheet_xml(data, cell_values, formula_cached_values)
|
||||
target.writestr(item, data)
|
||||
temp_path.replace(xlsx_path)
|
||||
except Exception:
|
||||
|
|
@ -357,7 +372,7 @@ def update_xlsx_cells(xlsx_path, cell_values):
|
|||
raise
|
||||
|
||||
|
||||
def update_sheet_xml(sheet_xml, cell_values):
|
||||
def update_sheet_xml(sheet_xml, cell_values, formula_cached_values):
|
||||
namespace = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
ET.register_namespace("", namespace)
|
||||
root = ET.fromstring(sheet_xml)
|
||||
|
|
@ -366,6 +381,11 @@ def update_sheet_xml(sheet_xml, cell_values):
|
|||
if cell is None:
|
||||
raise SystemExit(f"模板缺少单元格:{cell_ref}")
|
||||
set_cell_xml_value(cell, value, namespace)
|
||||
for cell_ref, value in formula_cached_values.items():
|
||||
cell = root.find(f".//{{{namespace}}}c[@r='{cell_ref}']")
|
||||
if cell is None:
|
||||
raise SystemExit(f"模板缺少单元格:{cell_ref}")
|
||||
set_formula_cached_value(cell, value, namespace)
|
||||
return ET.tostring(root, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
|
||||
|
|
@ -385,6 +405,18 @@ def set_cell_xml_value(cell, value, namespace):
|
|||
text_node.text = str(value)
|
||||
|
||||
|
||||
def set_formula_cached_value(cell, value, namespace):
|
||||
cell.attrib.pop("t", None)
|
||||
value_node = None
|
||||
for child in cell:
|
||||
if child.tag == f"{{{namespace}}}v":
|
||||
value_node = child
|
||||
break
|
||||
if value_node is None:
|
||||
value_node = ET.SubElement(cell, f"{{{namespace}}}v")
|
||||
value_node.text = format_number_for_excel(value)
|
||||
|
||||
|
||||
def format_number_for_excel(value):
|
||||
if isinstance(value, int):
|
||||
return str(value)
|
||||
|
|
@ -415,6 +447,11 @@ def unique_archive_dir(path):
|
|||
index += 1
|
||||
|
||||
|
||||
def cleanup_output_dir(output_dir):
|
||||
if output_dir.exists():
|
||||
shutil.rmtree(output_dir)
|
||||
|
||||
|
||||
def cleanup_pycache():
|
||||
pycache_dir = Path("__pycache__")
|
||||
if pycache_dir.exists():
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user