К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как заполнить табличную часть документа в 1С запросом

Как заполнить табличную часть документа в 1С запросом: выборка из запроса, метод Загрузить, обход через Выгрузить, примеры кода на встроенном языке и типичные ошибки.

Заполнение табличной части документа или справочника результатом запроса — одна из самых частых задач при доработке конфигураций 1С. Типовой сценарий: пользователь нажимает кнопку «Заполнить», система выполняет запрос к остаткам, задолженности или другому документу и подставляет полученные строки в таблицу. Такой подход быстрее ручного ввода и исключает ошибки оператора.

На встроенном языке задача решается двумя способами: построчным обходом выборки из запроса с добавлением строк через метод Добавить() либо массовой загрузкой через Выгрузить() и Загрузить(). Выбор зависит от того, совпадают ли имена колонок результата запроса с именами реквизитов табличной части и нужна ли дополнительная обработка каждой строки.

Ниже разобраны оба подхода с рабочими примерами кода, показано, как организовать заполнение по кнопке на управляемой форме, какие проверки выполнить до записи документа и какие ошибки встречаются чаще всего.

Как устроена задача: запрос, выборка и табличная часть

Табличная часть объекта в 1С — это коллекция строк, каждая из которых содержит набор реквизитов (Номенклатура, Количество, Цена и т.д.). Запрос возвращает таблицу значений или выборку. Задача программиста — перенести данные из результата запроса в коллекцию строк объекта, соблюдая соответствие типов и имён полей.

Важно различать контекст выполнения. На сервере вы работаете с объектом (ДокументОбъект), у которого табличная часть доступна напрямую. На клиенте управляемой формы доступны только данные формы, поэтому запрос всегда выполняется в серверной процедуре, а результат возвращается в форму. Попытка выполнить запрос на клиенте приведёт к ошибке компиляции.

Способ 1: построчное заполнение через обход выборки

Этот вариант универсален: имена полей запроса могут не совпадать с реквизитами табличной части, а каждую строку перед добавлением можно дополнительно обработать — пересчитать сумму, подставить значение по умолчанию, пропустить ненужные записи.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Остатки.Номенклатура КАК Номенклатура,

| Остатки.КоличествоОстаток КАК Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки

|ГДЕ

| Остатки.КоличествоОстаток > 0";

Запрос.УстановитьПараметр("Период", Объект.Дата);

Запрос.УстановитьПараметр("Склад", Объект.Склад);

Выборка = Запрос.Выполнить().Выбрать();

Объект.Товары.Очистить();

Пока Выборка.Следующий() Цикл

НоваяСтрока = Объект.Товары.Добавить();

НоваяСтрока.Номенклатура = Выборка.Номенклатура;

НоваяСтрока.Количество = Выборка.Количество;

КонецЦикла;

Обратите внимание на вызов Очистить() перед циклом: если кнопку «Заполнить» нажмут повторно, без очистки строки задвоятся. Если документ уже содержит введённые вручную строки, которые нужно сохранить, очистку не выполняют либо предварительно спрашивают пользователя.

Плюс подхода — полный контроль над каждой строкой. Минус — на больших объёмах (десятки тысяч строк) построчное добавление работает медленнее массовой загрузки, а на клиент-серверном варианте каждая модификация объекта может тянуть за собой дополнительные вызовы.

Способ 2: массовая загрузка через Выгрузить и Загрузить

Когда структура результата запроса совпадает со структурой табличной части, строки переносятся одной командой. Метод Загрузить() сопоставляет колонки по именам, поэтому в тексте запроса поля именуются через КАК точно как реквизиты табличной части.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Долг.Контрагент КАК Контрагент,

| Долг.СуммаОстаток КАК Сумма

|ИЗ

| РегистрНакопления.РасчетыСКонтрагентами.Остатки(&Период, Организация = &Организация) КАК Долг";

Запрос.УстановитьПараметр("Период", КонецДня(Объект.Дата));

