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

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

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

Разбор типичной ошибки: Вложенные таблицы в запросе

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


ВЫБРАТЬ
    ПоступлениеТоваровУслуг.Товары.(
        Количество КАК Количество,
        Цена КАК Цена,
        Номенклатура.Наименование КАК НоменклатураНаименование
    ) КАК Товары
ИЗ
    Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг

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

Правильный текст запроса должен выглядеть так:


ВЫБРАТЬ
    ПТУТовары.Номенклатура КАК Номенклатура,
    ПТУТовары.Количество КАК Количество,
    ПТУТовары.Цена КАК Цена
ИЗ
    Документ.ПоступлениеТоваровУслуг.Товары КАК ПТУТовары
ГДЕ
    ПТУТовары.Ссылка = &Ссылка

Способ 1: Использование метода Загрузить() — Самый быстрый путь

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

Давайте проанализируем шаги для реализации этого метода:

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

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПТУТовары.Номенклатура КАК Номенклатура,
    |	ПТУТовары.Количество КАК Количество,
    |	ПТУТовары.Цена КАК Цена
    |ИЗ
    |	Документ.ПоступлениеТоваровУслуг.Товары КАК ПТУТовары
    |ГДЕ
    |	ПТУТовары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);

ТаблицаРезультат = Запрос.Выполнить().Выгрузить();
// Объект — это наш документ или обработка
Объект.Товары.Загрузить(ТаблицаРезультат);

Важный нюанс: Метод Загрузить() полностью очищает табличную часть перед заполнением. Если вам нужно добавить данные к уже существующим строкам, используйте другие способы.

Способ 2: Ручной обход выборки с использованием ЗаполнитьЗначенияСвойств()

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

Рассмотрим этот алгоритм подробнее:


Выборка = Запрос.Выполнить().Выбрать();

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

Этот метод делает код чище и устойчивее к изменениям структуры метаданных.

Особенности работы в управляемом приложении

Проанализируем ситуацию работы с формами. Если вы вызываете серверную процедуру из модуля формы, помните, что на сервере вы часто работаете с РеквизитФормыВЗначение("Объект"). Данные формы не являются полноценным объектом базы данных.

Если вы заполнили таблицу на сервере через Объект.Товары.Загрузить(), не забудьте применить метод ЗначениеВРеквизитФормы(ДокОбъект, "Объект"), чтобы изменения отобразились в интерфейсе пользователя. В противном случае данные останутся только в памяти сервера.

Типизация колонок при создании таблицы значений вручную

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

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


ОписаниеЧисла = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3));
ОписаниеНоменклатуры = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");

ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Количество", ОписаниеЧисла);
ТЗ.Колонки.Добавить("Номенклатура", ОписаниеНоменклатуры);

Оптимизация и отладка

Для того чтобы ваши запросы работали быстро, а заполнение таблиц не вызывало вопросов, придерживайтесь следующих правил:

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

← На главную