Как создать печатную форму с произвольным количеством колонок, адаптировав их ширину под страницу?

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

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

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

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

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

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

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

Алгоритм решения

Для реализации "резиновых" колонок нам потребуется выполнить следующие шаги:

  1. Определить "эталонную" общую ширину, в которую мы должны уложиться.
  2. Узнать точное количество колонок, которые предстоит вывести.
  3. Рассчитать ширину одной колонки по формуле: ОбщаяШирина / КоличествоКолонок.
  4. В цикле вывода перед присоединением области устанавливать ей рассчитанную ширину.

Давайте рассмотрим технические детали реализации этого алгоритма.

Работа со свойством ШиринаКолонки

В платформе 1С для управления шириной ячеек используется свойство области табличного документа. Если мы обратимся к синтаксис-помощнику, то выясним, что нас интересует объект ОбластьЯчеекТабличногоДокумента и его свойство ШиринаКолонки.

Важный нюанс: Ширина колонки в 1С измеряется не в миллиметрах или пикселях, а в средней ширине символа шрифта (обычно это около 8 пикселей, но зависит от настроек стиля). Стандартная ширина колонки в новом макете часто равна 8-9 пунктам. Это означает, что при расчетах мы будем оперировать условными единицами.

Программная реализация

Посмотрим, как это выглядит в коде. Предположим, у нас есть макет с областью "КолонкаДанных", которую мы хотим тиражировать.

Сначала определим исходные данные:


// Пусть требуемая общая ширина равна 60 условным единицам (примерно ширина листа А4)
ТребуемаяОбщаяШирина = 60; 

// Получаем данные для вывода
ТаблицаДанных = ПолучитьДанныеДляПечати();
КоличествоКолонок = ТаблицаДанных.Колонки.Количество();

// Вычисляем ширину одной колонки
// Используем Окр, чтобы получить удобочитаемое число, но это не обязательно
Если КоличествоКолонок > 0 Тогда
    ШиринаОднойКолонки = ТребуемаяОбщаяШирина / КоличествоКолонок;
Иначе
    ШиринаОднойКолонки = 10; // Значение по умолчанию
КонецЕсли;

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


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

ОбластьКолонки = Макет.ПолучитьОбласть("КолонкаДанных");

// Устанавливаем рассчитанную ширину для всей области
// Важно обращаться к свойству Область(), чтобы захватить именно параметры колонок
ОбластьКолонки.Область().ШиринаКолонки = ШиринаОднойКолонки;

Для Каждого КолонкаИзТаблицы Из ТаблицаДанных.Колонки Цикл
    
    // Заполняем параметры области (если есть)
    ОбластьКолонки.Параметры.ИмяКолонки = КолонкаИзТаблицы.Имя;
    
    // Присоединяем область с уже измененной шириной
    ТабДок.Присоединить(ОбластьКолонки);
    
КонецЦикла;

В данном примере мы взяли область из макета, один раз изменили её ширину в памяти (так как она одинакова для всех итераций цикла) и затем выводили её. Если ширина должна быть разной для разных колонок, присваивание ОбластьКолонки.Область().ШиринаКолонки нужно поместить внутрь цикла.

Проблема минимальной ширины

Давайте проанализируем возможные риски. Если количество колонок будет очень большим (например, 50), то при делении 60 / 50 мы получим ширину 1.2. При такой ширине в ячейку не поместится ни одна цифра, и пользователь увидит частокол из символов "###" или обрезанный текст.

Чтобы избежать этого, нам следует ввести проверку на минимально допустимую ширину.


МинимальнаяШирина = 2.5; // Экспериментальное значение, при котором видно хотя бы 2-3 цифры
РасчетнаяШирина = ТребуемаяОбщаяШирина / КоличествоКолонок;

Если РасчетнаяШирина < МинимальнаяШирина Тогда
    ИтоговаяШирина = МинимальнаяШирина;
Иначе
    ИтоговаяШирина = РасчетнаяШирина;
КонецЕсли;

ОбластьКолонки.Область().ШиринаКолонки = ИтоговаяШирина;

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

Альтернативный подход: Автомасштаб

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

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

Для этого используем свойство АвтоМасштаб:

ТабДок.АвтоМасштаб = Истина;

При использовании этого свойства, если таблица получается шире листа, 1С автоматически уменьшит масштаб (размер шрифта и колонок) при отправке на принтер или при предварительном просмотре, чтобы всё поместилось по ширине страницы.

Однако, стоит помнить:

Комбинированный метод: Сетка мелких колонок

Рассмотрим еще один, более сложный, но гибкий метод. Он часто применяется в стандартных отчетах 1С.

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

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

Заключение

Мы выяснили, что для адаптации произвольного количества колонок под фиксированную ширину страницы наиболее эффективным является программный расчет свойства ШиринаКолонки. Основная формула проста: делим доступное пространство на количество элементов.

Однако не забывайте про ограничения:

  1. Всегда проверяйте, не стала ли колонка слишком узкой для отображения данных.
  2. Используйте АвтоМасштаб как страховку для печати.
  3. Помните, что изменение ширины области макета влияет на все последующие выводы этой области через Присоединить, поэтому устанавливайте ширину непосредственно перед выводом.
← На главную