Как вывести данные в две колонки в табличном документе 1С?

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

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

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

Почему метод Присоединить() смещает вторую колонку вниз?

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

Обратимся к синтаксису платформы. Метод Присоединить() помещает область в следующей колонке правее самой правой выведенной колонки, начиная со строки, с которой выводился предыдущий табличный документ. Таким образом, если левая колонка заняла 40 строк, попытка присоединить вторую область прикрепит ее начиная с 40-й строки, а не с 1-й.

Способ 1. Построчный параллельный вывод (Вывести + Присоединить)

Самый надежный и быстродействующий способ — формировать документ горизонтальными парами строк. Разберем по шагам, как организовать этот процесс:

  1. Подготовим массив или таблицу данных, которые требуется вывести на странице.
  2. Разделим порцию данных для одной страницы на две равные части: левый и правый массив (например, по 25 элементов).
  3. В цикле одновременно берем i-й элемент левой части и i-й элемент правой части.
  4. Сначала вызываем ТабДок.Вывести(ОбластьЛево), затем сразу ТабДок.Присоединить(ОбластьПраво).
  5. После заполнения страницы при необходимости вызываем ТабДок.ВывестиГоризонтальныйРазделительСтраниц().

Посмотрим на пример программной реализации параллельного вывода фиксированного количества строк:


// Количество строк в одной колонке на странице
СтрокНаЛисте = 30; 
ВсегоЭлементов = МассивДанных.Количество();
Индекс = 0;

Пока Индекс < ВсегоЭлементов Цикл
    // Вычисляем границы порции для текущего листа
    КоличествоНаЛист = Мин(СтрокНаЛисте * 2, ВсегоЭлементов - Индекс);
    СтрокВКолонке = Окр(КоличествоНаЛист / 2, 0, РежимОкругления.ОкруглениеВверх);
    
    Для НомерСтроки = 0 По СтрокВКолонке - 1 Цикл
        ИндексЛевый = Индекс + НомерСтроки;
        ИндексПравый = Индекс + СтрокВКолонке + НомерСтроки;
        
        // Заполняем и выводим левую колонку
        Если ИндексЛевый < ВсегоЭлементов Тогда
            ОбластьЛевая.Параметры.Заполнить(МассивДанных[ИндексЛевый]);
            ТабДок.Вывести(ОбластьЛевая);
        КонецЕсли;
        
        // Заполняем и присоединяем правую колонку
        Если ИндексПравый < (Индекс + КоличествоНаЛист) И ИндексПравый < ВсегоЭлементов Тогда
            ОбластьПравая.Параметры.Заполнить(МассивДанных[ИндексПравый]);
            ТабДок.Присоединить(ОбластьПравая);
        КонецЕсли;
    КонецЦикла;
    
    Индекс = Индекс + КоличествоНаЛист;
    
    // Если данные еще остались, добавляем разделитель страниц
    Если Индекс < ВсегоЭлементов Тогда
        ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЕсли;
КонецЦикла;

Способ 2. Динамический расчет высоты с помощью ПроверитьВывод()

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

  1. Создаем временный объект ТабличныйДокумент с теми же параметрами печати (поля, ориентация, масштаб), что и основной.
  2. Во временный документ последовательно выводим строки одной колонки и проверяем помещаемость через ТабДокВременный.ПроверитьВывод(МассивОбластей).
  3. Как только метод возвращает Ложь, фиксируем, сколько строк поместилось по высоте листа.
  4. Делим полученный объем данных пополам и выводим их в основной документ параллельным методом (Способ 1).

МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьСтроки);

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

Способ 3. Заполнение через метод ВставитьОбласть()

Если алгоритм построения макета требует сначала полностью сгенерировать левую часть таблицы, а затем перенести данные в правую половину, можно воспользоваться методом ВставитьОбласть():

  1. Выводим левую колонку в результирующий ТабличныйДокумент.
  2. Правую колонку формируем во втором, временном табличном документе.
  3. Копируем прямоугольный блок ячеек из временного документа в основной с помощью вызова ТабДок.ВставитьОбласть(ОбластьИсточник, ОбластьПриемник, ТипСмещенияТабличногоДокумента.БезСмещения).

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

Особенности и важные нюансы

← На главную