Каждый разработчик 1С рано или поздно сталкивается с ситуациями, которые на первый взгляд кажутся настоящей «мистикой». Представьте картину: вас попросили внести небольшое изменение в макет печатной формы. Вы добавили новую область, вывели ее в коде, запустили отладку — на форме предварительного просмотра все выглядит идеально. Клиент доволен, задача закрыта. Однако через некоторое время клиент сообщает, что при отправке документа на принтер или при сохранении в формате PDF внесенные изменения бесследно исчезают! При этом, если сохранить тот же документ в формате XLS (Excel), новые строки выводятся без каких-либо проблем.
В этой статье мы подробно разберем причины возникновения этой классической проблемы, проанализируем поведение платформы 1С при работе с различными форматами сохранения и разберем эффективные методы исправления этой ошибки раз и навсегда.
Для того чтобы понять природу этой проблемы, давайте проанализируем поведение платформы 1С:Предприятие в различных сценариях вывода табличного документа:
ТабличныйДокумент. Он отображает абсолютно все ячейки и области, которые были программно выведены в документ с помощью методов Вывести() или Присоединить(). Настройки разметки страницы и области печати при этом игнорируются, так как задача экранной формы — показать сформированный документ целиком.ОбластьПечати транслируется во внутренние метаданные файла Excel (настройки области печати листа), но сами ячейки физически записываются в результирующий файл. Открыв файл в MS Excel, пользователь видит весь документ, включая области, вышедшие за пределы условных границ печати.ОбластьПечати, система отсекает все ячейки, которые не входят в указанный диапазон. Все, что находится ниже или правее заданной области, просто игнорируется и не попадает на физический принтер или в файл PDF.Свойство ОбластьПечати объекта ТабличныйДокумент принимает значение типа ОбластьЯчеекТабличногоДокумента. Оно указывает платформе, какой именно прямоугольный сегмент таблицы нужно выводить на печать.
Часто в типовых конфигурациях или старых доработках можно встретить следующий код:
ТабДок.ОбластьПечати = ТабДок.Область("Шапка");
// Или жесткое ограничение по именованной области
ТабДок.ОбластьПечати = ТабДок.Область(1, 1, НомерПоследнейСтроки, НомерПоследнейКолонки);
Если вы добавили новую секцию в макет и вывели ее в самый конец табличного документа (например, перед возвратом документа из функции формирования), но при этом в коде ранее была жестко зафиксирована область печати без учета вашей новой секции, то новые строки будут отрезаны при любой попытке печати или генерации PDF.
Иногда разработчики замечают, что на компьютере программиста форма печатается корректно, а у клиента — со старыми границами. Обычная очистка кэша конфигурации (удаление папок из %appdata%) в этом случае не помогает. Почему так происходит?
Дело в свойстве КлючПараметровПечати. Если у табличного документа задано это свойство, платформа сохраняет индивидуальные настройки печати (включая масштаб, поля, ориентацию и границы области печати) в системном профиле пользователя Windows (в файлах настроек или реестре). При повторном открытии формы платформа пытается применить старые сохраненные параметры. Чтобы решить эту проблему на конкретном рабочем месте, необходимо сбросить настройки печати для этого документа или временно изменить значение свойства КлючПараметровПечати в коде.
Дополнительную путаницу могут вносить инструкции препроцессора, такие как #Если Клиент Тогда, #Если Сервер Тогда или #Если ТолстыйКлиентОбычноеПриложение Тогда. Если алгоритм формирования или ограничения области печати находится внутри условного блока компиляции, поведение программы будет кардинально отличаться в зависимости от контекста выполнения (например, тонкий клиент, толстый клиент или выполнение на стороне сервера при фоновом задании).
Необходимо тщательно анализировать, в каком контексте выполняется код формирования табличного документа и где именно заполняются его свойства.
Рассмотрим подробнее три основных способа устранения этой проблемы в зависимости от бизнес-логики вашей печатной формы.
Если для вашей печатной формы нет жесткой необходимости ограничивать выводимые колонки или строки (то есть документ должен печататься полностью от первой до последней заполненной ячейки), самым простым и надежным решением будет полная очистка свойства ОбластьПечати перед выводом или отправкой на печать.
Для этого в коде формирования печатной формы найдите строку, где переопределяется область печати, и удалите ее, либо принудительно установите значение в Неопределено:
// Очищаем область печати, чтобы платформа автоматически определяла границы документа
ТабличныйДокумент.ОбластьПечати = Неопределено;
В этом случае платформа самостоятельно вычислит крайнюю нижнюю и крайнюю правую заполненные ячейки и отправит на принтер весь документ целиком.
Если логика формы требует обязательного ограничения области печати (например, чтобы скрыть служебные расчетные таблицы, расположенные справа от основного документа), вам необходимо динамически пересчитывать границы области печати с учетом добавленных вами строк.
Проанализируем пример кода, который динамически расширяет область печати до фактической высоты табличного документа:
// Сначала формируем и выводим все необходимые области макета
ТабДок.Вывести(ОбластьШапка);
ТабДок.Вывести(ОбластьСтрока);
// Выводим нашу новую добавленную область
ТабДок.Вывести(ОбластьМоиНовыеИзменения);
// Динамически определяем координаты новой области печати.
// Мы берем диапазон от первой ячейки (1, 1) до фактически заполненной высоты и ширины таблицы.
НомерПоследнейСтроки = ТабДок.ВысотаТаблицы;
НомерПоследнейКолонки = ТабДок.ШиринаТаблицы;
ТабДок.ОбластьПечати = ТабДок.Область(1, 1, НомерПоследнейСтроки, НомерПоследнейКолонки);
Использование свойств ВысотаТаблицы и ШиринаТаблицы гарантирует, что любые программно выведенные области автоматически попадут в новые границы печати.
Чтобы изменения гарантированно применились у всех пользователей, у которых в системе могли сохраниться старые настройки принтера для этой формы, рекомендуется изменить или временно очистить свойство КлючПараметровПечати.
Посмотрим на пример реализации:
// Было в типовом коде:
// ТабличныйДокумент.КлючПараметровПечати = "КЛЮЧ_ПАРАМЕТРОВ_ПЕЧАТИ_АктВыполненныхРабот";
// Изменяем ключ (например, добавляем суффикс версии макета), чтобы платформа сбросила старый кэш у пользователей:
ТабличныйДокумент.КлючПараметровПечати = "КЛЮЧ_ПАРАМЕТРОВ_ПЕЧАТИ_АктВыполненныхРабот_v2";
При первом открытии документа с новым ключом платформа проигнорирует старые сохраненные настройки разметки страниц, пересчитает область печати по актуальному коду конфигурации и сохранит новые корректные параметры.
Применяя эти несложные правила и понимая разницу между физической структурой ячеек табличного документа и правилами его рендеринга, вы сможете легко избегать подобных ошибок при разработке и модификации печатных форм в системе 1С:Предприятие.