arm-ka-fixtures/synthgen/templates/build_forms_templates.py
2026-11-13 00:30:31 +04:00

83 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Сборка шаблонов ББ и ОФР в оформлении 1С (`bb_1c.xlsx`, `ofr_1c.xlsx`) из реальных образцов — один раз, результат коммитится.
Запуск из корня worktree:
uv run -q --with openpyxl==3.1.5 python -m synthgen.templates.build_forms_templates [каталог образцов]
Книга образца копируется целиком (шрифты Times New Roman, объединения, рамки, высоты строк, форматы, блок «КОДЫ»,
разрывы страниц, неизменяемые тексты форм 66н). В шаблоне очищено всё, что принадлежит образцу или считается генератором:
- все формулы (итоги, заголовки второй страницы, служебные расчёты) заменены пустыми значениями;
- числа в колонках значений строк с кодами, наименование организации, ИНН, ОКПО, ОКВЭД, ОКОПФ/ОКФС, вид деятельности,
адрес, дата формы, периодные подписи колонок и заголовка, ФИО подписантов;
- ячейки правее последней колонки формы (служебные расчёты автора образца) — значения и оформление.
Генератор (`synthgen.forms_xlsx`) пишет свои значения по кодам строк.
"""
import sys
from pathlib import Path
import openpyxl
from openpyxl.cell.cell import MergedCell
from openpyxl.styles import Alignment, Border, Font, PatternFill
from synthgen import xlsx
SAMPLES = Path("/Users/andrey.epifancev/projects/awp-ca/fixtures/statements-xlsx/mezheninovskaya/2025-Q3")
HERE = Path(__file__).parent
# (файл образца, имя шаблона, последняя колонка формы, колонка кодов, ячейки реквизитов и подписей для очистки)
BUILD = {
"BALANCE": (
"1_Форма1_бух_09.xlsx", "bb_1c.xlsx", 20, 11,
("B3", "G7", "R6", "S6", "T6", "R7", "R8", "G9", "R9", "G10", "R10", "S10", "G13", "M23", "Q23", "S23", "M48", "Q48", "S48",
"Q80", "Q83"),
),
"INCOME": (
"1_Форма2_бух_09.xlsx", "ofr_1c.xlsx", 18, 13,
("B3", "G7", "P6", "Q6", "R6", "P7", "P8", "G9", "P9", "G10", "P10", "Q10", "O14", "Q14", "O36", "Q36", "O49", "O52"),
),
} # fmt: skip
def _is_code(value) -> bool:
return isinstance(value, str) and value.isdigit() and len(value) == 4
def build(kind: str, samples: Path = SAMPLES, out_dir: Path = HERE) -> Path:
sample, name, last_col, code_col, clear = BUILD[kind]
wb = openpyxl.load_workbook(samples / sample)
ws = wb.active
value_cols: set[int] = set()
for row in ws.iter_rows():
for cell in row: # колонки значений: ячейки номеров колонок (строка под «Коды») правее колонки кодов
if cell.value == "Коды" and cell.column == code_col:
value_cols |= {c.column for c in ws[cell.row + 1] if c.value is not None and c.column > code_col}
code_rows = [r for r in range(1, ws.max_row + 1) if _is_code(ws.cell(r, code_col).value)]
for coord in clear:
ws[coord].value = None
for r in code_rows:
for c in value_cols:
cell = ws.cell(r, c)
if not isinstance(cell, MergedCell):
cell.value = None
for row in ws.iter_rows():
for cell in row:
if isinstance(cell.value, str) and cell.value.startswith("="):
cell.value = None
if cell.column > last_col and not isinstance(cell, MergedCell):
cell.value = None
cell.font, cell.fill, cell.border, cell.alignment = Font(), PatternFill(), Border(), Alignment()
cell.number_format = "General"
wb.properties.title = None
path = out_dir / name
xlsx.save_deterministic(wb, path)
return path
def main(argv: list[str]) -> None:
samples = Path(argv[1]) if len(argv) > 1 else SAMPLES
for kind in BUILD:
print(build(kind, samples))
if __name__ == "__main__":
main(sys.argv)