При формировании печатных форм на базе шаблонов Microsoft Word (DOCX) в программах 1С часто возникает ситуация, когда часть параметров является опциональной. Если параметр вынесен на отдельную строку макета в виде {v8 Параметр}, а в коде ему присваивается пустое значение, в итоговом документе часто остается пустой абзац с отступами, нарушающий визуальную структуру текста. Разберем причины такого поведения платформы и механизмов БСП, а также рассмотрим надежные способы решения этой проблемы без использования COM-соединений, что особенно актуально для серверов под управлением Linux.
Проанализируем внутреннее устройство документа DOCX (Office Open XML). Файл формата .docx представляет собой обычный ZIP-архив, содержащий набор XML-файлов. Текстовое содержимое документа хранится в файле word/document.xml, где текст разбит на узлы абзацев <w:p>, внутри которых находятся блоки форматирования и строки <w:r><w:t>...</w:t></w:r>.
Штатная подсистема печати БСП производит замену маркеров вида {v8 Параметр} исключительно на уровне содержимого тега <w:t>. Если в макете тег располагается на отдельной строке, то в XML-структуре ему соответствует полноценный узел абзаца. При подстановке пустой строки узел <w:p> никуда не исчезает: в результирующем документе сохраняется пустой абзац со всеми стилями, межстрочными интервалами и отступами. Специального управляющего символа, передача которого заставила бы БСП автоматически удалить родительский абзац, в платформе не предусмотрено.
Рассмотрим рабочие варианты обхода и устранения этой проблемы.
Наиболее правильный и штатный способ управления опциональными абзацами в БСП — это разбиение документа на секции при помощи именованных областей. Механизм БСП поддерживает теги областей в формате {v8 Область.ИмяОбласти} и {/v8 Область.ИмяОбласти}.
Разберем по шагам реализацию этого подхода:
{v8 Область.ДополнительныйПункт}5.2. Работнику предоставляется {v8 ОписаниеОтпуска}.{/v8 Область.ДополнительныйПункт}УправлениеПечатью:
// Проверяем наличие данных перед выводом блока
Если ЗначениеЗаполнено(ТекстДополнительногоОтпуска) Тогда
ОбластьБлока = УправлениеПечатью.ОбластьМакета(Макет, ОписаниеОбластей.ДополнительныйПункт);
ПараметрыБлока = Новый Структура;
ПараметрыБлока.Вставить("ОписаниеОтпуска", ТекстДополнительногоОтпуска);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФорма, ОбластьБлока, ПараметрыБлока);
КонецЕсли;
Если условие не выполняется, область просто не присоединяется к результирующему документу. В этом случае узел абзаца вообще не попадает в итоговый XML-файл, и разрыв текста полностью отсутствует.
Если документ формируется целиком за один вызов без секционирования на области, можно применить форматирование строки внутри кода 1С.
Посмотрим на пример организации шаблона:
{v8 ДополнительныйПункт} вплотную к предыдущему тексту или в конце предшествующего абзаца.Символы.ПС непосредственно к значению, если оно заполнено:
Если ЗначениеЗаполнено(ДополнительныйОтпуск) Тогда
// Формируем текст пункта с переводом строки в начале
ПараметрыДокумента.Вставить("ДополнительныйПункт", Символы.ПС + "5.2. Работнику предоставляется " + СокрЛП(ДополнительныйОтпуск));
Иначе
// Если данных нет, передаем пустую строку без переноса
ПараметрыДокумента.Вставить("ДополнительныйПункт", "");
КонецЕсли;
Когда условие не выполняется, пустая строка подставляется в конец существующего абзаца, не создавая нового переноса и лишних отступов.
Если изменить структуру макета невозможно, применим низкоуровневую обработку полученного файла. Поскольку DOCX является ZIP-архивом, платформа 1С позволяет распаковать его, скорректировать XML и упаковать обратно без COM и внешних библиотек.
Разберем по шагам последовательность действий:
ЧтениеZipФайла.word/document.xml в текстовую переменную или обрабатываем его через ЧтениеXML / ФабрикаXDTO.<w:p><w:r><w:t></w:t></w:r></w:p> или узлы <w:p/>, в которых нет текстового содержимого.word/document.xml обратно.ЗаписьZipФайла.Этот способ требует аккуратности при работе со структурой XML, однако обеспечивает полную независимость от операционной системы и корректно работает на серверах под управлением Windows и Linux.