Как правильно проверить выбранный тип данных при обработке выбора составного значения в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Выясним причину поведения платформы

Проанализируем механику работы поля ввода составного типа. Интерактивный выбор в таком поле выполняется платформой в два отдельных этапа:

  1. Выбор типа данных. Если в поле еще не определен конкретный тип, платформа открывает системное окно «Выбор типа данных». Как только пользователь указывает тип (например, справочник «Контрагенты»), платформа вызывает обработчик ОбработкаВыбора. В параметр ВыбранноеЗначение при этом передается не ссылка на элемент, а сам объект описания типа — значение типа Тип.
  2. Выбор конкретной ссылки. Платформа открывает форму выбора выбранного справочника. После выбора строки обработчик ОбработкаВыбора вызывается повторно, и только теперь в параметр ВыбранноеЗначение помещается ссылка (например, СправочникСсылка.Контрагенты).

Когда разработчик пишет условие вида ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Контрагенты") на первом этапе, платформа выполняет функцию ТипЗнч() над объектом, который уже сам является типом. Типом значения типа Тип является системный тип Тип, а вовсе не ссылка на справочник. В результате условие не выполняется.

Способ 1. Прямое сравнение выбранного типа

Если нам необходимо перехватить именно выбор типа в обработчике события, сравнение следует выполнять напрямую с результатом функции Тип(), без использования функции ТипЗнч():


Если ВыбранноеЗначение = Тип("СправочникСсылка.Контрагенты") Тогда
    // Пользователь только что выбрал тип "Контрагенты" в диалоге выбора типа
    Возврат;
ИначеЕсли ВыбранноеЗначение = Тип("СправочникСсылка.Пользователи") Тогда
    // Пользователь выбрал тип "Пользователи"
    Возврат;
КонецЕсли;

После отсечения первого шага на втором шаге в процедуру придет ссылка. Для нее уже будет корректно работать привычная конструкция с ТипЗнч():


Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Контрагенты") Тогда
    СправочникСотрудников = "Справочник.Контрагенты";
ИначеЕсли ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Пользователи") Тогда
    СправочникСотрудников = "Справочник.Пользователи";
КонецЕсли;

Способ 2. Универсальное отсечение промежуточного шага выбора типа

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


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

Такой подход универсален: если состав типов реквизита расширится в будущем, алгоритм не сломается и не потребует добавления новых условий выхода.

Способ 3. Перенос логики в событие «ПриИзменении»

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

  1. Событие ПриИзменении вызывается платформой один раз — строго после того, как пользователь завершил оба шага выбора (или выбрал значение быстрым вводом по строке).
  2. Внутри обработчика реквизит уже гарантированно содержит ссылку нужного типа либо пустое значение, что полностью исключает путаницу между объектом типа и самой ссылкой.

Рекомендации по оптимизации запросов и заполнению табличной части

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

  1. Динамическая подстановка таблиц: Склеивание строк вида "+ ИмяТаблицы +" КАК Источник" лишает запрос статической проверки синтаксиса. Если типов немного, надежнее использовать конструкцию ВЫБРАТЬ ... ИЗ Справочник.Контрагенты ГДЕ ... ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ... ИЗ Справочник.Пользователи либо разделять логику на два отдельных запроса.
  2. Заполнение табличной части: Вместо построчного добавления строк в цикле через ТабличнаяЧасть.Добавить() эффективнее использовать метод Загрузить(), передавая в него выгруженную таблицу значений запроса. Это существенно ускоряет работу формы при большом количестве строк.
← На главную