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