Как исправить разрезание строк текста при печати табличного документа в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке печатных форм в среде «1С:Предприятие» программисты часто сталкиваются с крайне неприятным поведением платформы: длинный многострочный текст (например, текст договора, подробное примечание, гарантийные обязательства или рекламация) при выводе на печать разрывается на стыке страниц. В результате верхняя половина букв строки печатается внизу одного листа, а нижняя половина переносится на следующий лист. Регулировка полей страницы, изменение высоты строк или шрифтов в макете не решают проблему системно, а лишь временно сдвигают границу разрыва на другую строку.

В этой статье мы подробно проанализируем причины возникновения этой проблемы и рассмотрим несколько надежных практических способов ее устранения — от правильных настроек макета до продвинутого программного разбиения текста.

Выясняем первопричину: почему платформа 1С «режет» буквы?

Основная причина кроется в использовании вертикального объединения ячеек в макете для вывода длинного текста. Когда мы выделяем область, например из 10–15 строк, и объединяем их как по горизонтали, так и по вертикали для размещения большого текстового блока, платформа 1С начинает воспринимать эту объединенную ячейку как единый, неделимый графический объект (цельный прямоугольник).

При выводе на печать движок табличного документа пытается уместить этот объект на странице. Если вся объединенная ячейка целиком не помещается на одном листе, система выполняет жесткую геометрическую (пиксельную) отсечку на физической границе листа А4. Платформа не умеет анализировать внутреннее текстовое содержимое объединенной области, чтобы рассчитать положение строк текста относительно границы страницы. Из-за этого линия разрыва страницы проходит прямо «по живому» — разделяя символы текста пополам по горизонтали.

Ограничение механизма «Автовысоты» для длинного текста

Некоторые разработчики пытаются решить проблему, отказываясь от вертикального объединения ячеек, но оставляя текст в одной горизонтальной строке с включенным свойством РазмещениеТекста в значении Переносить и автовысотой строки.

Однако здесь мы сталкиваемся с другим важным ограничением платформы: если объем текста в одной ячейке настолько велик, что рассчитанная автовысота этой строки превышает высоту одного физического листа бумаги (формата А4), то табличный документ не сможет корректно перенести часть текста на следующий лист. В результате мы получим одну из двух проблем:

  1. Текст будет принудительно и жестко обрезан по нижнему краю первой страницы.
  2. Вся гигантская строка целиком улетит на следующую страницу, оставив предыдущую страницу практически пустой (на ней останется только шапка документа).

Рассмотрим по шагам основные способы решения этой проблемы.

Решение 1. Правильное объединение ячеек в макете (отказ от вертикального объединения)

Самый простой и правильный первый шаг — полностью исключить объединение ячеек по вертикали в макете. Выполним правильную настройку ячеек в конфигураторе:

  1. Откройте макет печатной формы в конфигураторе.
  2. Выберите строку, в которой планируется вывод текста. Объедините ячейки только по горизонтали (в пределах необходимой ширины печатной области). Ни в коем случае не объединяйте строки по вертикали для текстовых блоков.
  3. Откройте свойства полученной объединенной ячейки (клавиша F4).
  4. Найдите свойство РазмещениеТекста и установите его в значение Переносить.
  5. Для строки макета, в которой находится ячейка, установите свойство ВысотаСтроки в значение Авто.

При таком подходе платформа сможет автоматически подбирать высоту строки в зависимости от объема текста. Если абзацы не слишком длинные, они будут аккуратно распределяться по страницам без деформации и разрезания букв.

Решение 2. Программное разбиение текста по абзацам (символу переноса строки)

Если ваш текст состоит из нескольких абзацев, разделенных символом перевода строки (Символы.ПС), мы можем программно разложить исходный текст на массив строк и выводить их в цикле как отдельные области макета. Это гарантирует, что разрыв страницы произойдет ровно между абзацами, а не посреди текста.

Разберем пример кода, реализующий этот подход:


// Получаем исходный текст из объекта-источника
ИсходныйТекст = СсылкаНаОбъект.ДлинныйТекст;

// Разлагаем текст в массив по символу перевода строки (абзацам)
МассивАбзацев = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ИсходныйТекст, Символы.ПС);

// Перебираем массив абзацев и последовательно выводим в табличный документ
Для Каждого ТекущийАбзац Из МассивАбзацев Цикл
    // Получаем отдельную область строки из макета
    ОбластьСтроки = Макет.ПолучитьОбласть("СтрокаТекста");
    
    // Заполняем параметр нашей строки текущим абзацем
    ОбластьСтроки.Параметры.ТекстАбзаца = ТекущийАбзац;
    
    // Выводим заполненную область в итоговый табличный документ
    ТабДокРезультат.Вывести(ОбластьСтроки);
КонецЦикла;

Этот способ отлично работает, если абзацы в вашем тексте относительно небольшие и каждый из них гарантированно помещается по высоте на одну страницу.

Решение 3. Продвинутый контроль переноса страниц через ПроверитьВывод()

