Часто при автоматизации документооборота и формировании печатных форм из системы 1С версии 7.7 мы сталкиваемся с необходимостью передать многострочный текст в готовый шаблон Microsoft Word. Проанализируем типичную ситуацию: мы создали шаблон, разместили в нем поля формы (закладки) и пытаемся заполнить их многострочными данными, например, банковскими реквизитами. Однако вместо аккуратного блока с переносами строк Word выводит весь переданный текст в одну длинную нечитаемую строку. Разберем по шагам, почему это происходит и как правильно решить данную техническую задачу.
Рассмотрим классический пример кода, который используют многие программисты. Мы собираем строку РасчСчет из нескольких частей, добавляя между ними стандартный разделитель или символы возврата каретки (например, Симв(13) + Симв(10)), а затем передаем результат в поле формы:
РасчСчет = "p/c " + Докум.Фирма.ОсновнойСчет.НомерСчета;
РасчСчет = РасчСчет + Симв(13) + Симв(10) + "к/с " + Докум.Фирма.ОсновнойСчет.Банк.КоррСчет;
РасчСчет = РасчСчет + Симв(13) + Симв(10) + "в " + Докум.Фирма.ОсновнойСчет.Банк;
ВордДок.FormFields("РсНаш").Result = РасчСчет;
В результате выполнения этого кода в Word мы ожидаем увидеть несколько строк, но видим только одну. Выясним причину такого поведения. Объект FormFields (поля формы) является устаревшим элементом управления в Word. У него есть специфическая особенность обработки вставляемого текста, в особенности если само поле расположено внутри ячейки таблицы. Если передать в него стандартный перенос каретки, Word может проигнорировать эти управляющие символы или отобразить их в виде нечитаемых "квадратиков", выстраивая текст линейно.
Чтобы Word корректно воспринял разрыв строки внутри поля формы, нам необходимо использовать символ "мягкого переноса", который эквивалентен нажатию комбинации клавиш Shift + Enter. В таблице ASCII этому символу соответствует код 11. Посмотрим на исправленный и гарантированно работающий вариант кода:
РасчСчет = "p/c " + Докум.Фирма.ОсновнойСчет.НомерСчета;
РасчСчет = РасчСчет + Симв(11) + "к/с " + Докум.Фирма.ОсновнойСчет.Банк.КоррСчет;
РасчСчет = РасчСчет + Симв(11) + "в " + Докум.Фирма.ОсновнойСчет.Банк;
РасчСчет = РасчСчет + Симв(11) + "БИК " + Докум.Фирма.ОсновнойСчет.Банк.Код;
ВордДок.FormFields("РсНаш").Result = РасчСчет;
Используя Симв(11), мы разрываем строку внутри одного абзаца. Этот метод поля формы воспринимают абсолютно корректно, и наши банковские реквизиты будут выведены красивым столбцом, ровно в 4 строки.
Рассмотрим подробнее другие методы работы с шаблонами Word. Если вы только начинаете разрабатывать механизм выгрузки, возможно, вам стоит отказаться от FormFields в пользу более гибких инструментов.
Вместо полей формы можно использовать классические закладки. Если обращаться к закладке через свойство Range, то Word будет обрабатывать текст иначе. Объект Range отлично понимает стандартные переносы строк Симв(13) и комбинации Симв(13) + Симв(10). Пример кода:
ВордДок.Bookmarks("РсНаш").Range.Text = РасчСчет;
Этот метод не только решает проблему с переносами, но и позволяет создавать полноценные новые абзацы.
Многие разработчики предпочитают расставлять в шаблоне Word текстовые теги, например [РасчетныйСчет], и заменять их программно. В этом случае для переноса строк нужно заменять символы из 1С на служебные комбинации самого Word: ^p для создания нового абзаца (аналог Enter) или ^l для ручного разрыва строки (аналог Shift+Enter).
Если необходимо сформировать большой массив текста с непредсказуемым количеством строк, надежнее всего встать на нужную позицию курсора и имитировать ввод с клавиатуры. Для перевода строки в таком случае используются методы ВордДок.Application.Selection.TypeParagraph() для нового абзаца или Selection.InsertBreak() для разрыва страницы/строки.
Проанализируем еще один подводный камень, о котором необходимо помнить. Свойство FormFields().Result, а также параметры метода Find.Execute в некоторых версиях Word имеют жесткое ограничение на длину передаваемого текста — 255 символов. Если формируемый блок данных (включая символы переноса) превысит этот лимит, 1С выдаст ошибку вызова COM-объекта. Если вы планируете передавать длинные блоки текста, обязательно используйте методы записи через Bookmarks.Range.Text или Selection.TypeText, так как они не имеют подобных ограничений длины.