Как заполнить макет по каждой строке табличной части в 1С

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

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

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

Разбор ошибки «Итератор для значения не определен»

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

Чтобы получить доступ к строкам, необходимо обратиться к источнику данных этого поля. Разберем два правильных способа:

  1. Через объект данных: Если табличная часть принадлежит основному объекту обработки, следует использовать конструкцию ЭтотОбъект.ИмяТабличнойЧасти.
  2. Через свойство Значение: Если вы обращаетесь именно к элементу формы, нужно использовать свойство Значение.

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


// Способ 1: Обращение напрямую к данным объекта
Для Каждого СтрокаТЧ Из ЭтотОбъект.Товары Цикл
    // Код заполнения макета
КонецЦикла;

// Способ 2: Если работаем с произвольной таблицей значений на форме
Для Каждого СтрокаТЧ Из ЭлементыФормы.ТаблицаТоваров.Значение Цикл
    // Код заполнения макета
КонецЦикла;

Алгоритм работы с макетом по шагам

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

Шаг 1. Получение макета и создание итогового документа.

Сначала мы должны инициализировать объект ТабличныйДокумент, куда будут выводиться данные, и получить сам макет из состава обработки.


ТабДок = Новый ТабличныйДокумент;
Макет = ЭтотОбъект.ПолучитьМакет("Макет"); // Укажите имя вашего макета

Шаг 2. Вывод шапки документа.

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


ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.ДатаДокумента = ТекущаяДата();
ТабДок.Вывести(ОбластьШапка);

Шаг 3. Цикл обхода строк и заполнение детальной части.

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

Важный совет: Чтобы не прописывать присвоение каждого параметра вручную (например, Область.Параметры.Номенклатура = СтрокаТЧ.Номенклатура), воспользуемся методом Заполнить(). Он автоматически сопоставит имена параметров в макете с именами колонок в строке вашей таблицы.


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");

Для Каждого Стр Из ЭтотОбъект.Товары Цикл
    // Автоматическое заполнение параметров по совпадающим именам
    ОбластьСтрока.Параметры.Заполнить(Стр);
    
    // Если нужны дополнительные вычисления
    ОбластьСтрока.Параметры.НомерСтроки = ЭтотОбъект.Товары.Индекс(Стр) + 1;
    
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

Обработка дополнительных данных

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

Критическая ошибка: Делать запрос к базе данных внутри цикла по строкам. Это приведет к катастрофическому замедлению работы при большом количестве строк.

Правильное решение:

  1. Перед началом цикла соберите все необходимые идентификаторы (например, ссылки на номенклатуру) в массив.
  2. Выполните один запрос к базе данных, чтобы получить все нужные данные сразу.
  3. Выгрузите результат запроса в ТаблицуЗначений или в Соответствие (для быстрого поиска по ключу).
  4. Внутри цикла по строкам получайте данные из подготовленной в памяти коллекции.

Рассмотрим пример с использованием Соответствие для получения артикулов:


// 1. Готовим данные заранее
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, Артикул ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&МассивСсылок)";
Запрос.УстановитьПараметр("МассивСсылок", ЭтотОбъект.Товары.ВыгрузитьКолонку("Номенклатура"));

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

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

Завершение формирования и вывод результата

После того как все строки выведены, не забудьте вывести «Подвал» макета (итоговые суммы, подписи) и настроить визуальное отображение документа.


ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
// Заполняем итоги, если нужно
ТабДок.Вывести(ОбластьПодвал);

// Настройки отображения
ТабДок.ТолькоПросмотр = Истина;
ТабДок.ОтображатьСетку = Ложь;
ТабДок.АвтоМасштаб = Истина;

// Показываем результат пользователю
ТабДок.Показать("Печать списка товаров");

Таким образом, мы разобрали полный цикл формирования печатной формы на основе табличной части: от корректного обращения к данным и устранения ошибок итерации до оптимизации запросов и финальной настройки табличного документа. Использование метода Заполнить() и предварительная подготовка данных через запросы — это признаки профессионального подхода к разработке в 1С.

← На главную