Переход с обычных форм 1С на управляемые часто вызывает трудности у разработчиков, привыкших к прямой работе с элементами интерфейса. Типичный сценарий — интерактивный выбор строки из регистра сведений с последующим заполнением поля ввода значением одного из ресурсов или реквизитов выбранной записи. При попытке перенести старый код «как есть» разработчики неизбежно сталкиваются с ошибкой «Поле объекта не обнаружено (Значение)».
В этой статье мы подробно разберем причины возникновения этой ошибки, проанализируем архитектурные ограничения управляемых форм и рассмотрим несколько надежных, проверенных способов решения этой задачи.
Для начала выясним причину возникновения ошибки. В обычных формах элементы управления (например, поля ввода) напрямую хранили отображаемые значения, и к ним можно было обращаться через конструкцию Элемент.Значение. В управляемых формах архитектура была полностью пересмотрена в соответствии с паттерном MVC (Model-View-Controller). Теперь данные отделены от их визуального представления:
ПолеФормы) больше не хранят данные. Они лишь отображают их. Все данные хранятся исключительно в реквизитах формы (или реквизитах объекта, например, Объект.ТорговыеТочкиПредприятия). Свойство Значение у элементов управляемой формы отсутствует, что и вызывает ошибку.РегистрыСведений, и метод СоздатьМенеджерЗаписи() доступны только на стороне сервера. Попытка вызвать их в клиентской процедуре под директивой &НаКлиенте приведет к ошибке компиляции.РегистрСведенийКлючЗаписи. На клиенте у этого объекта доступны только ключевые поля (измерения). Получить «через точку» другие ресурсы или реквизиты (например, нужный нам UUID) невозможно — для этого требуется обращение к серверной базе данных.Важное примечание: Использование свойства Элемент.ВыделенныйТекст, к которому иногда прибегают разработчики в качестве быстрого «обхода» проблемы, является грубой ошибкой. Данное свойство лишь визуально подменяет текст в поле ввода на клиенте. При записи документа, обновлении формы или потере фокуса это значение будет безвозвратно утеряно, так как реальный реквизит формы останется пустым.
Рассмотрим наиболее правильный и производительный способ решения задачи. Нам необходимо разделить логику на клиентскую (интерактивный выбор и присвоение значения реквизиту) и серверную (чтение данных из регистра сведений по полученному ключу записи).
Разберем по шагам реализацию этого механизма в модуле управляемой формы.
Шаг 1. Инициируем выбор в обработчике события «НачалоВыбора»
В этой процедуре мы отключаем стандартную обработку и программно открываем форму выбора нашего регистра сведений:
&НаКлиенте
Процедура ТорговыеТочкиПредприятияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ПараметрыВыбора = Новый Структура;
ПараметрыВыбора.Вставить("РежимВыбора", Истина);
// Открываем форму выбора регистра, передавая элемент-владелец для возврата значения
ОткрытьФорму("РегистрСведений.КлассификаторВЕТИС.Форма.ФормаВыбора", ПараметрыВыбора, Элемент);
КонецПроцедуры
Шаг 2. Обрабатываем выбор в событии «ОбработкаВыбора»
Когда пользователь выбирает строку, срабатывает обработчик выбора. Полученный ключ записи мы передаем в серверную функцию, а результат её работы записываем непосредственно в реквизит формы:
&НаКлиенте
Процедура ТорговыеТочкиПредприятияОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Проверяем, что пользователь действительно выбрал строку регистра
Если ВыбранноеЗначение <> Неопределено И ТипЗнч(ВыбранноеЗначение) = Тип("РегистрСведенийКлючЗаписи.КлассификаторВЕТИС") Тогда
// Вызываем серверный контекст для получения UUID по ключу записи
ЗначениеUUID = ПолучитьUUIDИзРегистраНаСервере(ВыбранноеЗначение);
// Присваиваем полученное значение реквизиту формы (или реквизиту объекта)
Объект.ТорговыеТочкиПредприятия = ЗначениеUUID;
КонецЕсли;
КонецПроцедуры
Шаг 3. Получаем данные на сервере
Для максимального быстродействия используем директиву &НаСервереБезКонтекста. Прочитать данные по ключу записи можно двумя путями. Рассмотрим оба варианта.
Вариант А (Через Менеджер записи): Этот вариант наиболее близок к логике обычного приложения, но требует полной вычитки всей записи.
&НаСервереБезКонтекста
Функция ПолучитьUUIDИзРегистраНаСервере(КлючЗаписи)
МенеджерЗаписи = РегистрыСведений.КлассификаторВЕТИС.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, КлючЗаписи);
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
Возврат МенеджерЗаписи.UUID;
КонецЕсли;
Возврат "";
КонецФункции
Вариант Б (Через Запрос — более производительный): Позволяет получить строго необходимое поле из базы данных без избыточного чтения всей строки регистра.
&НаСервереБезКонтекста
Функция ПолучитьUUIDИзРегистраНаСервере(КлючЗаписи)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КлассификаторВЕТИС.UUID КАК UUID
|ИЗ
| РегистрСведений.КлассификаторВЕТИС КАК КлассификаторВЕТИС
|ГДЕ
| КлассификаторВЕТИС.ИзмерениеАдрес = &ИзмерениеАдрес"; // Укажите ваши реальные измерения
// Заполняем параметры запроса из структуры ключа записи
Для Каждого КлючИЗначение Из КлючЗаписи Цикл
Запрос.УстановитьПараметр(КлючИЗначение.Ключ, КлючИЗначение.Значение);
КонецЦикла;
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.UUID;
КонецЕсли;
Возврат "";
КонецФункции
Если у вас есть возможность вносить изменения в форму выбора регистра сведений КлассификаторВЕТИС, то можно переопределить возвращаемое значение непосредственно в ней. Это позволит полностью избавиться от необходимости писать серверный код в вызывающей форме.
Посмотрим, как это реализовать:
Список) создадим обработчик события Выбор.ОповеститьОВыборе().Проанализируем пример кода для формы выбора регистра:
&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Оповещаем форму-владельца и передаем напрямую значение UUID вместо КлючаЗаписи
ОповеститьОВыборе(ТекущиеДанные.UUID);
КонецЕсли;
КонецПроцедуры
При таком подходе в вызывающей форме обработчик ОбработкаВыбора существенно упрощается. Параметр ВыбранноеЗначение сразу будет содержать готовый UUID, и нам останется лишь присвоить его реквизиту:
&НаКлиенте
Процедура ТорговыеТочкиПредприятияОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
Объект.ТорговыеТочкиПредприятия = ВыбранноеЗначение;
КонецЕсли;
КонецПроцедуры
При разработке под управляемый интерфейс 1С важно помнить ключевое правило: мы всегда работаем с данными (реквизитами), а не с элементами формы. Избегайте использования устаревших свойств вроде Значение у элементов и не применяйте обходные пути вроде визуальной подмены через ВыделенныйТекст. Использование клиент-серверного разделения или механизма прямого оповещения о выборе гарантирует стабильную работу вашей конфигурации и сохранность данных пользователей.