Как заполнить поле ввода на управляемой форме из регистра сведений по выбранной строке?

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

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

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

Почему старый код не работает на управляемых формах?

Для начала выясним причину возникновения ошибки. В обычных формах элементы управления (например, поля ввода) напрямую хранили отображаемые значения, и к ним можно было обращаться через конструкцию Элемент.Значение. В управляемых формах архитектура была полностью пересмотрена в соответствии с паттерном MVC (Model-View-Controller). Теперь данные отделены от их визуального представления:

  1. Разделение данных и интерфейса: Элементы формы (объекты типа ПолеФормы) больше не хранят данные. Они лишь отображают их. Все данные хранятся исключительно в реквизитах формы (или реквизитах объекта, например, Объект.ТорговыеТочкиПредприятия). Свойство Значение у элементов управляемой формы отсутствует, что и вызывает ошибку.
  2. Контекстные ограничения (Клиент-Сервер): Менеджеры объектов, такие как РегистрыСведений, и метод СоздатьМенеджерЗаписи() доступны только на стороне сервера. Попытка вызвать их в клиентской процедуре под директивой &НаКлиенте приведет к ошибке компиляции.
  3. Особенности работы с Ключом записи: При выборе строки из стандартной формы списка регистра сведений платформа возвращает объект типа РегистрСведенийКлючЗаписи. На клиенте у этого объекта доступны только ключевые поля (измерения). Получить «через точку» другие ресурсы или реквизиты (например, нужный нам UUID) невозможно — для этого требуется обращение к серверной базе данных.

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


Способ №1: Классический клиент-серверный вызов (Рекомендуемый)

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

Разберем по шагам реализацию этого механизма в модуле управляемой формы.

Шаг 1. Инициируем выбор в обработчике события «НачалоВыбора»

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


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

Шаг 2. Обрабатываем выбор в событии «ОбработкаВыбора»

Когда пользователь выбирает строку, срабатывает обработчик выбора. Полученный ключ записи мы передаем в серверную функцию, а результат её работы записываем непосредственно в реквизит формы:


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

Шаг 3. Получаем данные на сервере

Для максимального быстродействия используем директиву &НаСервереБезКонтекста. Прочитать данные по ключу записи можно двумя путями. Рассмотрим оба варианта.

Вариант А (Через Менеджер записи): Этот вариант наиболее близок к логике обычного приложения, но требует полной вычитки всей записи.


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

Вариант Б (Через Запрос — более производительный): Позволяет получить строго необходимое поле из базы данных без избыточного чтения всей строки регистра.


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

Способ №2: Оповещение о выборе из кастомной формы регистра

Если у вас есть возможность вносить изменения в форму выбора регистра сведений КлассификаторВЕТИС, то можно переопределить возвращаемое значение непосредственно в ней. Это позволит полностью избавиться от необходимости писать серверный код в вызывающей форме.

Посмотрим, как это реализовать:

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

Проанализируем пример кода для формы выбора регистра:


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

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


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

Резюме

При разработке под управляемый интерфейс 1С важно помнить ключевое правило: мы всегда работаем с данными (реквизитами), а не с элементами формы. Избегайте использования устаревших свойств вроде Значение у элементов и не применяйте обходные пути вроде визуальной подмены через ВыделенныйТекст. Использование клиент-серверного разделения или механизма прямого оповещения о выборе гарантирует стабильную работу вашей конфигурации и сохранность данных пользователей.

← На главную