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

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

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

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

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

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

Базовый способ: Выгрузить() результата запроса

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

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Товар,

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

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления";

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

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

Сообщить("Загружено строк: " + ТаблицаТоваров.Количество());

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

Выгрузка с группировками и итогами

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

// Плоская таблица только с детальными записями

ТЗ = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.Прямой);

// Таблица, где итоговые строки — обычные строки

ТЗСИтогами = РезультатЗапроса.Выгрузить(

ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

// Дерево значений с сохранением вложенности

Дерево = РезультатЗапроса.Выгрузить(

ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

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

Выгрузка в существующую таблицу или табличную часть

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

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

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

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

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

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

Когда таблица значений не нужна: обход выборки

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

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

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

Обход выборки (Выбрать + Следующий)

Минимальное потребление памяти, чтение только вперёд. Подходит для однократной последовательной обработки больших результатов.

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

Произвольный доступ, поиск, сортировка, свёртка. Требует памяти под весь результат — осторожно с большими выборками.

Выгрузить() в дерево значений

Сохраняет иерархию группировок. Подходит для отображения иерархических данных на форме, но сложнее в построчной обработке.

Производительность и память

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

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

Контрольные точки

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

Количество строк в таблице
Норма

Совпадает с количеством записей, которое возвращает запрос в консоли запросов

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

Строк меньше — вероятно, лишние условия в запросе или потеряны итоги при обходе

Имена и типы колонок
Норма

Колонки названы по псевдонимам полей, типы соответствуют данным

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

Колонка пустая или тип неожиданный — проверьте псевдонимы и составные типы полей

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

Все ожидаемые колонки заполнены значениями

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

Часть колонок пустая — имена в запросе не совпадают с именами колонок табличной части

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

Термин «выборка» иногда понимают шире — как любой набор данных, который нужно загрузить в таблицу значений: из файла Excel, CSV, результата COM-соединения или веб-сервиса. В этих случаях таблицу создают программно: сначала описывают колонки через ТаблицаЗначений.Колонки.Добавить() с указанием типа, затем в цикле добавляют строки через Добавить() и заполняют поля.

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(50)));

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

// В цикле по источнику данных

НоваяСтрока = ТЗ.Добавить();

НоваяСтрока.Артикул = ДанныеСтроки.Артикул;

НоваяСтрока.Количество = Число(ДанныеСтроки.Количество);

Явное указание типов колонок здесь важно: без ОписаниеТипов колонка получит произвольный тип, и сравнение, сортировка и свёртка могут работать непредсказуемо — например, числа, загруженные как строки, отсортируются лексикографически («10» окажется раньше «2»).

Итог

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

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

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

Как выгрузить результат запроса в таблицу значений на управляемой форме?

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

Почему после Выгрузить() в таблице нет итоговых строк?

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

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

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

Что быстрее: обход выборки или выгрузка в таблицу значений?

Для однократной последовательной обработки обход выборки экономичнее по памяти и обычно не медленнее. Выгрузка оправдана, когда к данным нужен повторный или произвольный доступ: поиск, сортировка, свёртка. На больших результатах выгрузка дополнительно нагружает память сервера.

Как найти строку в выгруженной таблице по значению?

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

Ошибка «Метод объекта не обнаружен (Выгрузить)» — в чём причина?

Метод Выгрузить() есть у объекта РезультатЗапроса, а не у выборки. Проверьте, что вызываете его у значения, возвращённого методом Запрос.Выполнить(), а не у результата метода Выбрать(). Также ошибка возникает, если переменная не инициализирована или запрос вернул Неопределено из-за исключения.