Как правильно переходить на новую строку при динамическом выводе колонок в макете 1С?

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

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

Механика работы методов Вывести и Присоединить

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

  1. Метод Вывести(): Этот метод всегда начинает отрисовку области с начала новой строки (с левого края документа). После его выполнения курсор перемещается в конец выведенной области, но логически система считает, что текущая позиция теперь находится ниже предыдущих данных.
  2. Метод Присоединить(): Этот метод пытается «пристыковать» новую область справа от последней выведенной. Он не переносит курсор на новую строку, а продолжает заполнять текущую.

Таким образом, основная проблема при выводе колонок в цикле заключается в том, что нам нужно сообщить системе: «Первая ячейка должна начать новую строку, а все остальные должны встать в ряд за ней».

Решение проблемы через условие первой колонки

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

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


// Предположим, у нас есть данные в переменной ДанныеСтрок
Для Каждого ТекущаяСтрока Из ДанныеСтрок Цикл
    
    ПерваяКолонка = Истина; // Устанавливаем флаг начала строки
    
    Для Каждого ТекущаяКолонка Из СписокКолонок Цикл
        
        // Получаем область ячейки из макета
        ОбластьЯчейка = Макет.ПолучитьОбласть("Ячейка");
        ОбластьЯчейка.Параметры.Значение = ТекущаяСтрока[ТекущаяКолонка.Имя];
        
        Если ПерваяКолонка Тогда
            // Начинаем новую строку табличного документа
            ТабДок.Вывести(ОбластьЯчейка);
            ПерваяКолонка = Ложь; // Последующие ячейки в этой строке будут присоединяться
        Иначе
            // Добавляем ячейку справа к уже выведенной
            ТабДок.Присоединить(ОбластьЯчейка);
        КонецЕсли;
        
    КонецЦикла;
    
КонецЦикла;

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

Оптимизация с использованием «ячейки-маркера»

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

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

Для Каждого Стр Из ТаблицаДанных Цикл
    // Сначала гарантированно переходим на новую строку
    ОбластьМаркер = Макет.ПолучитьОбласть("НачалоСтроки");
    ТабличныйДок.Вывести(ОбластьМаркер);
    
    // Теперь все колонки без исключения можно только присоединять
    Для Каждого Кол Из МассивКолонок Цикл
        ОбластьДанных = Макет.ПолучитьОбласть("Колонка");
        ОбластьДанных.Параметры.Значение = Стр[Кол];
        ТабличныйДок.Присоединить(ОбластьДанных);
    КонецЦикла;
КонецЦикла;

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

Работа с вертикальными секциями макета

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

Важный нюанс: при использовании Присоединить() для вертикальных областей, платформа 1С автоматически подтягивает высоту строки. Если в присоединяемой области высота ячеек отличается от уже выведенных, итоговая строка может «раздуться». Чтобы избежать этого, рекомендуется в свойствах ячеек макета устанавливать фиксированную высоту или использовать свойство Автовысота строки с последующим вызовом метода ЗакончитьАвторасчетВысотыСтрок() для объекта ТабличныйДокумент.

Типичные ошибки при формировании динамических таблиц

Разберем, почему возникают пустые строки или некорректное форматирование:

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

← На главную