Запрос.УстановитьПараметр("Организация", Объект.Организация);

Объект.Контрагенты.Загрузить(Запрос.Выполнить().Выгрузить());

Метод Загрузить() полностью замещает содержимое табличной части — предварительно вызывать Очистить() не нужно. Если требуется добавить строки к существующим, используют Выгрузить() в таблицу значений и обход с добавлением, либо метод ЗагрузитьКолонку() для отдельных реквизитов.

Заполнение по кнопке на управляемой форме

В типовых конфигурациях на управляемых формах запрос нельзя выполнить на клиенте. Стандартная схема: команда формы вызывает серверную процедуру, которая забирает объект из реквизита формы, заполняет его и возвращает обратно.

&НаКлиенте

Процедура ЗаполнитьПоОстаткам(Команда)

ЗаполнитьПоОстаткамНаСервере();

КонецПроцедуры

&НаСервере

Процедура ЗаполнитьПоОстаткамНаСервере()

ДокументОбъект = РеквизитФормыВЗначение("Объект");

// здесь запрос и заполнение табличной части

ЗаполнитьТабличнуюЧасть(ДокументОбъект);

ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

КонецПроцедуры

Оформление логики заполнения отдельной процедурой в модуле объекта — хорошая практика: тогда тот же код можно вызвать из обработки, регламентного задания или при программном создании документа, не дублируя текст запроса.

Порядок действий
  1. 1
    Создайте в модуле объекта экспортную процедуру заполнения с текстом запроса
  2. 2
    Получите параметры запроса из шапки документа (дата, организация, склад)
  3. 3
    Выполните запрос и заполните табличную часть через Загрузить() или цикл с Добавить()
  4. 4
    Добавьте на форму команду и кнопку, свяжите с серверным вызовом
  5. 5
    Проверьте заполнение на новом документе и на документе с уже введёнными строками

Проверка результата и контроль ошибок

Перед записью документа убедитесь, что запрос вернул осмысленные данные. Пустой результат — не всегда ошибка, но пользователь должен об этом узнать, а не получить молча очищенную таблицу. Проверяйте РезультатЗапроса.Пустой и сообщайте о ситуации через Сообщить() или вызов исключения с понятным текстом.

Также контролируйте типы данных. Если запрос возвращает NULL (например, из левого соединения), присвоение его реквизиту строки даст неожиданное значение. Используйте функцию ЕСТЬNULL() в тексте запроса для полей, которые могут быть не заполнены.

Контрольные точки

Как проверить результат

Количество строк после заполнения
Норма

Совпадает с количеством строк результата запроса в консоли запросов

Тревожный признак

Строк меньше — вероятно, отбор в запросе отсек часть данных, или строки задвоились

Значения колонок
Норма

Суммы и количества совпадают с отчётом по регистру за тот же период

Тревожный признак

Пустые значения или NULL — проверьте ЕСТЬNULL и соединения таблиц

Повторное нажатие кнопки
Норма

Таблица замещается, строки не дублируются

Тревожный признак

Строки добавляются к существующим — нет Очистить() или используется цикл вместо Загрузить()

Типичные ошибки и ограничения

Самая частая проблема — несовпадение псевдонимов запроса с именами реквизитов при использовании Загрузить(). Ошибки выполнения не возникает, но колонки остаются пустыми, и документ записывается с незаполненными строками. Всегда сверяйте псевдонимы с метаданными табличной части.

Вторая группа ошибок связана с датами. Остатки на дату документа нужно брать с учётом того, что сам документ может быть уже проведён: используйте &Период как границу или момент времени, иначе документ «увидит» собственные движения. Третья типичная ситуация — попытка выполнить запрос в клиентской процедуре управляемой формы, что приводит к ошибке компиляции модуля.

