Как вызвать форму выбора справочника в 1С с отбором и запретом изменения данных?

Программист
← На главную

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

Решение этой задачи имеет свои особенности и напрямую зависит от того, какая технология построения интерфейса используется в вашей конфигурации — Обычные формы (ОФ) или Управляемые формы (УФ). Часто разработчики путают методы этих двух подсистем, что приводит к неприятным ошибкам выполнения, таким как Поле объекта не обнаружено. В этой статье мы подробно разберем, как правильно реализовать данный функционал для обеих платформ, проанализируем типичные ошибки и рассмотрим продвинутые приемы управления интерфейсом.

Выясним причины возникновения популярных ошибок и рассмотрим по шагам корректные алгоритмы реализации для каждого режима работы платформы.

---

Типичные ошибки разработчиков и их причины

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

  1. Прямая установка свойства Форма.ТолькоПросмотр = Истина в Обычных формах.

    Если в обычных формах полностью заблокировать форму через это свойство, платформа заблокирует абсолютно все интерактивные действия. В результате на командной панели пропадет стандартная кнопка «Выбрать», а при двойном клике на строку списка вместо выбора элемента будет открываться карточка этого элемента в режиме просмотра. Для пользователя форма выбора станет бесполезной, так как вернуть выбранное значение в поле ввода он не сможет.

  2. Смешение контекстов ОФ и УФ.

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

  3. Использование устаревшего метода ПолучитьФорму() в Управляемом приложении.

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

---

Решение для Обычных форм (ОФ)

В обычных формах для решения нашей задачи необходимо воздействовать не на саму форму выбора, а на табличное поле списка, которое в ней содержится. Таким образом мы сохраним работоспособность кнопки «Выбрать» и стандартное поведение при двойном клике, но запретим любые действия по изменению данных (добавление, копирование, изменение, удаление).

Рассмотрим пример кода, который вызывается в обработчике события НачалоВыбора поля ввода обычного интерфейса. Посмотрим, как правильно инициализировать форму, установить отбор по контрагенту и заблокировать редактирование:


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

Важный момент: свойства РазрешитьДобавление и РазрешитьИзменение блокируют добавление новых строк и редактирование существующих непосредственно в списке. При этом кнопка выбора остается активной, и двойной клик корректно возвращает ссылку на выбранное место обратно в документ.

---

Решение для Управляемых форм (УФ)

В управляемом интерфейсе (управляемое приложение) разработчику нет необходимости вручную перебирать элементы формы выбора и отключать доступность кнопок. Платформа 1С:Предприятие 8.3 предоставляет встроенные механизмы интеллектуальной обработки параметров формы. Если передать параметр ТолькоПросмотр = Истина при открытии формы выбора, платформа автоматически отключит кнопки «Создать», «Изменить», «Пометить на удаление» и аналогичные пункты контекстного меню в динамическом списке, но полностью сохранит весь функционал выбора.

Рассмотрим правильный шаблон кода для вызова управляемой формы выбора с установленным отбором и блокировкой редактирования:


&НаКлиенте
Процедура АдресНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Отключаем стандартную обработку открытия формы
    СтандартнаяОбработка = Ложь;
    
    // Шаг 1. Формируем структуру отбора по Контрагенту
    СтруктураОтбора = Новый Структура;
    СтруктураОтбора.Вставить("Контрагент", Объект.Контрагент);
    
    // Шаг 2. Заполняем параметры открываемой формы выбора
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", СтруктураОтбора);
    ПараметрыФормы.Вставить("ТолькоПросмотр", Истина); // Отключает добавление и редактирование
    ПараметрыФормы.Вставить("РежимВыбора", Истина);      // Указывает форме работать в режиме выбора
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина); // Закрывать форму после клика на элемент
    
    // Шаг 3. Вызываем форму выбора. 
    // Элемент (поле ввода) передается третьим параметром для автовозврата значения.
    ОткрытьФорму("Справочник.Места.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

Этот способ является наиболее производительным и соответствует стандартам разработки фирмы "1С", так как вся настройка и инициализация происходят за один клиент-серверный вызов при открытии формы.

---

Продвинутый вариант управления доступностью кнопок в УФ

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

Рассмотрим, как это сделать. Для начала напишем код открытия формы на стороне документа (вызывающей формы):


&НаКлиенте
Процедура АдресНачалоВыбораАльтернативный(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура("Контрагент", Объект.Contragent));
    
    // Передаем наш собственный параметр "РазрешитьСозданиеНовых"
    ПараметрыФормы.Вставить("РазрешитьСозданиеНовых", Ложь);
    
    ОткрытьФорму("Справочник.Места.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

Теперь перейдем в конфигураторе в модуль формы выбора справочника Места и пропишем логику обработки нашего параметра в событии ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем наличие нашего переданного параметра
    Если Параметры.Свойство("РазрешитьСозданиеНовых") И Не Параметры.РазрешитьСозданиеНовых Тогда
        
        // Отключаем возможность добавления элементов в динамическом списке "Список"
        Элементы.Список.РазрешитьДобавление = Ложь;
        
        // Дополнительно можно визуально скрыть стандартную кнопку создания на командной панели
        ЭлементКнопкаСоздать = Элементы.Найти("СписокКоманднаяПанельСоздать");
        Если ЭлементКнопкаСоздать <> Неопределено Тогда
            ЭлементКнопкаСоздать.Видимость = Ложь;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

---

Как надежно защитить отбор от изменения пользователем в УФ

Если передать отбор простым способом через структуру параметров (ПараметрыФормы.Вставить("Отбор", СтруктураОтбора)), то у пользователя на управляемой форме останется техническая возможность обойти это ограничение. Он может зайти в меню списка («Еще» -> «Настроить список»), увидеть наложенный отбор по контрагенту, снять с него флажок использования или вовсе удалить.

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

Для этого в модуле формы выбора справочника Места в обработчике ПриСозданииНаСервере реализуем следующий алгоритм:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли отбор стандартным образом
    Если Параметры.Свойство("Отбор") Тогда
        
        // Обходим все переданные ключи отбора
        Для Каждого ЭлементОтбораИзПараметров Из Параметры.Отбор Цикл
            
            ИмяПоляОтбора = ЭлементОтбораИзПараметров.Ключ;
            ЗначениеОтбора = ЭлементОтбораИзПараметров.Значение;
            
            // Добавляем элемент отбора напрямую в компоновщик настроек нашего динамического списка "Список"
            НовыйЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
            НовыйЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных(ИмяПоляОтбора);
            НовыйЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
            НовыйЭлементОтбора.ПравоеЗначение = ЗначениеОтбора;
            НовыйЭлементОтбора.Использование  = Истина;
            
            // Самый важный шаг: делаем этот отбор скрытым и недоступным для изменения пользователем
            НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
            
        КонецЦикла;
        
        // Очищаем стандартную коллекцию параметров отбора, 
        // чтобы платформа не попыталась наложить его повторно стандартным путем
        Параметры.Отбор.Очистить();
        
    КонецЕсли;
    
КонецПроцедуры

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

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

← На главную