Как зафиксировать области макета печатной формы в 1С, чтобы они не разъезжались на разных компьютерах?

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

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

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

--- ### Выясняем причину: почему макет «плывет» на разных ПК?

Прежде чем переходить к написанию кода, давайте проанализируем ситуацию и поймем физику процесса. Табличный документ 1С не является жестким PDF-файлом. Это динамический объект, визуализация которого сильно зависит от окружения операционной системы конкретного пользователя. Выделим три главные причины деформации:

  1. Драйверы принтеров. При расчете параметров страницы платформа 1С обращается к драйверу принтера, установленного в Windows по умолчанию на конкретном компьютере. У разных моделей принтеров (и даже у разных версий драйверов одного принтера) отличаются минимальные физические поля (непечатаемая область). Если у одного пользователя по умолчанию стоит офисный МФУ с полями 4 мм, а у другого — портативный принтер с полями 8 мм, 1С автоматически сожмет документ или перенесет строки, которые не влезают, на следующий лист.
  2. Разрешение экрана и масштабирование (DPI). На современных мониторах и ноутбуках пользователи часто выставляют системный масштаб Windows в 125% или 150%. В некоторых версиях платформы 1С это приводит к погрешностям при расчете высоты строк и ширины ячеек.
  3. Отсутствующие шрифты. Если в макете использован шрифт, не установленный в операционной системе пользователя, Windows заменяет его на наиболее близкий аналог. Даже минимальное отличие в метриках (высоте и ширине глифов) заменяющего шрифта на документе из 50-100 строк способно суммарно дать погрешность в несколько сантиметров, из-за чего фиксированная область перестанет помещаться на лист.

--- ### Решение 1. Использование «Ключа параметров печати» и правильный порядок инициализации

Для того чтобы настройки печати (такие как масштаб, поля, ориентация) сохранялись индивидуально для каждого макета и не сбрасывались при каждом открытии, платформа предоставляет свойства КлючПараметровПечати (или ИмяПараметровПечати в зависимости от версии платформы и режима управляемых/обычных форм).

Важнейшее правило: параметры страницы по умолчанию (например, поля или свойство автомасшаба) необходимо задавать в коде ДО присвоения значения свойству КлючПараметровПечати. Рассмотрим пример:


ТабДок = Новый ТабличныйДокумент;

// 1. Сначала задаем дефолтные параметры страницы
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДок.АвтоМасштаб = Истина;
ТабДок.ПолеСверху = 10;
ТабДок.ПолеСнизу = 10;
ТабДок.ПолеСлева = 10;
ТабДок.ПолеСправа = 10;

// 2. Только теперь задаем ключ параметров печати!
ТабДок.КлючПараметровПечати = "УникальныйКлючМоегоМаккета_РТиУ";

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

--- ### Решение 2. Программный контроль вывода областей на страницу

Если макет содержит строго две страницы (например, титульный лист и основная спецификация), и нам критически важно, чтобы первая область выводилась на первой странице, а вторая — строго на второй, мы можем принудительно управлять разбивкой страниц.

Рассмотрим подробнее, как объединить две статические области в один документ с жестким разделителем:


ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МойМакет");

// Получаем области для первой и второй страниц
ОбластьСтраница1 = Макет.ПолучитьОбласть("Страница1");
ОбластьСтраница2 = Макет.ПолучитьОбласть("Страница2");

// Выводим первую страницу
ТабДок.Вывести(ОбластьСтраница1);

// Принудительно вставляем горизонтальный разделитель страниц
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();

// Выводим вторую страницу
ТабДок.Вывести(ОбластьСтраница2);

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


ТабДок = Новый ТабличныйДокумент;

// Выводим первую область
ТабДок.Вывести(ОбластьСтраница1);
// Фиксируем колонки для выведенных строк
ТабДок.СоздатьФорматСтрок(); 

// Разделяем страницы
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();

// Выводим вторую область
ТабДок.Вывести(ОбластьСтраница2);
// Фиксируем колонки для второй части документа
ТабДок.СоздатьФорматСтрок();

--- ### Решение 3. Динамический подбор масштаба через ПроверитьВывод()

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

Проанализируем пример функции динамического масштабирования:


// Создаем массив областей для проверки
МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьСтраница1);

// Задаем начальный масштаб
ТабДок.МасштабПечати = 100;

// Если область не влезает на одну страницу при масштабе 100%, 
// начинаем плавно уменьшать масштаб в цикле
Пока Не ТабДок.ПроверитьВывод(МассивОбластей) И ТабДок.МасштабПечати > 80 Цикл
    ТабДок.МасштабПечати = ТабДок.МасштабПечати - 2; // Уменьшаем масштаб на 2%
КонецЦикла;

// Теперь выводим область с гарантией, что она поместится
ТабДок.Вывести(ОбластьСтраница1);

Этот метод опирается на реальные метрики принтера по умолчанию, установленного у пользователя. Мы заставляем платформу «примерить» документ к листу перед выводом на экран и гибко уменьшить масштаб только на тех компьютерах, где это действительно необходимо.

--- ### Решение 4. Использование ПакетОтображаемыхДокументов

Если наши страницы настолько разные, что их невозможно корректно объединить в рамках одного табличного документа (например, первая страница должна быть портретной ориентации, а вторая — ландшафтной, либо у них кардинально различаются настройки полей), на помощь приходит объект ПакетОтображаемыхДокументов.

Этот механизм позволяет сформировать несколько независимых табличных документов и объединить их в единый пакет печати. Для пользователя это будет выглядеть как один документ: при отправке на печать сформируется одно задание в очереди принтера, а при сохранении в формат PDF получится один многостраничный файл.

Разберем программную реализацию этой схемы:


// 1. Создаем и заполняем первую страницу
ТабДок1 = Новый ТабличныйДокумент;
ТабДок1.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДок1.Вывести(ОбластьСтраница1);

// 2. Создаем и заполняем вторую страницу
ТабДок2 = Новый ТабличныйДокумент;
ТабДок2.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабДок2.Вывести(ОбластьСтраница2);

// 3. Создаем пакет документов
Пакет = Новый ПакетОтображаемыхДокументов;

// Помещаем первый документ во временное хранилище и добавляем в пакет
Адрес1 = ПоместитьВоВременноеХранилище(ТабДок1);
ЭлементПакета1 = Пакет.Состав.Добавить();
ЭлементПакета1.Данные = Адрес1;

// Помещаем второй документ во временное хранилище и добавляем в пакет
Адрес2 = ПоместитьВоВременноеХранилище(ТабДок2);
ЭлементПакета2 = Пакет.Состав.Добавить();
ЭлементПакета2.Данные = Адрес2;

// Отображаем пакет пользователю или сразу отправляем на печать
Пакет.Показать("Печать пакета документов");

--- ### Общие рекомендации по проектированию стабильных макетов

Для того чтобы свести к минимуму вероятность «расползания» областей, придерживайтесь следующих правил при разработке макетов в Конфигураторе:

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

← На главную