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

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

При изучении программирования в 1С, особенно проходя примеры из «Практического пособия разработчика» (например, М.Г. Радченко), многие сталкиваются с ошибками типов данных на этапе проведения документов расчета зарплаты. Одной из самых частых и сбивающих с толку ошибок является сообщение: «Преобразование значения к типу Число не может быть выполнено».

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

Анализ текста ошибки и кода

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


ЗаписьРегистра.Результат = (ЗаписьРегистра.ИсходныеДанные/ВыборкаРезультата.Норма) * ВыборкаРезультата.Факт;

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

Давайте проанализируем компоненты формулы:

  1. ЗаписьРегистра.ИсходныеДанные — значение, которое берется из ресурса регистра (обычно заполняется при формировании движений в модуле документа).
  2. ВыборкаРезультата.Норма — данные, полученные из запроса к графику работы.
  3. ВыборкаРезультата.Факт — данные, также полученные из запроса к графику.

Если хотя бы одна из этих переменных содержит Null (значение базы данных, обозначающее отсутствие данных), вычисление всей формулы падает с ошибкой, так как в языке 1С операция Число * Null или Число / Null недопустима.

Основная причина: Отсутствие данных графика

В ходе обсуждения выяснилось, что наиболее вероятной причиной является получение пустых значений (NULL) из запроса к виртуальной таблице графика. Давайте посмотрим на текст запроса, который используется в коде:


"ВЫБРАТЬ
| НачисленияДанныеГрафика.ЗначениеПериодДействия КАК Норма,
| НачисленияДанныеГрафика.ЗначениеФактическийПериодДействия КАК Факт,
...
|ИЗ
| РегистрРасчета.Начисления.ДанныеГрафика(...)
| КАК НачисленияДанныеГрафика";

Виртуальная таблица ДанныеГрафика работает по принципу левого соединения (Left Join) основной таблицы регистра расчета с таблицей регистра сведений, содержащего графики работы. Соединение происходит по измерению ГрафикРаботы и датам периода действия.

Суть проблемы: Если на конкретную дату (или период), за который производится расчет, в регистре сведений (графике) отсутствуют записи, то соединение не находит соответствия. В результате поля Норма и Факт возвращают значение NULL.

В примере из темы проблема заключалась в следующем:

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

Почему автор вопроса утверждал, что в отладчике он видит числа? Это распространенная ошибка при отладке циклов. В цикле Для Каждого ЗаписьРегистра Из НаборЗаписейРегистра может обрабатываться несколько строк (несколько сотрудников).

  1. Первые сотрудники могут иметь корректные данные (например, если период у них указан верно, или если они попали в "заполненный" кусок графика).
  2. Вы смотрите в отладчике значения на первой итерации цикла — там все отлично, числа.
  3. Вы нажимаете "Продолжить" (F5), цикл доходит до проблемной строки (например, сотрудника с неверным годом или графиком), значения становятся NULL, и программа падает.

Чтобы поймать ошибку, необходимо использовать Точку останова с условием или просматривать значения переменных непосредственно в момент падения (когда конфигуратор останавливается на строке с ошибкой). В табло (Shift+F9) нужно проверить:

Решения проблемы

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

Способ 1: Исправление данных (Пользовательский уровень)

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

  1. Проверьте даты начала и окончания периода действия в табличной части документа «Начисления сотрудникам». Убедитесь, что год и месяц соответствуют ожидаемым.
  2. Откройте справочник ГрафикиРаботы и связанный с ним регистр сведений (обычно ГрафикиРаботы).
  3. Убедитесь, что график заполнен на тот период, за который вы пытаетесь начислить зарплату. В учебных конфигурациях часто нужно нажать кнопку «Заполнить» в форме графика, чтобы сформировались записи в регистре на новый год.

Способ 2: Защита кода от NULL (Программный уровень)

Даже если пользователь ошибся с датой, программа не должна "падать" с критической ошибкой платформы. Хорошим тоном программирования является обработка возможных значений NULL непосредственно в запросе.

Для этого используйте функцию языка запросов ЕСТЬNULL (ISNULL). Она позволяет заменить NULL на значение по умолчанию (обычно 0) на этапе выборки данных.

Изменим текст запроса в общем модуле следующим образом:


Запрос.Текст =
"ВЫБРАТЬ
| ЕСТЬNULL(НачисленияДанныеГрафика.ЗначениеПериодДействия, 0) КАК Норма,
| ЕСТЬNULL(НачисленияДанныеГрафика.ЗначениеФактическийПериодДействия, 0)
| КАК Факт,
| НачисленияДанныеГрафика.НомерСтроки КАК НомерСтроки
|ИЗ
| РегистрРасчета.Начисления.ДанныеГрафика(Регистратор = &Регистратор И
| ВидРасчета = &ВидРасчета И Сотрудник В (&СписокСотрудников))
| КАК НачисленияДанныеГрафика";

Что это даст?

  1. Если график не заполнен, поля Норма и Факт вернут число 0 вместо NULL.
  2. Далее в коде сработает уже существующая проверка:
    
    Если ВыборкаРезультата.Норма = 0 Тогда
        // Вывод сообщения пользователю о том, что нет рабочих дней
        ЗаписьРегистра.Результат = 0;
    Иначе
        // Расчет выполняется корректно
    КонецЕсли;
    

Таким образом, вместо падения программы пользователь получит понятное сообщение: "Вид расчета: Оклад – Нет рабочих дней в заданном периоде".

Дополнительная проверка: Исходные Данные

Хотя в данном случае проблема была в графике, не стоит забывать про переменную ЗаписьРегистра.ИсходныеДанные. Она заполняется в модуле документа при формировании движений:

Движение.ИсходныеДанные = ТекСтрокаНачисления.Начислено;

Если в документе колонка "Начислено" не заполнена, а тип значения допускает пустые ссылки или Неопределено, это также может привести к ошибке. Однако для числовых ресурсов регистра, если не задано иное, пустое значение обычно преобразуется в 0 при записи. Тем не менее, рекомендуется всегда контролировать заполненность реквизитов документа перед проведением, используя метод ПроверитьЗаполнение().

Резюме

Ошибка «Преобразование значения к типу Число не может быть выполнено» при расчете зарплаты почти всегда означает, что запрос к виртуальной таблице ДанныеГрафика вернул NULL из-за отсутствия календарных данных за указанный период. Чтобы исправить это, нужно заполнить графики работы на нужный год. Чтобы предотвратить ошибку в будущем — обернуть поля запроса в функцию ЕСТЬNULL(Поле, 0).

← На главную