При разработке или доработке документов в системе 1С:Предприятие 8 программисты часто сталкиваются с ошибкой: «Преобразование значения к типу Число не может быть выполнено». Чаще всего это происходит в строке кода, где вычисляется сумма: СтрокаТабличнойЧасти.Сумма = СтрокаТабличнойЧасти.Количество * СтрокаТабличнойЧасти.Цена;. Давайте подробно разберем, почему возникает эта ситуация, как ее диагностировать и какие существуют способы решения — от простых до профессиональных.
Прежде всего, проанализируем саму формулировку ошибки. Если система сообщает о невозможности преобразования к числу, это означает, что объект СтрокаТабличнойЧасти успешно обратился к свойствам Количество (или Колличество) и Цена, но содержимое этих полей оказалось нечисловым. Если бы поля с таким именем вовсе не существовало (например, из-за опечатки), 1С выдала бы другую ошибку: «Поле объекта не обнаружено».
Рассмотрим основные сценарии, почему в числовых, на первый взгляд, полях оказываются другие данные:
Строка, то пустая ячейка будет содержать "". Математические операции со строками в 1С запрещены.Самый простой и быстрый способ — принудительно преобразовать значения в числовой формат перед умножением. Рассмотрим код:
СтрокаТабличнойЧасти.Сумма = Число(СтрокаТабличнойЧасти.Количество) * Число(СтрокаТабличнойЧасти.Цена);
Разберем, как это работает. Функция Число() пытается превратить переданный ей аргумент в число. Однако у этого метода есть существенный недостаток: если в строке окажется текст, который нельзя интерпретировать как число (например, "10 шт."), система снова выдаст ошибку и прервет работу пользователя. Этот метод хорош только тогда, когда вы уверены, что данные «почти всегда» числовые.
Более профессиональный и безопасный подход заключается в использовании объекта ОписаниеТипов. В отличие от функции Число(), метод ПривестиЗначение() не вызывает критическую ошибку, а возвращает значение по умолчанию (для чисел это 0), если преобразование невозможно. Посмотрим на пример:
ТипЧисло = Новый ОписаниеТипов("Число");
КоличествоЧислом = ТипЧисло.ПривестиЗначение(СтрокаТабличнойЧасти.Количество);
ЦенаЧислом = ТипЧисло.ПривестиЗначение(СтрокаТабличнойЧасти.Цена);
СтрокаТабличнойЧасти.Сумма = КоличествоЧислом * ЦенаЧислом;
Проанализируем ситуацию: если в поле Цена попадет NULL или пустая строка, переменная ЦенаЧислом станет равна 0. Программа продолжит работу без сбоев, а сумма просто обнулится, что гораздо лучше для пользователя, чем «вылет» системы.
Часто проблема кроется в «грязных» данных. Стандартная функция СокрЛП() удаляет только обычные пробелы по краям. Неразрывный пробел (символ с кодом 160) часто встречается в числах, скопированных из Excel (например, "1 500"). Давайте разберем, как его удалить:
ЧистоеКоличество = СтрЗаменить(СтрокаТабличнойЧасти.Количество, Символы.НПП, "");
СтрокаТабличнойЧасти.Сумма = Число(ЧистоеКоличество) * Число(СтрокаТабличнойЧасти.Цена);
Здесь Символы.НПП — это системная константа неразрывного пробела. Удалив его, мы превращаем строку "1 500" в "1500", которую функция Число() обработает корректно.
Если ваша табличная часть заполняется программно на основе данных из базы, важно предусмотреть наличие пустых значений (NULL) еще на этапе выполнения запроса. Выясним, как это сделать правильно:
// В тексте запроса всегда используйте ЕСТЬNULL
ТекстЗапроса = "
|ВЫБРАТЬ
| ЕСТЬNULL(Номенклатура.Цена, 0) КАК Цена,
| ЕСТЬNULL(Остатки.Количество, 0) КАК Количество
|ИЗ ...";
Использование функции ЕСТЬNULL(Поле, 0) гарантирует, что в результат запроса попадет число 0, а не пустое значение, которое позже приведет к ошибке трансформации типа.
Чтобы окончательно разобраться в проблеме, рекомендуем использовать отладчик. Выполните следующие шаги:
СтрокаТабличнойЧасти.Количество.Строка, Неопределено или NULL, значит, вам нужно либо исправлять метаданные (менять тип реквизита на Число), либо применять функции приведения, описанные выше.Помните, что правильная настройка типов в конфигураторе — это залог отсутствия подобных ошибок. Всегда проверяйте, чтобы для числовых полей в свойствах реквизита был установлен тип Число с нужной точностью и длиной, а не Строка или ЛюбаяСсылка.