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