Почему возникает ошибка при обращении к реквизитам через точку на тонком клиенте в 1С и как её исправить?

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

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

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

Причина возникновения ошибки

Проанализируем контекст выполнения кода в клиент-серверной архитектуре и на управляемых формах 1С.

На тонком клиенте объект формы Объект и его непосредственные реквизиты доступны. Если реквизит формы является ссылкой (например, СправочникСсылка.ФизическиеЛица), то на клиенте хранится только сам ссылочный тип — уникальный идентификатор (GUID) и стандартное представление объекта. Все внутренние реквизиты элемента справочника (такие как Наименование, Код, ИНН и другие) на клиенте отсутствуют.

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

Способ 1. Использование функции Строка() на клиенте

Если цель разработчика — получить текстовое представление объекта (например, ФИО водителя или наименование контрагента) для отображения в интерфейсе или вывода в сообщение, обращаться к реквизиту Наименование не обязательно. Достаточно применить функцию Строка() непосредственно на клиенте.

Разберем пример кода на клиенте:


&НаКлиенте
Процедура ОбработатьВыбор()
    // Получаем строковое представление ссылки без обращения к серверу
    ИмяВодителя = Строка(Объект.Водитель);
    Сообщить("Выбран водитель: " + ИмяВодителя);
КонецПроцедуры

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

Способ 2. Вызов внеконтекстной серверной функции

Если на клиенте требуется получить конкретное значение реквизита, которое не совпадает с представлениями ссылки, необходимо выполнить обращение к серверу. Для минимизации объема передаваемых данных рекомендуется использовать директиву &НаСервереБезКонтекста.

Рассмотрим пример реализации:


&НаКлиенте
Процедура ЗаполнитьДанные()
    НаименованиеВодителя = ПолучитьНаименованиеВодителя(Объект.Водитель);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьНаименованиеВодителя(СсылкаВодитель)
    Если Не ЗначениеЗаполнено(СсылкаВодитель) Тогда
        Возврат "";
    КонецЕсли;
    
    Возврат СсылкаВодитель.Наименование;
КонецФункции

Способ 3. Использование функций Библиотеки Стандартных Подсистем (БСП)

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

Пример получения реквизита через БСП:


&НаКлиенте
Процедура ПолучитьДанныеЧерезБСП()
    // Получение значения реквизита с помощью функции БСП
    НаименованиеВодителя = ОбщегоНазначенияВызовСервера.ЗначениеРеквизитаОбъекта(Объект.Водитель, "Наименование");
КонецПроцедуры

Способ 4. Выборка данных с помощью запроса на сервере

При необходимости получить сразу несколько реквизитов объекта или при написании высокопроизводительного кода рекомендуется использовать язык запросов на сервере. Прямое обращение через точку к реквизитам ссылки на сервере (например, Ссылка.Наименование) считывает из базы данных объект целиком. Запрос же выбирает только необходимые поля.

Разберем пример серверной функции с запросом:


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

Способ 5. Протаскивание реквизита в реквизиты формы

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

Резюме

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

← На главную