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