Параметры в запросах 1С 8.3: передача значений, списков и таблиц из кода
Содержание
Чтобы установить параметр
запроса в 1С, в тексте запроса пишут имя с амперсандом (&Организация), а в коде до вызова Выполнить() передают значение: Запрос.УстановитьПараметр("Организация", ВыбраннаяОрганизация). Имя в методе указывают без &, регистр букв не важен. Если хотя бы один параметр из текста остался без значения, запрос упадёт при выполнении.
Типичная ситуация: отчёт по остаткам работал, пока его не попросили фильтровать по складу. Вы дописали условие в текст, а значение склада в запрос не передали, и пользователь видит ошибку.
Как объект Запрос получает параметры
У объекта Запрос три свойства, с которыми работают постоянно:
- 📝
Текст— строка на языке запросов, где параметры отмечены амперсандом; - 📦
Параметры— коллекция значений, имеет типСтруктура: ключ — имя параметра, значение — то, что подставится в запрос; - 🗂
МенеджерВременныхТаблиц— нужен, если запрос создаёт временные таблицы или читает их из другого запроса.
Минимальный рабочий пример выглядит так:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Контрагент,
| Контрагенты.ИНН КАК ИНН
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.ИНН = &ИНН
| И НЕ Контрагенты.ПометкаУдаления";
Запрос.УстановитьПараметр("ИНН", "7707083893");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Контрагент);
КонецЦикла;
Объект Запрос доступен на сервере, в толстом клиенте и во внешнем соединении. В управляемой форме код с запросом выносят в процедуру с директивой &НаСервере или в общий серверный модуль. На тонком клиенте конструктор Новый Запрос недоступен.
Зачем вообще параметры, если можно склеить строку? Склейка ломается на ссылках, датах и строках с кавычками, а значение из поля ввода превращается в кусок текста запроса. Параметр передаётся как значение нужного типа, без разбора текста.
Синтаксис УстановитьПараметр и коллекции Параметры
Сигнатура метода простая:
Запрос.УстановитьПараметр(<Имя>, <Значение>);
<Имя>— строка, совпадающая с именем в тексте без&. Должна быть корректным идентификатором: буквы, цифры, подчёркивание, первой не цифра.<Значение>— значение любого типа, который понимает язык запросов: ссылка, число, строка, дата, булево,Неопределено,Тип,Граница,МоментВремени, а также коллекции (о них в следующем разделе).
Повторный вызов с тем же именем просто перезапишет значение. Это удобно, когда один объект Запрос выполняют в цикле с разными параметрами: текст не меняется, меняется только значение.
Поскольку Запрос.Параметры — это структура, к ней применимы обычные методы структуры:
// то же самое, что УстановитьПараметр
Запрос.Параметры.Вставить("Склад", Склад);
// проверить, передали ли значение
Если Не Запрос.Параметры.Свойство("Склад") Тогда
ВызватьИсключение "Не передан склад";
КонецЕсли;
Лишний параметр, который есть в коллекции, но не упоминается в тексте, ошибки не вызывает. Обратное правило строгое: всё, что упомянуто в тексте, должно быть передано.
Даты и периоды
Дата в 1С всегда содержит время. Условие Документ.Дата <= &КонецПериода с датой 31.03.2026 00:00:00 отрежет все документы, проведённые 31 марта днём. Поэтому конец периода передают так:
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));
Для виртуальных таблиц остатков часто нужно включить в расчёт движения самого момента. Для этого вместо даты передают границу:
Запрос.УстановитьПараметр("Период",
Новый Граница(КонецДня(ДатаОстатков), ВидГраницы.Включая));
Если нужны остатки строго на момент конкретного документа, передают Документ.МоментВремени() или Новый Граница(Документ.МоментВремени(), ВидГраницы.Исключая) — без движений самого документа.
Строки и ПОДОБНО
Для поиска по части наименования шаблон собирают в коде, а в тексте оставляют только параметр:
// в тексте: ГДЕ Номенклатура.Наименование ПОДОБНО &Шаблон
Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%");
Если пользователь может ввести символы %, _ или [, их нужно экранировать и указать в тексте ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~", иначе они сработают как подстановочные.
Передаём списки, массивы и таблицы значений
Одним параметром можно передать сразу набор значений. Сравнение тогда пишут через В:
// в тексте: ГДЕ Остатки.Склад В (&Склады)
Склады = Новый Массив;
Склады.Добавить(СкладОсновной);
Склады.Добавить(СкладРозница);
Запрос.УстановитьПараметр("Склады", Склады);
Что подходит для условия В (&Параметр):
| Тип значения | Когда удобен | На что смотреть |
|---|---|---|
Массив | значения набраны в коде | самый лёгкий вариант |
ФиксированныйМассив | значения пришли из реквизита формы или кэша | работает так же, как массив |
СписокЗначений | значения выбраны пользователем в форме | берутся значения, представления игнорируются |
ТаблицаЗначений | нужен отбор по колонке готовой таблицы | передавайте таблицу из одной колонки или выгрузку колонки в массив |
Частый приём — выгрузить колонку и передать массив: ТЗ.ВыгрузитьКолонку("Номенклатура"). Пустой массив допустим: условие В просто не найдёт ни одной строки.
Таблица значений как источник данных
Таблицу значений можно передать в запрос не только для отбора, но и как полноценный источник. Её помещают во временную таблицу, а затем соединяют с данными базы:
МВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст =
"ВЫБРАТЬ
| Т.Номенклатура КАК Номенклатура,
| Т.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Строки
|ИЗ
| &ТаблицаСтрок КАК Т";
Запрос.УстановитьПараметр("ТаблицаСтрок", ТаблицаСтрок);
Запрос.Выполнить();
Колонки такой таблицы должны иметь заданный тип значения. Если создать колонку через ТЗ.Колонки.Добавить("Количество") без описания типов, запрос не сможет определить тип поля и выдаст ошибку. Правильно так:
ТаблицаСтрок.Колонки.Добавить("Номенклатура",
Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТаблицаСтрок.Колонки.Добавить("Количество",
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Таблица, полученная из табличной части через Выгрузить(), типы уже содержит, ничего дописывать не нужно.
Параметры в конструкторе запроса
Конструктор запроса открывают в Конфигураторе или в редакторе модуля: поставьте курсор внутрь текста запроса или на пустую строку, вызовите контекстное меню и выберите «Конструктор запроса». Есть и вариант «Конструктор запроса с обработкой результата» — он сразу сгенерирует код с объектом Запрос, циклом по выборке и строками УстановитьПараметр.
Где параметры появляются в конструкторе
- Вкладка «Условия». Перетащите поле в список условий. Конструктор сам подставит параметр с именем поля, например
Склад = &Склад. Имя можно исправить прямо в строке условия. - Произвольное условие. Включите флажок «Произвольное» и напишите выражение вручную, например
Остатки.КоличествоОстаток > &МинимальныйОстаток. - Параметры виртуальной таблицы. Выделите таблицу
ОстаткиилиОстаткиИОборотыв списке выбранных таблиц и нажмите кнопку «Параметры виртуальной таблицы». В поле периода впишите&Период, в условие —Склад = &Склад. - Вычисляемые поля. Параметр можно использовать и в выражении поля, например
&ДатаОтчета КАК ДатаОтчета.
Отбор по складу лучше ставить в параметры виртуальной таблицы Остатки, а не в ГДЕ. Тогда платформа отфильтрует данные при расчёте остатков, а не после него, и запрос будет работать заметно быстрее на больших регистрах.
После нажатия «ОК» конструктор вернёт только текст. Строки УстановитьПараметр за вас допишет лишь вариант «с обработкой результата». В обычном режиме перечислите параметры сами: самый надёжный способ — пройтись поиском по тексту на символ &.
Необязательный отбор: параметр, который могут не заполнить
В отчётах и обработках пользователь часто оставляет поле отбора пустым и ждёт, что увидит «всё». Есть два рабочих подхода.
Условие в самом тексте. Передаёте параметр всегда, а в тексте учитываете пустое значение:
// в тексте:
// ГДЕ (&Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
// ИЛИ Документ.Контрагент = &Контрагент)
Запрос.УстановитьПараметр("Контрагент", Контрагент);
Текст один, но такое условие хуже использует индексы на больших таблицах.
Сборка текста в коде. Условие добавляют, только если отбор задан:
ТекстУсловия = "";
Если ЗначениеЗаполнено(Контрагент) Тогда
ТекстУсловия = " И Документ.Контрагент = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", Контрагент);
КонецЕсли;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "//УсловиеКонтрагент", ТекстУсловия);
Здесь в тексте заранее ставят маркер-комментарий //УсловиеКонтрагент после основного условия ГДЕ. Значение по-прежнему идёт через параметр, склеивается только служебная часть текста.
| Подход | Плюсы | Минусы |
|---|---|---|
Условие с ИЛИ в тексте | один текст, легко читать и отлаживать | на больших объёмах медленнее |
| Сборка текста в коде | оптимальный план запроса | текст сложнее проверить в конструкторе |
Параметры запроса в СКД и динамическом списке
Не каждый запрос в конфигурации выполняется через Новый Запрос. В отчётах на системе компоновки данных (СКД) и в формах списков с динамическим списком текст запроса тот же, а передача параметров устроена иначе: УстановитьПараметр там нет.
Отчёт на СКД. Когда вы пишете &Период в тексте набора данных, параметр автоматически появляется на вкладке «Параметры» схемы. Там задают его заголовок, тип, значение по умолчанию и флажок ограничения доступности. Из кода значение передают через настройки:
Настройки = КомпоновщикНастроек.Настройки;
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Период", КонецДня(Дата));
Динамический список в форме. Если у реквизита формы типа ДинамическийСписок включён произвольный запрос с параметром, значение передают в обработчике формы, обычно ПриСозданииНаСервере:
Список.Параметры.УстановитьЗначениеПараметра("Склад", Склад);
Если в динамическом списке параметр не установлен, список не покажет данных. При открытии такой формы пользователь видит пустую таблицу без понятного сообщения, поэтому ищите пропущенный параметр в первую очередь.
Отладка: проверяем, что попало в параметры
Когда запрос возвращает не то, первое подозрение — значения параметров. Проверяют так:
- Поставьте точку останова на строке
Запрос.Выполнить()(клавишаF9в Конфигураторе) и запустите отладку. - Выделите
Запрос.Параметрыи откройте окно вычисления выражения (Shift+F9). Раскройте структуру: видно каждое имя, значение и его тип. - Проверьте типы. Если вместо ссылки на склад лежит строка с наименованием или число, условие не сработает, хотя ошибки не будет.
- Для сверки списка имён вычислите
Запрос.НайтиПараметры(). Метод возвращает описание всех параметров, найденных в тексте, — его удобно сравнить с тем, что лежит вЗапрос.Параметры.
Чтобы прогнать запрос отдельно от кода, скопируйте Запрос.Текст из окна вычисления в консоль запросов (внешняя обработка для разработчиков), задайте там параметры вручную и посмотрите результат. Так быстро становится понятно, где проблема: в тексте или в значениях, которые передаёт код.
Ошибки при установке параметров и как их исправить
Ещё две ловушки, которые встречаются при доработке чужого кода:
- 🔁 Пакетный запрос. Параметры общие для всех запросов пакета. Один и тот же
&Периодв первом и третьем запросе получит одно значение — передать разные под одним именем нельзя, дайте им разные имена. - 🧩 Один объект
Запросв цикле. Значения с прошлой итерации остаются в коллекции. Если на очередном шаге отбор не нужен, а условие в тексте осталось, сработает старое значение. Перед каждой итерацией либо переустанавливайте все параметры, либо очищайте коллекцию:Запрос.Параметры.Очистить().
Можно ли использовать один параметр в тексте несколько раз?
&Организация может стоять и в условии виртуальной таблицы, и в ГДЕ, и в поле выборки. Значение передают один раз.Можно ли передать в параметр тип, а не значение?
Тип, например Тип("ДокументСсылка.РеализацияТоваровУслуг"), и сравнивайте в тексте через ТИПЗНАЧЕНИЯ(Поле) = &ТипДокумента.Как передать пустую ссылку?
Справочники.Склады.ПустаяСсылка(). В тексте запроса параметр не нужен, можно написать ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка).Сколько значений можно передать в условие В?
Почему параметр не подставляется в текст при просмотре Запрос.Текст?
Запрос.Параметры и передаются платформе при выполнении.