Преобразование значения к типу Число не может быть выполнено: что делать

· 10 мин

Содержание

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

Распространённое заблуждение: «ошибка в базе, надо переустанавливать платформу». Нет. Платформа здесь работает правильно, она отказывается угадывать, что вы имели в виду под значением "12 о" или Неопределено. Проблема всегда в данных или в коде, который их обрабатывает.

Статья про разработку и доработку: обработки, отчёты, обмены, загрузки из файлов. Если ошибка вылетает у пользователя в типовой конфигурации, начните с первого раздела и передайте текст ошибки разработчику.

Откуда берётся ошибка: пять типичных источников

Число не получается из значения, у которого нет числового представления. Вот что встречается на практике.

  • 🔤 Текст с посторонними символами. "1 250,50 руб.", "12,5%", "н/д", "-". Платформа умеет читать только саму цифровую запись.
  • 🕳️ Неопределено. Функция ничего не вернула, поле не заполнено, значение не прочитано из файла. Число(Неопределено) падает всегда.
  • 🔗 Ссылка или объект вместо числа. Например, в реквизит типа Число кладут Справочники.Номенклатура.ПустаяСсылка() или элемент справочника.
  • 📅 Дата и булево. Из даты число не получить, из Истина тоже. Это ловится в универсальных обработках, где тип колонки заранее неизвестен.
  • ⚙️ Разделители и невидимые символы. Внешне строка выглядит как число, а внутри неразрывный пробел (код 160), табуляция или перевод строки. Самый неприятный случай: глазами не отличить.

Пустая строка ошибкой не считается: Число("") вернёт 0. Поэтому пустые ячейки Excel часто проходят, а ломается только ячейка с пробелом или дефисом.

Как отличить свою ошибку от чужой

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

Диагностика: выберите симптом

Найти место ошибки с помощью отладчика

Текст ошибки обычно содержит стек вызовов: модуль и номер строки. Часто его хватает. Если нет, запускайте отладку.

Остановка по ошибке

Самый быстрый способ: в Конфигураторе включите остановку по ошибке и повторите действие.

  1. Откройте Конфигуратор и выберите пункт меню Отладка → Остановка по ошибке. Достаточно отметить остановку при необработанных исключениях.
  2. Запустите отладку клавишей F5 (запустится «1С:Предприятие» в режиме отладки).
  3. Повторите действие, которое вызывает ошибку.
  4. Платформа остановит выполнение на строке, где произошло исключение, и откроет модуль.

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

Что смотреть на остановке

Когда выполнение встало, посмотрите значения всех переменных в строке с Число(...).

  • Окно Локальные переменные показывает, что лежит в аргументе. Если вместо числа строка, посмотрите её целиком: нет ли в конце пробела, знака процента, слова.
  • Вычисление выражения (Shift+F9) позволяет проверить ТипЗнч(Значение) и СтрДлина(Значение). Если длина строки больше, чем видно глазом, внутри невидимый символ.
  • Для цикла по таблице поставьте условную точку останова на строку с преобразованием, чтобы не нажимать «Продолжить» тысячу раз. Условие, например, ТипЗнч(Значение) <> Тип("Число").

Нужную строку можно найти и без отладчика: временно оберните вызов в Попытка … Исключение и выведите значение и тип в сообщение. Но на сложных циклах отладчик быстрее.

Исправление в коде: как привести значение к числу

Единого рецепта нет, выбор зависит от того, откуда пришло значение и можно ли ему доверять. Три рабочих приёма, от самого мягкого.

ПриёмКогда подходитРиск
ОписаниеТипов("Число").ПривестиЗначение(Значение)Нужно число или 0, ошибка не должна прерывать работуМусорные данные тихо превращаются в ноль
Очистка строки + Число()Источник известен: Excel, текстовый файл, ввод пользователяНужно учесть все варианты символов
Попытка … ИсключениеНужно отличить «плохое значение» от нуля и сообщить пользователюЛишняя нагрузка в больших циклах

Тихое приведение

