Почему Табличный документ присоединяет данные снизу, а не справа, и как это исправить?

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

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

Разберем механику работы методов Вывести() и Присоединить()

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

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

Если мы вызываем Присоединить() в цикле, но при этом область в макете определена неверно, 1С не находит места справа и переносит данные вниз. Рассмотрим основные причины такого поведения.

Причина 1: Неправильный тип области в макете

Это самая распространенная ошибка. В редакторе макета область можно выделить тремя способами:

Если вы назвали область, выделив целую строку, то для системы 1С эта область имеет бесконечную ширину. Попытка «присоединить» бесконечную ширину к чему-либо справа логически невозможна, поэтому платформа просто выводит ее ниже.

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

Причина 2: Сбитая последовательность вызовов

Проанализируем типичный ошибочный код. Часто программисты пытаются сразу использовать Присоединить() для первой ячейки строки. Но «присоединять» еще не к чему! Чтобы быстро найти такую логическую ошибку, удобно использовать универсальные формы отладки Правильный алгоритм формирования строки выглядит так:

  1. Выводим самую первую (левую) часть строки методом Вывести().
  2. Все последующие ячейки в этой же строке добавляем методом Присоединить().

Посмотрим на пример правильной структуры цикла:


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

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

Метод пересечения областей: создаем «шахматку» профессионально

Рассмотрим более продвинутый и надежный способ формирования сложных таблиц — использование пересечения именованных строк и колонок. Этот подход незаменим при создании сложных динамических отчетов. Это позволяет избежать путаницы с размерами областей.

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

Выясним, как это реализовать в коде:


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

В этом примере Макет.ПолучитьОбласть("СтрокаСырье|КолонкаПродукт") возвращает нам именно ту область, которая находится на стыке указанной строки и колонки. Метод Присоединить() здесь отработает идеально, так как ширина области четко ограничена шириной колонки КолонкаПродукт.

Альтернативный вариант: Прямая адресация ячеек

Если структура вашего отчета слишком сложна и методы Вывести/Присоединить приводят к непредсказуемым результатам, проанализируем вариант с прямой адресацией. Этот метод часто называют «заполнением по координатам». Он дает полный контроль, но стоит помнить, что такая жесткая структура может усложнить дальнейшее редактирование печатных форм пользователями, поэтому применять его стоит осознанно.

Алгоритм действий:

  1. Сначала выводим пустой каркас таблицы или просто определяем, сколько строк и колонок нам потребуется.
  2. Обращаемся к конкретной ячейке через объект Область(НомерСтроки, НомерКолонки).
  3. Устанавливаем значение напрямую в свойство Текст или Значение.

Посмотрим на пример:


// Определяем координаты
НомерСтроки = 5; 
НомерКолонки = 2;

// Прямое заполнение конкретной ячейки
Ячейка = ТабДок.Область(НомерСтроки, НомерКолонки);
Ячейка.Текст = "Сахар";
Ячейка.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;

// Следующая колонка в той же строке
ТабДок.Область(НомерСтроки, НомерКолонки + 1).Текст = "10 кг";

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

Чек-лист для проверки, если Присоединить() все равно не работает:

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

← На главную