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

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

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

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

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

Проанализируем типовую ситуацию. Предположим, в форме выполняется следующий код при изменении количества:


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

При выполнении этой процедуры платформа генерирует исключение. Выделим основные причины, почему данный код не работает:

  1. Обращение к элементам формы вместо данных: Конструкция вида Элементы.СтоимостьМатериалов возвращает объект формы (элемент управления), а не то значение, которое в нем заполнено. Для работы с конкретной строкой таблицы нужно обращаться к данным строки через ТекущиеДанные.
  2. Несоответствие типов данных: Если реквизит СтоимостьМатериалов (или Материал) имеет тип СправочникСсылка.Номенклатура, то в нем хранится ссылка на элемент справочника, а не числовое значение. Выполнение математической операции умножения числа на ссылку недопустимо в платформе 1С.
  3. Некорректное использование функции Число(): Попытка обернуть ссылку в явное приведение типов (например, Число(СтрокаТабличнойЧасти.СтоимостьМатериалов)) также приведет к ошибке. Функция Число() может принимать только числовые значения, строки с числовыми символами или значения типа Булево. Передача ссылок, а также значений Неопределено или Null вызывает фатальное исключение.

Шаг 1. Обращение к данным строки табличной части

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

Рассмотрим, как правильно получить текущую строку на клиенте:


СтрокаТабличнойЧасти = Элементы.МатериалыСписок.ТекущиеДанные;
Если СтрокаТабличнойЧасти <> Неопределено Тогда
    // Работаем с реквизитами строки:
    // СтрокаТабличнойЧасти.КоличествоМатериалов
    // СтрокаТабличнойЧасти.СуммаМатериалов
КонецЕсли;

Шаг 2. Получение цены из реквизита справочника на сервере

В тонком клиенте (в управляемых формах) разменование ссылок «через точку» (например, СтрокаТабличнойЧасти.Материал.Цена) либо ограничено, либо приводит к неявному серверному вызову, что негативно сказывается на производительности. Для считывания реквизитов объекта по его ссылке следует использовать серверную функцию.

Создадим внеконтекстную серверную функцию &НаСервереБезКонтекста, которая принимает ссылку на номенклатуру или материал и возвращает числовое значение стоимости:


&НаСервереБезКонтекста
Функция ПолучитьСтоимостьМатериала(Знач МатериалСсылка)
    Если Не ЗначениеЗаполнено(МатериалСсылка) Тогда
        Возврат 0;
    КонецЕсли;
    
    Возврат МатериалСсылка.Стоимость;
КонецФункции

Шаг 3. Итоговый пересчет строки на клиенте

Теперь объединим получение цены с сервера и расчет суммы в процедуре пересчета строки на клиенте. Посмотрим на итоговый рабочий пример:


&НаКлиенте
Процедура ПросчётСтроки()
    СтрокаТабличнойЧасти = Элементы.МатериалыСписок.ТекущиеДанные;
    
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем числовую стоимость с сервера
    Стоимость = ПолучитьСтоимостьМатериала(СтрокаТабличнойЧасти.Материал);
    
    // Выполняем математический расчет
    СтрокаТабличнойЧасти.СуммаМатериалов = СтрокаТабличнойЧасти.КоличествоМатериалов * Стоимость;
КонецПроцедуры

&НаКлиенте
Процедура КоличествоМатериаловПриИзменении(Элемент)
    ПросчётСтроки();
КонецПроцедуры

Архитектурные рекомендации по хранению цен и сумм

Разберем важные нюансы проектирования структуры данных, которые помогут избежать подобных ошибок в будущем:

  1. Создавайте отдельные числовые реквизиты в табличной части: В табличной части документа или справочника реквизиты Количество, Цена и Сумма должны иметь тип Число с нужной точностью (например, длина 15, точность 2). В реквизите Материал или Номенклатура хранится только ссылка.
  2. Фиксируйте цену в документе: Не рассчитывайте сумму напрямую из реквизита справочника при формировании печатных форм или отчетов. Со временем цена в справочнике может измениться, поэтому при выборе номенклатуры заполняйте числовой реквизит Цена в табличной части документа, а расчет суммы выполняйте по формуле Сумма = Количество * Цена.
  3. Используйте регистры сведений для цен: В профессиональных конфигурациях цены хранятся не в реквизитах справочника «Номенклатура», а в периодическом регистре сведений «Цены номенклатуры». Это позволяет вести историю изменения цен и получать актуальную стоимость на нужную дату методом СрезПоследних.
← На главную