Типичные ошибки
01
Нет Очистить() перед циклом добавления — при повторном заполнении строки дублируются
02
Псевдоним колонки запроса не совпадает с именем реквизита — Загрузить() оставляет колонку пустой без сообщения об ошибке
03
Запрос выполняется в клиентской процедуре управляемой формы — ошибка компиляции, нужен вызов сервера
04
Остатки берутся без учёта проведённости самого документа — задваивание количества при перезаполнении
05
NULL из левого соединения попадает в реквизит строки — используйте ЕСТЬNULL в запросе

Альтернативы: когда запрос не нужен

Не каждое заполнение требует запроса. Если данные берутся из одного документа-основания, достаточно обойти его табличную часть в цикле — запрос к СУБД здесь избыточен. Если заполнение идёт по произвольным данным из файла или внешнего источника, используют загрузку из таблицы значений, сформированной программно.

Сравнение вариантов

Цикл по выборке + Добавить()

Подходит, когда имена полей не совпадают, нужна обработка каждой строки или фильтрация. Медленнее на больших объёмах.

Загрузить(Выгрузить())

Оптимально при совпадении структуры результата и табличной части. Одна строка кода, высокая скорость, но нет построчной обработки.

Обход табличной части основания

Для ввода на основании без обращения к регистрам. Проще и не грузит СУБД лишним запросом.

Для сложных сценариев — например, заполнение нескольких табличных частей одним нажатием — удобно собрать пакетный запрос: каждый запрос пакета заполняет свою таблицу, а обход результатов выполняется через Выбрать() с указанием индекса результата.

Итог

Что важно запомнить

Запрос выполняйте на сервере, результат переносите через Загрузить() при совпадении имён колонок или циклом с Добавить() при необходимости обработки строк. Перед заполнением очищайте таблицу, в запросе используйте ЕСТЬNULL и корректные параметры периода. Отлаживайте на копии базы.

Частые вопросы

Можно ли заполнить табличную часть запросом без программирования?

В типовых конфигурациях многие документы уже имеют штатные кнопки «Заполнить» (по остаткам, по задолженности, по документу-основанию). Если штатной команды нет, без доработки кода обойтись нельзя — потребуется процедура на встроенном языке или внешняя обработка заполнения табличных частей, подключаемая через механизм дополнительных отчетов и обработок БСП.

Почему после Загрузить() колонки табличной части пустые?

Имена колонок результата запроса не совпадают с именами реквизитов табличной части. Метод Загрузить() сопоставляет данные по именам и молча пропускает несовпадающие колонки. Проверьте псевдонимы после КАК в тексте запроса и сравните их с именами реквизитов в конфигураторе.

Как заполнить табличную часть, не очищая существующие строки?

Используйте цикл по выборке с методом Добавить() и не вызывайте Очистить(). Если нужно избежать дублей, перед добавлением ищите строку с тем же ключом через Найти() или НайтиСтроки() по реквизиту, например по номенклатуре, и обновляйте найденную строку вместо добавления новой.

Как передать результат запроса с сервера на клиент управляемой формы?

Напрямую таблицу значений в клиентскую процедуру передавать не требуется: серверная процедура заполняет объект через РеквизитФормыВЗначение и возвращает его через ЗначениеВРеквизитФормы — форма обновится автоматически. Если данные нужны отдельно, серверная функция может вернуть массив структур или поместить таблицу во временное хранилище.

Что быстрее: обход выборки или Загрузить()?

Массовая загрузка через Выгрузить() и Загрузить() быстрее, особенно на тысячах строк, так как данные переносятся одним вызовом без построчного обращения к коллекции. Разница заметна при объёмах от нескольких тысяч строк; на небольших таблицах выбирайте способ по удобству сопровождения кода.

Как отладить текст запроса перед вставкой в код?

Используйте консоль запросов (в типовых конфигурациях на БСП она доступна через «Инструменты разработчика» или как внешняя обработка). Сформируйте запрос с теми же параметрами, проверьте состав и значения строк, затем перенесите текст в модуль. Это исключает отладку вслепую через сообщения.