Как в 1С 8.3 настроить автоматическое заполнение одного реквизита при изменении другого в управляемой форме?

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

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

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

Разбор основной проблемы: ошибка «Переменная не определена»

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

Проанализируем контекст выполнения кода. В управляемом приложении код формы чаще всего выполняется на Тонком клиенте (директива &НаКлиенте). На стороне клиента действуют строгие ограничения:

  1. Отсутствие прямого доступа к метаданным: Глобальный контекст Перечисления доступен только на сервере. Клиент «не знает» о существовании всей структуры перечислений в базе данных.
  2. Изоляция данных формы: На клиенте вы работаете не с объектом базы данных напрямую, а с его «проекцией» — реквизитом формы, который по умолчанию называется Объект.

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

Решение 1: Использование функции ПредопределенноеЗначение на клиенте

Для того чтобы получить ссылку на значение перечисления, не обращаясь к серверу, в 1С существует специальная функция ПредопределенноеЗначение(). Она принимает на вход строковое имя объекта метаданных и возвращает ссылку на него. Это позволяет нам оставить логику на клиенте, что обеспечит максимальную скорость работы интерфейса.

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

  1. Откроем форму элемента справочника в Конфигураторе.
  2. Выберем на форме элемент Пол и в панели свойств создадим событие ПриИзменении.
  3. В модуле формы пропишем логику, обращаясь к данным через точку от слова Объект.

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


&НаКлиенте
Процедура ПолПриИзменении(Элемент)
    
    // Проверяем выбранное значение в реквизите Объект.Пол
    Если Объект.Пол = ПредопределенноеЗначение("Перечисление.Пол.Мужской") Тогда
        
        // Устанавливаем зависимое значение
        Объект.ЛичныеКачества = ПредопределенноеЗначение("Перечисление.ЛичныеКачества.Мужчина");
        
    ИначеЕсли Объект.Пол = ПредопределенноеЗначение("Перечисление.Пол.Женский") Тогда
        
        Объект.ЛичныеКачества = ПредопределенноеЗначение("Перечисление.ЛичныеКачества.Женщина");
        
    КонецЕсли;
    
КонецПроцедуры

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

Решение 2: Вынос логики на сервер (директива &НаСервере)

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

Рассмотрим вариант реализации с вызовом серверной процедуры:


&НаКлиенте
Процедура ПолПриИзменении(Элемент)
    УстановитьЛичныеКачестваНаСервере();
КонецПроцедуры

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

Важный момент: Использование директивы &НаСервере заставляет систему передавать все данные формы (весь контекст) на сервер и обратно. Если форма «тяжелая», это может вызвать задержки в работе интерфейса.

Оптимизация кода: обработка пустых значений

Проанализируем ситуацию: что произойдет, если пользователь случайно выбрал пол, а затем очистил поле? В приведенных выше примерах старое значение в поле «Личные качества» сохранится, что может привести к логическим ошибкам в базе данных.

Хорошим тоном в программировании 1С считается добавление блока очистки. Рассмотрим, как это выглядит:


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

Масштабируемость: использование структур и соответствий

Представим, что в вашем перечислении не 2, а 10 или 20 значений. Нагромождение конструкций Если...ИначеЕсли...КонецЕсли делает программный код трудночитаемым и сложным в поддержке. Профессиональные разработчики используют для таких целей коллекции Соответствие или Структура.

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

Пример реализации через серверную функцию:


&НаСервереБезКонтекста
Функция ПолучитьЗависимоеКачество(ЗначениеПола)
    
    КартаСоответствий = Новый Соответствие;
    КартаСоответствий.Вставить(Перечисления.Пол.Мужской, Перечисления.ЛичныеКачества.Мужчина);
    КартаСоответствий.Вставить(Перечисления.Пол.Женский, Перечисления.ЛичныеКачества.Женщина);
    
    Возврат КартаСоответствий.Получить(ЗначениеПола);
    
КонецФункции

&НаКлиенте
Процедура ПолПриИзменении(Элемент)
    Объект.ЛичныеКачества = ПолучитьЗависимоеКачество(Объект.Пол);
КонецПроцедуры

Использование директивы &НаСервереБезКонтекста является наиболее производительным вариантом, так как на сервер передается только одно значение (выбранный пол), а не вся форма целиком.

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

Для корректной работы сопоставления реквизитов в управляемых формах 1С 8.3 необходимо помнить три ключевых правила:

  1. Всегда обращайтесь к реквизитам через префикс Объект. (например, Объект.Пол).
  2. Для доступа к перечислениям на клиенте используйте ПредопределенноеЗначение().
  3. Не забывайте обрабатывать очистку полей и пустые ссылки, чтобы поддерживать актуальность данных в системе.

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

← На главную