К статье
Практический материал

Разработка и Конфигурация · 9 мин

1С: как загрузить результат запроса в таблицу

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

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

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

Базовый способ: результат запроса в таблицу значений

Стандартная последовательность состоит из четырёх шагов: создать объект «Запрос», задать текст, выполнить его и выгрузить результат. Метод Выполнить() возвращает объект «РезультатЗапроса», а метод Выгрузить() этого объекта — таблицу значений.

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

Результат = Запрос.Выполнить();
ТаблицаДанных = Результат.Выгрузить();

Для Каждого Строка Из ТаблицаДанных Цикл
 Сообщить(Строка.Товар);
КонецЦикла;

У метода Выгрузить() есть необязательный параметр — тип обхода результата. По умолчанию используется ОбходРезультатаЗапроса.Прямой, и данные выгружаются плоской таблицей. Если запрос содержит итоги по группировкам, можно указать ОбходРезультатаЗапроса.ПоГруппировкам — тогда получится дерево значений, а не таблица.

Колонки таблицы значений получают имена и типы из полей выборки запроса. Если в запросе полю задан псевдоним через «КАК», колонка будет называться именно так. Это важно при последующей загрузке в табличную часть, где имена должны совпадать.

Загрузка таблицы значений в табличную часть документа

Когда таблица значений получена, её можно одной командой перенести в табличную часть документа, справочника или обработки. Для этого у табличной части есть метод Загрузить(), который принимает таблицу значений и заполняет строки по совпадению имён колонок и реквизитов.

Порядок действий
  1. 1
    Сформируйте запрос и задайте полям псевдонимы, совпадающие с именами реквизитов табличной части
  2. 2
    Выполните запрос и выгрузите результат в таблицу значений
  3. 3
    Вызовите Объект.Товары.Загрузить(ТаблицаДанных)
  4. 4
    Запишите объект: Объект.Записать()
  5. 5
    Проверьте количество строк и заполненность колонок в форме документа
Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Остатки.Номенклатура КАК Номенклатура,

| Остатки.КоличествоОстаток КАК Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки";

Запрос.УстановитьПараметр("Период", ТекущаяДатаСеанса());

Запрос.УстановитьПараметр("Склад", ВыбранныйСклад);

ДокОбъект = Документы.ИнвентаризацияТоваров.СоздатьДокумент();

ДокОбъект.Дата = ТекущаяДатаСеанса();

ДокОбъект.Товары.Загрузить(Запрос.Выполнить().Выгрузить());

ДокОбъект.Записать();

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

Построчная загрузка через выборку

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

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

Пока Выборка.Следующий() Цикл

НоваяСтрока = ДокОбъект.Товары.Добавить();

НоваяСтрока.Номенклатура = Выборка.Номенклатура;

НоваяСтрока.Количество = Выборка.КоличествоОстаток;

НоваяСтрока.Цена = ПолучитьЦену(Выборка.Номенклатура);

КонецЦикла;

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

Выборка или таблица значений: что выбрать

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

Сравнение вариантов

Выгрузить() в таблицу значений

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

Выбрать() и обход выборки

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

Выгрузить() с обходом по группировкам

Подходит для иерархических данных из запроса с итогами. Возвращает дерево значений, обход — рекурсивный.

Загрузка запроса в таблицу на форме обработки

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

&НаСервере

Процедура ЗаполнитьТаблицуНаСервере()

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ Ссылка КАК Контрагент ИЗ Справочник.Контрагенты";

ТЗ = Запрос.Выполнить().Выгрузить();

ЗначениеВРеквизитФормы(ТЗ, "ТаблицаКонтрагентов");

КонецПроцедуры

&НаКлиенте

Процедура Заполнить(Команда)

ЗаполнитьТаблицуНаСервере();

КонецПроцедуры

Реквизит формы «ТаблицаКонтрагентов» должен быть создан заранее с типом «ТаблицаЗначений» и колонками, совпадающими по именам с полями запроса. Если тип реквизита — «ДинамическийСписок», подход другой: там запрос задаётся в свойствах списка, и выгружать ничего не нужно.

Проверка результата и типичные ошибки

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

Типичные ошибки
01
Несовпадение имён колонок и реквизитов табличной части — колонки молча не загружаются, поля остаются пустыми
02
Загрузка без проверки Результат.Пустой() — табличная часть очищается пустой таблицей
03
Вызов Загрузить() вместо добавления строк — стираются введённые ранее данные
04
Использование Выгрузить() для миллионов строк — чрезмерный расход памяти, лучше обход выборки
05
Попытка вызвать серверные методы запроса в клиентской процедуре управляемой формы
Контрольные точки

Как проверить результат

Количество строк после загрузки
Норма

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

Тревожный признак

Строк меньше или табличная часть пуста

Заполненность колонок
Норма

Все ключевые поля заполнены значениями

Тревожный признак

Колонки пустые при непустом запросе — не совпали имена

Сохранение прежних данных
Норма

Нужные строки сохранились или осознанно замещены

Тревожный признак

Пропали строки, введённые до загрузки

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

Частые вопросы

Чем отличается Выгрузить() от Выбрать() у результата запроса?

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

Почему после Загрузить() часть колонок табличной части пустая?

Метод Загрузить() сопоставляет данные по именам: колонка таблицы значений должна называться точно так же, как реквизит табличной части. Проверьте псевдонимы полей в запросе (секция «КАК») и приведите их к именам реквизитов.

Как добавить строки из запроса, не удаляя существующие?

Не используйте Загрузить() — он замещает все строки. Обойдите таблицу значений или выборку в цикле и добавляйте строки методом Добавить(), либо выгрузите текущую табличную часть, объедините таблицы и загрузите результат обратно.

Можно ли загрузить результат запроса с итогами в таблицу?

Да, но с итогами по группировкам Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам) вернёт дерево значений, а не плоскую таблицу. Для иерархии понадобится рекурсивный обход строк дерева.

Как показать результат запроса пользователю в управляемой форме?

Создайте реквизит формы типа «ТаблицаЗначений» с нужными колонками, в серверной процедуре выгрузите результат запроса и передайте его через ЗначениеВРеквизитФормы(). Альтернатива — динамический список с произвольным запросом, где выгрузка вообще не требуется.

Что делать, если запрос возвращает очень много строк?

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

Итог

Что важно запомнить

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