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