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