Метод ПривестиЗначение у описания типов возвращает число, а если значение не удалось привести, значение по умолчанию для типа, то есть 0. Исключения нет.

ОписаниеЧисла = Новый ОписаниеТипов("Число");
Результат = ОписаниеЧисла.ПривестиЗначение(ИсходноеЗначение);

Это удобно в отчётах и расчётах, где ноль вместо пропуска допустим. Для данных, где важна точность (суммы в документах, остатки), этот способ не подходит: ошибка просто спрячется, а сумма окажется неверной.

Очистка строки перед преобразованием

Если значение пришло из файла или от пользователя, сначала уберите всё лишнее.

Функция СтрокаВЧисло(Знач Значение)

	Если ТипЗнч(Значение) = Тип("Число") Тогда
		Возврат Значение;
	КонецЕсли;

	Если Значение = Неопределено Тогда
		Возврат 0;
	КонецЕсли;

	Текст = СокрЛП(Строка(Значение));
	Текст = СтрЗаменить(Текст, Символ(160), "");
	Текст = СтрЗаменить(Текст, " ", "");
	Текст = СтрЗаменить(Текст, ",", ".");

	Если Текст = "" Тогда
		Возврат 0;
	КонецЕсли;

	Попытка
		Возврат Число(Текст);
	Исключение
		Возврат Неопределено;
	КонецПопытки;

КонецФункции

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

Что делает каждая подстановка: Символ(160) убирает неразрывный пробел (его любят ставить Excel и веб-страницы как разделитель тысяч), обычный пробел убирает группировку, замена запятой на точку выравнивает десятичный разделитель. Знаки %, руб. и подобное вычищайте отдельно, под свой источник.

Попытка и Исключение

Если важно показать пользователю конкретную строку с проблемой, оборачивайте только само преобразование, а не весь цикл.

Для Каждого Строка Из Таблица Цикл
	Попытка
		Сумма = Число(Строка.Сумма);
	Исключение
		Сообщить("Строка " + Строка.НомерСтроки + ": не число «" + Строка.Сумма + "». " + ОписаниеОшибки());
		Продолжить;
	КонецПопытки;
	// дальнейшая обработка суммы
КонецЦикла;

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

Не оборачивайте в Попытка весь обработчик проведения и не оставляйте пустой Исключение. Платформа откатит часть действий, а пользователь увидит «успех» с неполными данными.

Проверка типа до действия

Для универсальных процедур дешевле проверить тип, чем ловить исключение:

Если ТипЗнч(Значение) = Тип("Строка") Тогда
	// чистим и преобразуем
ИначеЕсли ТипЗнч(Значение) = Тип("Число") Тогда
	// используем как есть
Иначе
	// Дата, Булево, ссылка: сообщаем об ошибке данных
КонецЕсли;

Разделители, знаки и региональные настройки

Десятичная запятая или точка, группировка тысяч: частая причина, когда на одном компьютере код работает, а на другом падает.

Как платформа читает строку, зависит от региональных настроек среды, где выполняется код. Клиентский код опирается на настройки компьютера пользователя, серверный на настройки сервера 1С. Поэтому файл «1 234,56» может спокойно читаться на ваших машинах и не читаться на сервере с другой локалью.

Что с этим делать:

  • ✅ Не полагайтесь на локаль. Приводите строку к одному виду сами: уберите пробелы, замените запятую на точку, и только потом Число().
  • ✅ Для записи числа в строку используйте Формат(Значение, "ЧДЦ=2; ЧГ=0") вместо Строка(Значение): форматирование явно задаёт число знаков и отключает группировку.
  • ✅ Для обмена в XML и JSON держите формат фиксированным: десятичный разделитель точка, без группировки. Для XML удобно XMLЗначение и XMLСтрока, они не зависят от локали.
  • ✅ Для минуса проверьте, что это обычный дефис-минус. В файлах из чужих систем встречается длинное тире и «минус» из набора Unicode, которые Число() не принимает.

