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

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

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

Сложность заключается в том, что на клиенте (в процедуре &НаКлиенте) мы имеем доступ только к самой ссылке. Попытка обратиться «через точку» к реквизиту справочника (например, Объект.Контрагент.ЮрФизЛицо) вызовет ошибку, так как данные объекта находятся на сервере в базе данных. Проанализируем ситуацию и разберем несколько способов решения этой задачи: от классического серверного вызова до продвинутых методов оптимизации.

Способ 1. Создание серверной функции (Классический подход)

Самый правильный и распространенный способ — это вынос логики проверки на сервер. Для этого мы создаем вспомогательную функцию. Важно использовать директиву &НаСервереБезКонтекста, так как она работает быстрее, не передавая всю форму на сервер.

Рассмотрим пример, где в документе есть реквизит РеквизитДок1 (ссылка на справочник), и нам нужно проверить его внутренний реквизит РеквизитСпр1 на соответствие определенному значению перечисления.


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

&НаСервереБезКонтекста
Функция ЭтоНужноеЗначениеНаСервере(СсылкаНаСправочник)
    
    // На сервере нам доступны реквизиты через точку
    Возврат СсылкаНаСправочник.РеквизитСпр1 = Перечисления.ИмяВашегоПеречисления.ЗначениеПеречис3;
    
КонецФункции

Разберем, почему это работает. Функция ЭтоНужноеЗначениеНаСервере принимает ссылку, обращается к базе данных, считывает значение перечисления и возвращает логический результат (Истина или Ложь) обратно на клиент.

Способ 2. Использование функций Библиотеки стандартных подсистем (БСП)

Если вы работаете в современной конфигурации (например, УТ 11, БП 3.0, ERP), то в ней, скорее всего, подключена БСП. В этом случае нам не обязательно писать свою серверную функцию для получения одного значения. Можно воспользоваться универсальным методом общего модуля ОбщегоНазначения.

Посмотрим на пример кода:


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

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

Способ 3. Оптимизация через «Путь к данным» (Без вызова сервера)

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

Выполним следующие шаги:

  1. Откройте редактор формы документа.
  2. Перейдите на закладку «Реквизиты».
  3. Найдите ваш Объект, раскройте его, найдите РеквизитДок1.
  4. Раскройте сам справочник (нажмите на «+» рядом с типом) и найдите там РеквизитСпр1.
  5. Перетащите этот «вложенный» реквизит на дерево элементов формы (но не вставляйте в визуальные группы, если не хотите его показывать пользователю).

Теперь платформа знает, что этот реквизит нужен форме. Проанализируем, как изменится код:


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

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

Способ 4. Работа с массивами (Групповая проверка)

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

Проанализируем правильную реализацию:


&НаСервереБезКонтекста
Функция ПолучитьСоответствиеТиповКонтрагентов(МассивСсылок)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Контрагенты.Ссылка КАК Ссылка,
        |   Контрагенты.ЮрФизЛицо КАК ЮрФизЛицо
        |ИЗ
        |   Справочник.Контрагенты КАК Контрагенты
        |ГДЕ
        |   Контрагенты.Ссылка В(&МассивСсылок)";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    
    // Возвращаем результат в виде Соответствия (Ключ = Ссылка, Значение = Тип)
    Возврат Запрос.Выполнить().Выгрузить().СкопироватьКолонку("Ссылка").НайтиСтроки(); // Упрощенно
    // В реальности лучше выгрузить в соответствие для быстрого поиска на клиенте
КонецФункции

Использование Запроса на сервере — это самый быстрый способ получения данных, особенно когда нужно проверить свойства сразу множества объектов.

Резюме и рекомендации

Выясним причину, почему в 1С нельзя просто написать условие на клиенте. Это сделано для экономии трафика: зачем передавать все данные объекта, если нам нужна только ссылка? Поэтому:

Применяя эти подходы, вы напишете не только работающий, но и производительный код, который будет соответствовать стандартам разработки 1С.

← На главную