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