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