Разработка и Конфигурация · 9 мин
Как в 1С загрузить выборку запроса в таблицу значений
Как выгрузить результат запроса 1С в таблицу значений: методы Выгрузить, ОбходРезультатаЗапроса, работа с итогами и деревом значений. Примеры кода и типичные ошибки.
Задача перенести результат запроса в таблицу значений встречается в 1С постоянно: при построении отчётов, обработках обмена данными, заполнении табличных частей на форме. Платформа делает это в одну строку — методом Выгрузить() у результата запроса, но у этого подхода есть важные нюансы: количество обходов, тип итогов, преобразование типов колонок и потребление памяти на больших объёмах.
Ключевое различие, которое нужно понимать сразу: выборка — это последовательный курсор по строкам результата, который читается только вперёд, а таблица значений — это полностью материализованная структура в памяти, к которой можно обращаться по индексу, сортировать, искать и сворачивать. Выгрузка в таблицу оправдана тогда, когда данные нужны многократно или в произвольном порядке.
Базовый способ: Выгрузить() результата запроса
Стандартная последовательность состоит из трёх шагов: создать объект Запрос, установить текст и параметры, выполнить и выгрузить. Метод Выгрузить() по умолчанию формирует «плоскую» таблицу значений без итоговых строк по группировкам.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить();
ТаблицаТоваров = РезультатЗапроса.Выгрузить();
Сообщить("Загружено строк: " + ТаблицаТоваров.Количество());
После выгрузки колонки таблицы значений получают имена полей запроса (по псевдонимам КАК), а типы колонок определяются автоматически по типам данных полей. Если поле может содержать составной тип (например, ссылка на разные справочники), колонка получит составной тип — это нормально, но может влиять на сортировку и сравнение.
Выгрузка с группировками и итогами
Если запрос содержит секцию ИТОГИ, поведение выгрузки зависит от параметра обхода. По умолчанию (ОбходРезультатаЗапроса.Прямой) в таблицу попадают только детальные записи, а итоговые строки теряются. Чтобы сохранить иерархию, укажите обход по группировкам.
// Плоская таблица только с детальными записями
ТЗ = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.Прямой);
// Таблица, где итоговые строки — обычные строки
ТЗСИтогами = РезультатЗапроса.Выгрузить(
ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
// Дерево значений с сохранением вложенности
Дерево = РезультатЗапроса.Выгрузить(
ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Обратите внимание: если нужна именно иерархическая структура (например, для вывода в дерево на форме), правильнее выгружать не в таблицу значений, а в дерево значений — тогда вложенные строки попадут в коллекцию Строки родительской строки. При выгрузке в таблицу значений иерархия «сплющивается», и восстановить её можно только по значениям группировочных полей.
Выгрузка в существующую таблицу или табличную часть
Частая ситуация — заполнить табличную часть документа или реквизит формы типа «ТаблицаЗначений». Здесь структура колонок уже задана, и простое присваивание результата Выгрузить() не подойдёт: типы реквизитов формы и произвольная таблица значений несовместимы напрямую.
Для табличной части объекта используйте метод Загрузить() — он сопоставляет колонки по именам и заполняет табличную часть из таблицы значений:
ТЗ = РезультатЗапроса.Выгрузить();
ДокументОбъект.Товары.Загрузить(ТЗ);
Для реквизита формы типа «ТаблицаЗначений» в управляемой форме используйте ЗначениеВРеквизитФормы(). Имена колонок в запросе должны совпадать с именами колонок табличной части — несовпадающие колонки просто игнорируются, что часто становится источником скрытых ошибок, когда данные «молча» не переносятся.
Когда таблица значений не нужна: обход выборки
Не каждая задача требует материализации результата. Если данные обрабатываются один раз и последовательно — например, выводятся в макет печатной формы или построчно записываются в регистр, — экономичнее работать напрямую с выборкой через Выбрать() и цикл Пока Выборка.Следующий() Цикл.
Таблица значений оправдана, когда нужно: многократно обращаться к данным, искать строки методом Найти() или НайтиСтроки(), сортировать, сворачивать, объединять с другой таблицей или передавать результат между процедурами. Правило простое: один проход — выборка, многократный произвольный доступ — таблица значений.
Сравнение вариантов
Минимальное потребление памяти, чтение только вперёд. Подходит для однократной последовательной обработки больших результатов.
Произвольный доступ, поиск, сортировка, свёртка. Требует памяти под весь результат — осторожно с большими выборками.
Сохраняет иерархию группировок. Подходит для отображения иерархических данных на форме, но сложнее в построчной обработке.
Производительность и память
Выгрузка результата запроса — это копирование всех данных в оперативную память сервера (или толстого клиента). На выборках в десятки тысяч строк это незаметно, но на сотнях тысяч строк с десятками колонок таблица значений может занять существенный объём памяти и замедлить сеанс.
Практические меры: выбирайте в запросе только реально нужные поля, отсекайте лишние строки условием ГДЕ на стороне СУБД, а не фильтрацией уже выгруженной таблицы. Если таблица нужна только для поиска по одному полю, после выгрузки добавьте индекс: ТЗ.Индексы.Добавить("Товар") — это многократно ускорит Найти() в цикле.
Как проверить результат
Совпадает с количеством записей, которое возвращает запрос в консоли запросов
Строк меньше — вероятно, лишние условия в запросе или потеряны итоги при обходе
Колонки названы по псевдонимам полей, типы соответствуют данным
Колонка пустая или тип неожиданный — проверьте псевдонимы и составные типы полей
Все ожидаемые колонки заполнены значениями
Часть колонок пустая — имена в запросе не совпадают с именами колонок табличной части
Загрузка данных из внешних источников в таблицу значений
Термин «выборка» иногда понимают шире — как любой набор данных, который нужно загрузить в таблицу значений: из файла Excel, CSV, результата COM-соединения или веб-сервиса. В этих случаях таблицу создают программно: сначала описывают колонки через ТаблицаЗначений.Колонки.Добавить() с указанием типа, затем в цикле добавляют строки через Добавить() и заполняют поля.
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(50)));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
// В цикле по источнику данных
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Артикул = ДанныеСтроки.Артикул;
НоваяСтрока.Количество = Число(ДанныеСтроки.Количество);
Явное указание типов колонок здесь важно: без ОписаниеТипов колонка получит произвольный тип, и сравнение, сортировка и свёртка могут работать непредсказуемо — например, числа, загруженные как строки, отсортируются лексикографически («10» окажется раньше «2»).
Что важно запомнить
Результат запроса выгружается в таблицу значений методом Выгрузить(). Для итогов указывайте обход по группировкам, для иерархии — выгружайте в дерево значений. Табличную часть заполняйте методом Загрузить() с совпадающими именами колонок. Для однократной последовательной обработки больших данных выгоднее обход выборки без выгрузки.
Частые вопросы
Как выгрузить результат запроса в таблицу значений на управляемой форме?
На серверной процедуре выполните запрос и вызовите Выгрузить(), затем перенесите таблицу в реквизит формы через ЗначениеВРеквизитФормы(ТаблицаЗначений, "ИмяРеквизита"). Напрямую присвоить таблицу значений реквизиту формы типа «ТаблицаЗначений» нельзя — типы несовместимы.
Почему после Выгрузить() в таблице нет итоговых строк?
По умолчанию используется прямой обход, который отдаёт только детальные записи. Передайте параметр ОбходРезультатаЗапроса.ПоГруппировкамСИерархией — тогда итоговые строки попадут в таблицу. Учтите, что в плоской таблице их нельзя будет отличить от детальных без дополнительного признака.
Можно ли выгрузить в таблицу значений с уже заданными колонками?
Метод Выгрузить() всегда создаёт новую таблицу с колонками по полям запроса. Если нужна конкретная структура, создайте таблицу вручную с описанием типов колонок и перенесите данные построчно, либо выгрузите результат и затем используйте метод Загрузить() у целевой табличной части — он сопоставит колонки по именам.
Что быстрее: обход выборки или выгрузка в таблицу значений?
Для однократной последовательной обработки обход выборки экономичнее по памяти и обычно не медленнее. Выгрузка оправдана, когда к данным нужен повторный или произвольный доступ: поиск, сортировка, свёртка. На больших результатах выгрузка дополнительно нагружает память сервера.
Как найти строку в выгруженной таблице по значению?
Используйте ТЗ.Найти(Значение, "ИмяКолонки") для первой подходящей строки или ТЗ.НайтиСтроки(СтруктураОтбора) для всех совпадений. Если поиск выполняется многократно в цикле, предварительно добавьте индекс: ТЗ.Индексы.Добавить("ИмяКолонки") — это существенно ускоряет поиск на больших таблицах.
Ошибка «Метод объекта не обнаружен (Выгрузить)» — в чём причина?
Метод Выгрузить() есть у объекта РезультатЗапроса, а не у выборки. Проверьте, что вызываете его у значения, возвращённого методом Запрос.Выполнить(), а не у результата метода Выбрать(). Также ошибка возникает, если переменная не инициализирована или запрос вернул Неопределено из-за исключения.