При разработке печатных форм в системе 1С:Предприятие одной из наиболее частых задач является контроль разбиения документа на страницы. Разработчики используют метод ПроверитьВывод() объекта ТабличныйДокумент, чтобы определить, умещается ли порция данных (например, строка таблицы или подвал документа) на текущей странице, или пора принудительно вставить разделитель страниц. Однако на практике этот метод ведет себя крайне непредсказуемо. Довольно часто возникает ситуация, когда ПроверитьВывод() упорно возвращает значение Ложь, но при отправке этого же документа на принтер он идеально помещается на одном листе, и даже остается свободное место. Более того, свойство табличного документа КоличествоСтраниц после вывода также может возвращать значение 1, опровергая результат проверки.
Давайте подробно разберем, почему возникает эта проблема, какие скрытые механизмы платформы влияют на расчет страниц и как реализовать надежный алгоритм проверки вывода, который не подведет в реальной эксплуатации.
Самая распространенная причина ложного срабатывания метода кроется в использовании свойства АвтоМасштаб табличного документа. Когда для документа установлено значение АвтоМасштаб = Истина, платформа при выводе на печать автоматически сжимает документ по ширине, чтобы он полностью уместился на одном листе формата А4. Однако метод ПроверитьВывод() работает иначе.
Алгоритм работы метода не умеет динамически рассчитывать коэффициент сжатия, который будет применен при выводе. Он выполняет расчет физических размеров областей "как есть" — при исходном масштабе 100%. Если ваш исходный макет (шаблон) хотя бы на пару миллиметров шире печатной области страницы А4 при масштабе 100%, платформа считает, что документ выйдет за границы листа. В итоге метод возвращает Ложь, сигнализируя о нехватке места, хотя при фактической печати механизм автомасшабирования сожмет документ до 95-98%, и он прекрасно поместится на одной странице.
Вторая неочевидная деталь связана со свойствами КлючПараметровПечати и ИмяПараметровПечати. Эти свойства предназначены для того, чтобы 1С запоминала индивидуальные настройки печати конкретного пользователя (выбранный принтер, поля, масштаб, ориентацию листа) и восстанавливала их при следующем открытии печатной формы.
Если у табличного документа задан ключ параметров печати, то при вызове метода ПроверитьВывод() платформа будет использовать не те параметры (поля, масштаб), которые вы программно задали в коде, а те, которые сохранены в системном профиле пользователя на сервере или локальном компьютере. Если пользователь ранее вручную изменил поля или масштаб для этой формы, метод выполнит проверку на основе сохраненного старого кэша, что приведет к неверному результату.
Метод ПроверитьВывод() критически зависит от системного графического движка операционной системы и доступных драйверов принтера. Рассмотрим, как это влияет на результат:
msttcorefonts операционная система Linux подменяет их на похожие шрифты. Из-за разницы в метриках символов текст может переноситься на новые строки, увеличивая высоту ячеек, что приводит к ложному результату работы ПроверитьВывод().Если в вашем документе используется автоматический расчет высоты строк совместно со свойством переноса текста, расчет высоты документа может сбоить. Особенно это выражено при программном объединении ячеек (метод Объединить()). В момент работы метода ПроверитьВывод() операционная система не всегда корректно пересчитывает высоту строк с объединенными ячейками, из-за чего платформа "думает", что текст занимает больше места, чем на самом деле.
---
Для того чтобы обойти ограничения платформы и заставить проверку вывода работать со 100% точностью, рассмотрим несколько эффективных подходов.
Поскольку ПроверитьВывод() не дружит со свойством АвтоМасштаб, мы можем сымитировать работу автомасштабирования программным путем. Для этого мы отключим автоматический масштаб и будем в цикле уменьшать МасштабПечати нашего табличного документа до тех пор, пока метод ПроверитьВывод() не вернет значение Истина.
Проанализируем следующий пример реализации этого алгоритма:
// Создаем новый табличный документ для проверки
ТабличныйДокументДляПроверки = Новый ТабличныйДокумент;
// Отключаем автоматический масштаб, так как он мешает проверке
ТабличныйДокументДляПроверки.АвтоМасштаб = Ложь;
// Копируем настройки полей и ориентации из исходного документа
ТабличныйДокументДляПроверки.ПолеСлева = ИсходныйДокумент.ПолеСлева;
ТабличныйДокументДляПроверки.ПолеСправа = ИсходныйДокумент.ПолеСправа;
ТабличныйДокументДляПроверки.ПолеСверху = ИсходныйДокумент.ПолеСверху;
ТабличныйДокументДляПроверки.ПолеСнизу = ИсходныйДокумент.ПолеСнизу;
ТабличныйДокументДляПроверки.ОриентацияСтраницы = ИсходныйДокумент.ОриентацияСтраницы;
// Начинаем подбор масштаба со 100%
ТекущийМасштаб = 100;
ТабличныйДокументДляПроверки.МасштабПечати = ТекущийМасштаб;
// Выводим данные во временный документ
ТабличныйДокументДляПроверки.Вывести(ИсходныйДокумент);
// Запускаем цикл подбора масштаба (не опускаемся ниже 70%, чтобы текст оставался читаемым)
УспешныйВывод = Ложь;
Пока ТекущийМасштаб >= 70 Цикл
Если ТабличныйДокументДляПроверки.ПроверитьВывод(ТабличныйДокументДляПроверки) Тогда
УспешныйВывод = Истина;
Прервать;
КонецЕсли;
// Уменьшаем масштаб на 2 процента за шаг
ТекущийМасштаб = ТекущийМасштаб - 2;
ТабличныйДокументДляПроверки.МасштабПечати = ТекущийМасштаб;
КонецЦикла;
Если УспешныйВывод Тогда
// Применяем подобранный рабочий масштаб к оригинальному документу
ИсходныйДокумент.АвтоМасштаб = Ложь;
ИсходныйДокумент.МасштабПечати = ТекущийМасштаб;
Иначе
// Если даже при сжатии не влезает, возвращаем исходный автомасштаб
ИсходныйДокумент.АвтоМасштаб = Истина;
КонецЕсли;
Если вам необходимо сохранять настройки печати пользователя, но при этом гарантировать корректность проверки на сервере, никогда не устанавливайте КлючПараметровПечати до выполнения проверок вывода. Присваивайте его в самый последний момент, непосредственно перед выводом готового сформированного документа на экран или печать.
Рассмотрим правильную последовательность действий:
КлючПараметровПечати уникальный идентификатор вашей печатной формы.В клиент-серверной архитектуре прямой вызов метода ПроверитьВывод() на сервере может завершиться аварийным завершением работы процесса из-за отсутствия установленных драйверов принтеров в операционной системе. Чтобы обезопасить конфигурацию от непредвиденных падений, рекомендуется использовать безопасную обертку из Библиотеки Стандартных Подсистем (БСП).
Вместо прямого вызова метода используем функцию общего назначения БСП:
// Безопасный вызов проверки вывода средствами БСП
ПараметрыПроверки = Новый Массив;
ПараметрыПроверки.Добавить(ОбластьМакета);
Если ОбщегоНазначенияКлиентСервер.ПроверитьВыводТабличногоДокумента(ТабличныйДокумент, ПараметрыПроверки) Тогда
ТабличныйДокумент.Вывести(ОбластьМакета);
Иначе
ТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц();
ТабличныйДокумент.Вывести(ОбластьМакета);
КонецЕсли;
Данная функция выполняет внутреннюю проверку возможности построения печатных страниц на сервере и перехватывает возможные исключения операционной системы, предотвращая падение сеанса пользователя.
Если макет разрабатывается с нуля, старайтесь избегать чрезмерно широких колонок. Всегда тестируйте макет при масштабе 100% с полями по 10 мм. Если макет в ширину превышает границы листа А4 при 100%, пересмотрите структуру таблиц. Помните: правильный макет изначально должен быть спроектирован так, чтобы укладываться в печатную область по ширине без использования автомасшабирования.