Что делать, если абзацы длинные или вы хотите абсолютно жестко контролировать, поместится ли очередная порция текста на страницу перед ее выводом? Для этого в платформе 1С предусмотрен мощный метод ПроверитьВывод() объекта ТабличныйДокумент.

Проанализируем алгоритм динамической проверки вывода. Мы помещаем проверяемую область в массив и передаем его методу ПроверитьВывод(). Если метод возвращает Ложь, это означает, что при выводе данной области произойдет переход на новую страницу. В этот момент мы можем принудительно добавить разделитель страниц, чтобы документ выглядел красиво и аккуратно.

Посмотрим на практический пример реализации такого алгоритма:


// Получаем массив абзацев
МассивАбзацев = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ИсходныйТекст, Символы.ПС);

// Инициализируем массив для проверки вывода областей
ПроверяемыеОбласти = Новый Массив;

Для Каждого ТекущийАбзац Из МассивАбзацев Цикл
    // Получаем область строки макета
    ОбластьСтроки = Макет.ПолучитьОбласть("СтрокаТекста");
    ОбластьСтроки.Параметры.ТекстАбзаца = ТекущийАбзац;
    
    // Очищаем массив и добавляем текущую область для проверки
    ПроверяемыеОбласти.Очистить();
    ПроверяемыеОбласти.Добавить(ОбластьСтроки);
    
    // Проверяем, поместится ли строка на текущей странице
    Если Не ТабДокРезультат.ПроверитьВывод(ПроверяемыеОбласти) Тогда
        // Если не помещается, принудительно переносим на следующую страницу
        ТабДокРезультат.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЕсли;
    
    // Выводим строку в итоговый документ
    ТабДокРезультат.Вывести(ОбластьСтроки);
КонецЦикла;

Этот подход полностью решает проблему разрезания строк, так как каждая строка выводится целиком. Если она не помещается на текущем листе, то переносится на следующий лист без разрывов посередине текста. Ознакомиться со стандартной структурой кода печати можно на примере внешней печатной формы на БСП 3.1.10.

Важные технические нюансы и скрытые проблемы

При работе с макетами печати и методом ПроверитьВывод() необходимо учитывать несколько критически важных особенностей платформы 1С:

1. Конфликт с масштабированием (АвтоМасштаб)
Свойство табличного документа АвтоМасштаб = Истина или установленный вручную МасштабПечати могут приводить к некорректной работе метода ПроверитьВывод(). Дело в том, что расчет вместимости областей производится платформой на основе физических размеров страницы при масштабе 100%. Если включен автомасштаб, 1С пытается сжать документ, чтобы он влез по ширине, из-за чего расчеты высоты сбиваются, и строки на границах листов снова могут начать «резаться».

Рекомендация: Выполняйте проверку вывода при стандартном масштабе (100%), а свойство АвтоМасштаб = Истина применяйте к табличному документу уже после того, как он полностью сформирован.

2. Зависимость от принтера по умолчанию
Метод ПроверитьВывод() осуществляет расчет геометрии вывода на основе драйвера принтера, установленного по умолчанию в операционной системе текущего пользователя. Если печать происходит на сервере (например, в фоновом задании), где принтеры не установлены, или у разных пользователей стоят разные модели принтеров (с разными минимальными полями печати и разрешениями), результаты работы метода могут отличаться. Старайтесь тестировать вывод на тех принтерах, которые реально используются конечными пользователями.

3. Свойство строки «Вместе со следующим»
Чтобы избежать ситуации, когда заголовок текста или подписи («подвал») отрываются от основного содержимого и переносятся на новую страницу в одиночку, в свойствах строк макета (или программно для области табличного документа) следует использовать флаг ВместеСоСледующим (KeepWithNext). Это гарантирует, что 1С перенесет эти строки на новую страницу только вместе с предшествующей или последующей значимой строкой.

Решение 4. Использование объекта «ФорматированныйДокумент»

Если перед вами стоит задача вывода на печать очень длинных и сложных юридических текстов (договоров, соглашений, актов), табличный документ 1С в принципе является не самым лучшим инструментом. Гораздо эффективнее использовать объект ФорматированныйДокумент или выводить текст через HTML-поле. Платформа 1С умеет автоматически и абсолютно корректно разбивать форматированные документы на страницы при печати, полностью исключая любые проблемы с разрезанием строк текста. Для знакомства с возможностями этого объекта можно изучить материал по работе с форматированным документом.

Ограничения при экспорте в Excel

Если ваши пользователи планируют сохранять сформированные печатные формы в формате Excel, помните о жестком ограничении программы Microsoft Excel: максимальная высота одной строки в ней ограничена 409.5 пунктами (около 546 пикселей).

Если вы выведете огромный кусок текста в одну ячейку табличного документа 1С с включенной автовысотой, то при экспорте в Excel часть текста, не поместившаяся в лимит высоты строки Excel, гарантированно скроется или обрежется. Единственным надежным способом избежать этого является изначальное программное разбиение длинного текста на несколько самостоятельных строк в табличном документе 1С до момента вывода, как это было показано в Решении 2 и Решении 3.

← На главную