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