Почему регламентное задание 1С выдает ошибку преобразования числа, хотя вручную всё работает?

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

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

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

Различие контекстов: Тонкий клиент против Сервера

Первым делом проанализируем, почему код ведет себя по-разному. Когда мы запускаем отчет вручную, выполнение части кода может происходить на стороне клиента (в тонком или толстом клиенте). В этом случае доступны текущие настройки пользователя, его права и, что самое важное, полностью инициализированное окружение.

Регламентное задание (РЗ) порождает фоновое задание, которое всегда выполняется на сервере. Рассмотрим основные отличия:

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

Локализация ошибки с помощью Журнала регистрации

Поскольку отладка на «боевом» сервере часто невозможна, воспользуемся методом расширенного логирования. Рассмотрим ситуацию: ошибка возникает при расчете итогов. Для понимания того, что именно идет не так, внесем изменения в код, добавив блок Попытка...Исключение.

Посмотрим на пример кода, который поможет выявить проблемную переменную:


Попытка
    // Опасный участок кода, где происходит деление или умножение
    Результат = Выборка.Сумма / Выборка.Количество * 100;
Исключение
    ТекстОшибки = СтрШаблон("Ошибка в строке 468. Тип Сумма: %1, Значение Сумма: %2. Тип Количество: %3, Значение Количество: %4",
        ТипЗнч(Выборка.Сумма), Выборка.Сумма,
        ТипЗнч(Выборка.Количество), Выборка.Количество);
    
    ЗаписьЖурналаРегистрации("ОтчетВыгрузка.ОшибкаРасчета",
        УровеньЖурналаРегистрации.Ошибка,,, 
        ТекстОшибки + " | " + ОписаниеОшибки());
КонецПопытки;

После выполнения регламентного задания посмотрите в Журнал регистрации. Если вместо ожидаемых чисел вы увидите Undefined или NULL, значит, корень проблемы — в данных или в запросе, который эти данные поставляет.

Ловушка параметров сеанса: главная причина сбоя

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

Выясним, почему это происходит. В 1С есть специальный механизм — модуль сеанса, где процедура УстановкаПараметровСеанса отвечает за наполнение этих данных. Если внутри этой процедуры стоит условие Если НЕ РольДоступна("ПолныеПрава") Тогда... или проверка на конкретного пользователя, то фоновое задание, работающее под системным пользователем, может «пролететь» мимо инициализации.

В результате запрос возвращает пустую выборку. Если код не содержит проверки Если Выборка.Следующий() Тогда, то обращение к полям выборки вернет Undefined. Попытка совершить математическую операцию с Undefined неминуемо приведет к ошибке Cannot convert value to Numeric.

Реализация надежного кода: оборонительное программирование

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

Разберем правильный подход на примере:


Выборка = Запрос.Выполнить().Выбрать();

// Обязательная проверка на наличие записей
Пока Выборка.Следующий() Цикл
    
    // Используем Число() для защиты от NULL, если это допустимо бизнес-логикой
    Значение1 = ?(ТипЗнч(Выборка.Переменная2) = Тип("Число"), Выборка.Переменная2, 0);
    Значение2 = ?(ТипЗнч(Выборка.Переменная3) = Тип("Число"), Выборка.Переменная3, 0);
    
    // Защита от деления на ноль
    Если Значение2 <> 0 Тогда
        облИтог.Параметры.Переменная1 = Значение1 / Значение2 * 100;
    Иначе
        облИтог.Параметры.Переменная1 = 0; // Или другое значение по умолчанию
    КонецЕсли;

КонецЦикла;

Нюансы работы с Excel на сервере

Хотя в данном случае проблема была в данных, при выгрузке в Excel через регламентные задания часто возникают проблемы с COM-объектами. Помните: на сервере нельзя использовать интерактивные функции Excel.

Если ваша выгрузка использует Новый COMОбъект("Excel.Application"), убедитесь, что:

Однако лучшим решением для регламентных заданий будет использование встроенных средств 1С: сохранение табличного документа в формат ТипФайлаТабличногоДокумента.XLSX. Это работает быстрее, стабильнее и не требует установленного Excel на сервере.

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

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

  1. Проверить модуль сеанса на предмет корректного заполнения ПараметрыСеанса для фоновых заданий.
  2. Добавить в код отчета проверку на пустую выборку (Выборка.Следующий()).
  3. Обеспечить инициализацию всех переменных значениями по умолчанию (0), если данные из БД не получены.
  4. При использовании расчетов в цикле всегда проверять делитель на равенство нулю.

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

← На главную