fix: 6 замечаний по генератору
1) нормализация адреса: «Р-Н Крымский» → «р-н. Крымский», «Г Крымск» → «г. Крымск», «УЛ» → «ул.», «Д.» → «д.» 2) убрана строчка «ПО» на вкладке ИС 3) СЗИ без категорий: «Kaspersky, КриптоПро» (через запятую) 4) кнопка «Выбрать из списка» в подвкладке «Пользователи ИС» 5) бумажные документы: «хранятся в сейфе» (авто-предлог+падеж) 6) незаполненные данные «—» подсвечиваются жёлтым (незаменённые переменные — красным, как было)
This commit is contained in:
+47
-21
@@ -449,32 +449,58 @@ def expand_loops_in_zip(docx_path: str, loops: Dict[str, List[Dict]]) -> str:
|
||||
# 3. ЗАМЕНА ПЕРЕМЕННЫХ В ЭЛЕМЕНТАХ DOCX
|
||||
# ============================================================
|
||||
|
||||
def _apply_highlight_color(run_el, color: str):
|
||||
"""Добавляет маркер highlight указанного цвета к run."""
|
||||
ns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
|
||||
rpr = run_el.find(f'{{{ns}}}rPr')
|
||||
if rpr is None:
|
||||
rpr = OxmlElement('w:rPr')
|
||||
run_el.insert(0, rpr)
|
||||
hl = OxmlElement('w:highlight')
|
||||
hl.set(f'{{{ns}}}val', color)
|
||||
rpr.append(hl)
|
||||
|
||||
|
||||
def _replace_text_in_para(para, replacements: Dict[str, str]) -> bool:
|
||||
"""Заменяет {{var}} в параграфе. Возвращает True, если были замены."""
|
||||
"""Заменяет {{var}} в параграфе. Возвращает True, если были замены.
|
||||
|
||||
Значения «—» (незаполненная информация) подсвечиваются жёлтым маркером.
|
||||
"""
|
||||
full = para.text
|
||||
matches = VAR_PATTERN.findall(full)
|
||||
matches = list(VAR_PATTERN.finditer(full))
|
||||
if not matches:
|
||||
return False
|
||||
|
||||
new_text = full
|
||||
for var in matches:
|
||||
|
||||
# Собираем параграф заново: обычный текст + значения переменных
|
||||
first = para.runs[0] if para.runs else None
|
||||
para.clear()
|
||||
pos = 0
|
||||
changed = False
|
||||
for m in matches:
|
||||
var = m.group(0)
|
||||
val = replacements.get(var)
|
||||
if val is not None:
|
||||
new_text = new_text.replace(var, str(val))
|
||||
|
||||
if new_text == full:
|
||||
return False
|
||||
|
||||
# Сохраняем форматирование первого run
|
||||
if para.runs:
|
||||
first = para.runs[0]
|
||||
para.clear()
|
||||
run = para.add_run(new_text)
|
||||
_copy_run_style(first, run)
|
||||
else:
|
||||
para.clear()
|
||||
para.add_run(new_text)
|
||||
return True
|
||||
if val is None:
|
||||
continue
|
||||
# текст до переменной
|
||||
if m.start() > pos:
|
||||
run = para.add_run(full[pos:m.start()])
|
||||
if first is not None:
|
||||
_copy_run_style(first, run)
|
||||
# значение переменной
|
||||
val_str = str(val)
|
||||
run = para.add_run(val_str)
|
||||
if first is not None:
|
||||
_copy_run_style(first, run)
|
||||
if val_str == '—' or val_str == '':
|
||||
_apply_highlight_color(run._element, 'yellow')
|
||||
changed = True
|
||||
pos = m.end()
|
||||
# хвост после последней переменной
|
||||
if pos < len(full):
|
||||
run = para.add_run(full[pos:])
|
||||
if first is not None:
|
||||
_copy_run_style(first, run)
|
||||
return changed
|
||||
|
||||
|
||||
def _copy_run_style(source, target):
|
||||
|
||||
Reference in New Issue
Block a user