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