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