Если строка вида "1 234,56" у вас читается на одном сервере и не читается на другом, сравните региональные параметры операционной системы, под учётной записью которой запущена служба сервера 1С. Менять их без согласования с администратором не нужно: надёжнее поправить код.

Данные из внешних источников

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

Excel и CSV

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

Внешние базы и COM

При чтении из внешней СУБД через ADO значение может прийти как Null (в 1С это отдельный тип Null, не Неопределено). Прямое Число(Null) падает, проверяйте ТипЗнч(Значение) = Тип("Null") до преобразования.

Веб-сервисы, XML и JSON

  • Пустой узел XML даёт пустую строку или Неопределено, смотрите на схему, а не на пример.
  • Число в JSON бывает строкой: "amount": "100.50". После ПрочитатьJSON тип будет строка, а не число.
  • Скобки, валюта и знак процента попадают в значение, если сервис форматирует цены «для людей».

Не меняйте тип на стороне 1С, если ошибка вызвана «кривыми» данными источника. Лучше договориться об исправлении источника и оставить в 1С защитную проверку с понятным текстом.

Запросы и отчёты: когда ошибка живёт в СКД

В запросе ошибка выглядит иначе: «Значение не может быть преобразовано к типу Число» при выполнении запроса или в отчёте. Причина в поле составного типа (скажем, реквизит принимает и число, и строку), которое вы складываете или сравниваете как число.

Что помогает:

  1. Явно приведите тип в запросе: ВЫРАЗИТЬ(Реквизит КАК ЧИСЛО(15, 2)). Значения, не приводимые к числу, потребуют отдельной обработки до этого шага.
  2. В выражениях СКД проверяйте тип через ЕстьNULL(...) и условия ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ, чтобы строки не попадали в арифметику.
  3. Проверьте соединение: поле из левой таблицы может быть NULL, и после ЛЕВОЕ СОЕДИНЕНИЕ сумма «исчезает». Оберните в ЕСТЬNULL(Поле, 0).

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

Как не получать эту ошибку

Хорошая практика при написании кода, который работает с чужими числами:

  • 🛡️ Принимайте данные через одну функцию-преобразователь. Одно место, где решено, что считать числом, и что делать с мусором.
  • 🛡️ Задавайте типы явно. Реквизиты и параметры процедур с описанием Число(15, 2) отсекают часть проблем ещё при записи.
  • 🛡️ Не складывайте строки и числа через +. Для строки используйте Строка() и Формат() явно, для чисел Число() только после проверки.
  • 🛡️ Логируйте плохие значения. Строка с номером и текстом ячейки сэкономит час поиска, когда придёт новая выгрузка.
  • 🛡️ Тестируйте на плохих данных. Дайте обработке файл с пустой ячейкой, дефисом, пробелом, 100,5 и 100.5 и убедитесь, что она ведёт себя предсказуемо.
Проверка кода перед выпуском в работу
Выполнено: 0 / 5

Частые вопросы

Чем отличается `Число("")` от `Число(Неопределено)`?
Пустая строка даёт 0, Неопределено вызывает ошибку преобразования. Поэтому пустая ячейка проходит, а «не прочитанное» значение ломает код.
Можно ли отключить эту ошибку в настройках платформы?
Нет. Это поведение языка, а не настройка. Решается кодом: проверкой типа, очисткой строки или ПривестиЗначение.
Почему на одном компьютере работает, а на другом нет?
Скорее всего, дело в региональных настройках: десятичная запятая или точка и разделитель тысяч у компьютеров разные. Приводите строку к единому виду в коде, не надеясь на локаль.
`ПривестиЗначение` или `Попытка`: что выбрать?
ПривестиЗначение, если ноль вместо мусора допустим (отчёты, оценки). Попытка, если нужно сообщить о проблемной строке и не искажать суммы (документы, учётные данные).
Что делать, если ошибка у пользователя в типовой конфигурации?
Зафиксируйте текст ошибки и последовательность действий, найдите документ или данные, на которых она воспроизводится, и передайте программисту. Править типовой модуль напрямую не стоит: изменения слетят при обновлении.