Почему возникает ошибка «Значение не является значением объектного типа (Сумма)» и как ее исправить?

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

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

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

Анализ механизма возникновения ошибки

Рассмотрим типовой листинг клиентского общего модуля, в котором реализуется расчет суммы:


Процедура РасчетСуммы(СтрокаТЧ) Экспорт
    СтрокаТЧ.Сумма = СтрокаТЧ.Цена * СтрокаТЧ.Количество;
КонецПроцедуры

Данная процедура вызывается из обработчиков событий элементов формы, например, при изменении количества или цены:


&НаКлиенте
Процедура ПереченьНоменклатурыКоличествоПриИзменении(Элемент)
    СтрокаТЧ = Элементы.ПереченьНоменклатуры.ТекущиеДанные;
    РаботаСДокументами.РасчетСуммы(СтрокаТЧ);
КонецПроцедуры

Текст ошибки указывает на то, что обращение через точку к свойству Сумма происходит не у объекта или структуры, а у значения примитивного типа, не имеющего свойств. В подавляющем большинстве случаев переменная СтрокаТЧ принимает значение Неопределено.

Проанализируем ситуацию: свойство таблицы формы Элементы.ИмяТаблицы.ТекущиеДанные возвращает объект типа ДанныеФормыЭлементКоллекции, представляющий активную строку. Однако это свойство возвращает Неопределено в следующих случаях:

  1. Табличная часть документа не содержит строк (пустая таблица).
  2. Фокус ввода в пользовательском интерфейсе еще не спозиционирован на конкретной строке таблицы.
  3. Процедура расчета ошибочно привязана к событиям самой таблицы формы (например, ПередНачаломДобавления или ПриАктивизацииСтроки), когда строка еще не создана в памяти формы.
  4. Выполняется добавление новой строки, и в момент инициализации платформа выполняет обработчики до момента фиксации строки в качестве текущей.

Способ 1. Проверка правильности привязки событий на форме

Разберем распространенную ошибку начинающих разработчиков — ошибочное назначение обработчиков через палитру свойств. Часто процедура пересчета или процедура КоличествоПриИзменении случайно привязывается к событиям самой таблицы, а не к событиям конкретного поля ввода (колонки).

Выполним проверку привязки событий по шагам:

  1. Откроем форму документа в конфигураторе.
  2. Выделим элемент формы, представляющий саму таблицу (например, ПереченьНоменклатуры).
  3. Откроем палитру свойств (нажатием клавиши F4) и перейдем в раздел События (значок с лупой).
  4. Убедимся, что на событиях таблицы (таких как ПередНачаломДобавления, ПриНачалеРедактирования, ПриАктивизацииСтроки) не назначены процедуры пересчета сумм. Если они там назначены — очистим эти привязки.
  5. Раскроем дерево элементов таблицы формы и перейдем к элементам колонок: ПереченьНоменклатурыКоличество и ПереченьНоменклатурыЦена.
  6. Проверим, чтобы событие ПриИзменении было назначено строго на соответствующее поле ввода колонки.

Способ 2. Защитное программирование (проверка на Неопределено)

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

Посмотрим на пример правильной организации кода в модуле формы:


&НаКлиенте
Процедура ПереченьНоменклатурыКоличествоПриИзменении(Элемент)
    СтрокаТЧ = Элементы.ПереченьНоменклатуры.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        РаботаСДокументами.РасчетСуммы(СтрокаТЧ);
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПереченьНоменклатурыЦенаПриИзменении(Элемент)
    СтрокаТЧ = Элементы.ПереченьНоменклатуры.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        РаботаСДокументами.РасчетСуммы(СтрокаТЧ);
    КонецЕсли;
КонецПроцедуры

Также мы можем внедрить проверку непосредственно внутрь процедуры общего модуля, чтобы обезопасить алгоритм от любых некорректных вызовов из других мест конфигурации:


Процедура РасчетСуммы(СтрокаТЧ) Экспорт
    Если СтрокаТЧ = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    СтрокаТЧ.Сумма = СтрокаТЧ.Цена * СтрокаТЧ.Количество;
КонецПроцедуры

Способ 3. Получение строки через идентификатор

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

Разберем пример реализации:


&НаКлиенте
Процедура ПереченьНоменклатурыКоличествоПриИзменении(Элемент)
    ИдентификаторСтроки = Элементы.ПереченьНоменклатуры.ТекущаяСтрока;
    Если ИдентификаторСтроки <> Неопределено Тогда
        СтрокаТЧ = Объект.ПереченьНоменклатуры.НайтиПоИдентификатору(ИдентификаторСтроки);
        Если СтрокаТЧ <> Неопределено Тогда
            РаботаСДокументами.РасчетСуммы(СтрокаТЧ);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Такой подход гарантирует, что мы обращаемся к строке коллекции прикладного объекта формы даже в том случае, если интерфейсный фокус ТекущиеДанные временно сброшен или переключен на другой управляющий элемент.

Особенности работы с общими модулями на клиенте

Обратим внимание на настройки общего модуля, в котором расположена процедура РасчетСуммы. Так как параметр СтрокаТЧ имеет тип ДанныеФормыЭлементКоллекции, данный объект существует исключительно в контексте клиентского приложения.

Для корректного исполнения кода общий модуль РаботаСДокументами должен иметь следующие параметры в палитре свойств:

  1. Установлен флаг Клиент (управляемое приложение).
  2. Снят флаг Вызов сервера, если внутри модуля нет серверных функций.

Если попытаться передать объект ДанныеФормыЭлементКоллекции в процедуру общего модуля, выполняемую на стороне сервера, платформа выдаст ошибку передачи мутабельного значения между контекстами клиента и сервера. Для серверных расчетов следует передавать не саму строку формы, а примитивные типы (числовые значения цены и количества), возвращая результат вычисления обратно на клиент.

← На главную