Как программно ограничить выбор в колонке с составным типом данных и убрать окно «Выбор типа» в 1С?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

В этой статье мы подробно разберем, как автоматизировать этот процесс, исключить лишние клики и сделать интерфейс более профессиональным и удобным.

Метод 1. Использование события НачалоВыбора

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

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

В этом обработчике мы выполним следующую логику:

  1. Проанализируем текущую строку табличной части.
  2. Определим значение в колонке ТипМатериала.
  3. Установим параметр СтандартнаяОбработка в значение Ложь, чтобы подавить системное окно выбора типа.
  4. Вызовем метод ОткрытьФорму с указанием конкретной формы выбора нужного справочника.

Проанализируем пример кода, который решает эту задачу:


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

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

Метод 2. Динамическое ограничение типа (TypeRestriction)

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

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

Разберем, как это реализовать в событии ПриАктивизацииСтроки табличной части. Это событие срабатывает каждый раз, когда пользователь переходит с одной строки на другую.


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

Выясним преимущество этого метода: установив ОграничениеТипа, мы также автоматически настраиваем механизм автоподбора. Теперь, если пользователь начнет вводить буквы, 1С будет искать совпадения только в том справочнике, который соответствует выбранному типу материала, не предлагая искать везде.

Метод 3. Очистка значений при смене типа

Проанализируем ситуацию, которую часто забывают обработать: пользователь сначала выбрал «Материал» и подобрал товар из справочника «Номенклатура», а затем передумал и изменил «Тип материала» на «Спецификация». В этом случае в колонке Название останется ссылка на Номенклатуру, что приведет к логической ошибке или отображению текста «Объект не обнаружен», так как тип данных в ячейке больше не соответствует выбранной категории.

Чтобы избежать этой проблемы, обязательно добавим обработчик события ПриИзменении для колонки ТипМатериала. Рассмотрим пример:


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

Подведем итоги

Для решения задачи программного управления составным типом в 1С мы рассмотрели два основных пути. Первый путь (через НачалоВыбора) проще в реализации «здесь и сейчас», если вам нужно просто открыть форму. Второй путь (через ОграничениеТипа) является более «правильным» с точки зрения архитектуры платформы 8.3, так как он задействует встроенные механизмы проверки типов и автоподбора.

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

Также не забывайте про свойство Связи параметров выбора в палитре свойств метаданных. В некоторых случаях, если типы данных связаны иерархически, задачу можно решить вообще без написания кода, просто указав связь колонки Название с колонкой ТипМатериала.

← На главную