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