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

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

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

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

Выясним причину ошибки

Проанализируем устройство управляемого интерфейса в платформе 1С:Предприятие 8. В управляемых формах существует четкое разделение между данными и элементами интерфейса:

  1. Данные формы (реквизиты) — это переменные, содержащие реальные значения (числа, строки, ссылки на справочники). Данные реквизита формы хранятся в объектах типа ДанныеФормыСтруктура, ДанныеФормыКоллекция или напрямую в реквизите Объект.
  2. Элементы формы (элементы интерфейса) — это визуальные элементы управления, находящиеся в коллекции Элементы (объекты типа ПолеФормы, ГруппаФормы, ТаблицаФормы). Они служат исключительно для отображения данных пользователю и считывают их по свойству ПутьКДанным.

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

Разберем ошибочный пример кода

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


Процедура РасчитатьВесПартии()
    Стр = Элементы.Таблица.ТекущиеДанные;
    Шапка = Элементы; // Здесь сохраняется ссылка на коллекцию элементов формы!
    
    Стр.ОбщийВес = Стр.Количество * Стр.ВесЕдиницы;
    
    // ОШИБКА! Попытка деления на элемент формы (ПолеФормы)
    Стр.УдельныйВесПартии = (Стр.ОбщийВес / Шапка.ОбщийВесГруза) * 100;
КонецПроцедуры

В данном фрагменте обращения к Шапка.ОбщийВесГруза адресованы к элементу пользовательского интерфейса, а не к числу.

Исправляем проблему: как правильно обращаться к данным

Чтобы арифметическая операция выполнилась корректно, необходимо делить число на число. Для этого обращаемся к реквизиту формы напрямую или через реквизит Объект.

Рассмотрим варианты в зависимости от того, где объявлен реквизит:

  1. Реквизит входит в состав объекта (например, документа): Обращение происходит через реквизит Объект: Значение = Объект.ОбщийВесГруза;
  2. Реквизит является самостоятельным реквизитом формы: Обращение выполняется напрямую по его имени: Значение = ОбщийВесГруза;

Посмотрим на исправленный вариант процедуры расчетов:


&НаКлиенте
Процедура РасчитатьВесПартии()
    Стр = Элементы.Таблица.ТекущиеДанные;
    Если Стр = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Стр.ОбщийВес = Стр.Количество * Стр.ВесЕдиницы;
    
    // Обращаемся к реквизиту шапки документа "Объект.ОбщийВесГруза"
    Если ЗначениеЗаполнено(Объект.ОбщийВесГруза) И Объект.ОбщийВесГруза <> 0 Тогда
        Стр.УдельныйВесПартии = (Стр.ОбщийВес / Объект.ОбщийВесГруза) * 100;
    Иначе
        Стр.УдельныйВесПартии = 0;
    КонецЕсли;
КонецПроцедуры

Защита от потенциальных ошибок при расчетах

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

  1. Проверка на наличие выделенной строки: Если таблица пуста или строка не выбрана, свойство Элементы.Таблица.ТекущиеДанные возвращает значение Неопределено. Попытка обращения к его полям через точку вызовет критическую ошибку «Поле объекта не обнаружено». Всегда проверяйте переменную на Неопределено перед расчетами.
  2. Обработка деления на ноль: Если делитель равен нулю или не заполнен, оператор деления вызовет исключение. Выполняйте проверку с помощью функции ЗначениеЗаполнено() и явного сравнения с нулем.
  3. Учет контекста выполнения (Клиент/Сервер): Свойство ТекущиеДанные элемента таблицы доступно только на клиенте в процедурах с директивой &НаКлиенте. На сервере у элементов таблицы нет свойства ТекущиеДанные — там следует обращаться напрямую к реквизиту объекта Объект.Таблица.
← На главную