fix: жёлтая подсветка пустых значений в циклах + выборочный Применить
- Циклы (item.*, user_*, алиасы): пустые значения '—'/'' теперь подсвечиваются жёлтым маркером (раньше подстановка шла на уровне XML простым replace — подсветка терялась) - Вложенные циклы (users_loop): та же подсветка - Панель «Проверка данных»: чекбоксы «Подставлять: склонения / кр. склон. / адрес / ИНН-КПП-ОГРН / руковод.» — выборочный Применить - get_short_fio/get_initials: не теряют отчество в сокращённом ФИО
This commit is contained in:
+24
-7
@@ -293,6 +293,23 @@ def _cleanup_marker_paras(doc_xml: str) -> str:
|
||||
return etree.tostring(root, xml_declaration=True, encoding='UTF-8', standalone=True).decode('utf-8')
|
||||
|
||||
|
||||
def _subst_var_xml(xml: str, var: str, val: str) -> str:
|
||||
"""Замена {{var}} в XML-фрагменте.
|
||||
|
||||
Пустые значения («—»/«») подсвечиваются жёлтым маркером: значение
|
||||
выносится в отдельный run с <w:highlight w:val="yellow"/>, чтобы
|
||||
подсветка не затиралась при подстановке на уровне XML (циклы).
|
||||
"""
|
||||
token = '{{%s}}' % var
|
||||
if val not in ('—', ''):
|
||||
return xml.replace(token, val)
|
||||
hl_run = ('<w:rPr><w:highlight w:val="yellow"/></w:rPr>'
|
||||
'<w:t xml:space="preserve">%s</w:t>' % val)
|
||||
return xml.replace(token,
|
||||
'</w:t></w:r><w:r>' + hl_run
|
||||
+ '</w:r><w:r><w:t xml:space="preserve">')
|
||||
|
||||
|
||||
def _expand_nested_loops(template: str, item: Dict) -> str:
|
||||
"""Разворачивает вложенные циклы вида <!-- loop:users_loop --> ... <!-- loop_end -->
|
||||
данными из item (список словарей). Используется для циклов внутри цикла ИС,
|
||||
@@ -342,8 +359,8 @@ def _expand_nested_loops(template: str, item: Dict) -> str:
|
||||
clone = inner
|
||||
for f, v in sub.items():
|
||||
val = str(v) if v else ''
|
||||
clone = clone.replace('{{user_%s}}' % f, val)
|
||||
clone = clone.replace('{{item.%s}}' % f, val)
|
||||
clone = _subst_var_xml(clone, 'user_%s' % f, val)
|
||||
clone = _subst_var_xml(clone, 'item.%s' % f, val)
|
||||
parts.append(clone)
|
||||
result = result[:m_start.start()] + ''.join(parts) + result[m_end.end():]
|
||||
return result
|
||||
@@ -467,13 +484,13 @@ def expand_loops_in_zip(docx_path: str, loops: Dict[str, List[Dict]]) -> str:
|
||||
continue # списки — данные вложенных циклов, не подставляем
|
||||
val_str = str(value) if value else ('—' if value is None else '')
|
||||
# С префиксом item.
|
||||
clone = clone.replace('{{item.%s}}' % field, val_str)
|
||||
clone = _subst_var_xml(clone, 'item.%s' % field, val_str)
|
||||
# Без префикса (алиасы {{name}}, {{pd_list}}, {{document}} и т.д.)
|
||||
clone = clone.replace('{{%s}}' % field, val_str)
|
||||
clone = _subst_var_xml(clone, '%s' % field, val_str)
|
||||
# Альтернативный синтаксис {{item_поле}} (без точки)
|
||||
clone = clone.replace('{{item_%s}}' % field, val_str)
|
||||
clone = clone.replace('{{item.number}}', str(idx))
|
||||
clone = clone.replace('{{number}}', str(idx))
|
||||
clone = _subst_var_xml(clone, 'item_%s' % field, val_str)
|
||||
clone = _subst_var_xml(clone, 'item.number', str(idx))
|
||||
clone = _subst_var_xml(clone, 'number', str(idx))
|
||||
expanded_parts.append(clone)
|
||||
if br_in_suffix:
|
||||
expanded_parts.append('<w:p><w:r><w:br w:type="page"/></w:r></w:p>')
|
||||
|
||||
Reference in New Issue
Block a user