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