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