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