Как исправить ошибку «Значение не является значением объектного типа» при работе регламентного задания с хранилищем настроек?

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

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

Выясняем причину: почему «вручную» работает, а в регламентном задании — нет?

Проанализируем ситуацию. Когда вы открываете форму обработки и сохраняете настройки, система 1С:Предприятие использует объект ХранилищеОбщихНастроек или ХранилищеПользовательскихНастроекОтчетов. По умолчанию эти настройки привязываются к текущему пользователю, под которым вы авторизованы в системе.

Разберем, что происходит в момент выполнения регламентного задания:

  1. Регламентное задание запускается в фоновом сеансе на сервере.
  2. В зависимости от настроек, фоновое задание может выполняться либо под специальным служебным пользователем, либо под пользователем, указанным в консоли регламентных заданий.
  3. Если в коде используется метод ХранилищеОбщихНастроек.Загрузить("КлючОбъекта", "КлючНастроек") без явного указания имени пользователя, система пытается найти настройки для текущего пользователя фонового сеанса.

Поскольку настройки сохранял «Иванов», а задание выполняет «СлужебныйПользователь», метод Загрузить() возвращает Неопределено. Как только код пытается обратиться к свойству ЗагруженныеНастройки.ДатаНачала, возникает фатальная ошибка, так как у Неопределено не может быть свойств.

Решение 1. Явное указание пользователя при загрузке настроек

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


// Неправильно (ищет настройки текущего фонового сеанса)
Настройки = ХранилищеОбщихНастроек.Загрузить("МояОбработка_Ключ", "НастройкиПериода");

// Правильно (явно указываем пользователя, чьи настройки нам нужны)
ИмяПользователяНастроек = "Администратор"; // Или берем из параметра
Настройки = ХранилищеОбщихНастроек.Загрузить("МояОбработка_Ключ", "НастройкиПериода", , ИмяПользователяНастроек);

Если Настройки <> Неопределено Тогда
    ДатаНачала = Настройки.ДатаНачала;
Иначе
    // Обработка ситуации, когда настройки не найдены
    ДатаНачала = НачалоДня(ТекущаяДата());
КонецЕсли;

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

Решение 2. Использование механизмов БСП для дополнительных обработок

Если ваша обработка встроена в информационную базу через подсистему «Дополнительные отчеты и обработки» Библиотеки Стандартных Подсистем (БСП), то существует более элегантный и надежный способ. В справочнике ДополнительныеОтчетыИОбработки предусмотрен специальный реквизит ХранилищеНастроек с типом ХранилищеЗначения.

Проанализируем преимущества этого метода:

При выполнении регламентного задания БСП передает в модуль объекта обработки параметры. Мы можем извлечь сохраненные данные следующим образом:


// В модуле объекта дополнительной обработки
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
    
    // Получаем объект настройки из справочника "Дополнительные отчеты и обработки"
    // Ссылка на текущую обработку обычно доступна в контексте выполнения
    ОбъектДопОбработки = ПараметрыВыполненияКоманды.ДополнительнаяОбработкаСсылка.ПолучитьОбъект();
    
    Если ОбъектДопОбработки.ХранилищеНастроек.Получить() <> Неопределено Тогда
        СтруктураНастроек = ОбъектДопОбработки.ХранилищеНастроек.Получить();
        ДатаНачала = СтруктураНастроек.ДатаНачала;
    Иначе
        // Значения по умолчанию
        ДатаНачала = ТекущаяДата();
    EndIf;
    
КонецПроцедуры

Специфика работы с типом «СтандартныйПериод»

Часто в формах используется реквизит с типом СтандартныйПериод. При попытке сохранить его напрямую в ХранилищеОбщихНастроек и последующей загрузке в фоновом задании, иногда происходит ошибка десериализации, особенно если версии платформы на клиенте и сервере имеют нюансы. Рассмотрим, как обезопасить себя:

Вместо сохранения всего объекта СтандартныйПериод, рекомендуется сохранять обычную Структуру с примитивными типами (Дата). Посмотрим на пример:


// При сохранении в форме
НастройкиДляХранилища = Новый Структура;
НастройкиДляХранилища.Вставить("ДатаНачала", Объект.Период.ДатаНачала);
НастройкиДляХранилища.Вставить("ДатаОкончания", Объект.Период.ДатаОкончания);

ХранилищеОбщихНастроек.Сохранить("МояОбработка", "Ключ", НастройкиДляХранилища);

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

Нюансы отладки фоновых заданий

Многие разработчики сталкиваются с тем, что «в отладчике всё работает». Это происходит из-за того, что отладка часто запускается путем имитации вызова серверного метода из клиентского сеанса. В этом случае контекст пользователя сохраняется, и система видит настройки.

Чтобы увидеть реальную картину, выполните следующие шаги:

  1. Используйте автоматическое подключение к фоновым заданиям в конфигураторе (Меню: Отладка -> Подключение -> Автоматическое подключение -> Фоновые задания).
  2. Убедитесь, что в консоли регламентных заданий указан именно тот пользователь, под которым вы ожидаете запуск.
  3. Если вы используете файловую базу, помните, что регламентные задания выполняются только в том случае, если запущен отдельный сеанс или включена поддержка фоновых заданий в текущем сеансе.

Проанализировав все вышеперечисленные моменты, мы можем сделать вывод: главная проблема кроется в пустом значении, которое возвращает хранилище из-за разницы в пользователях. Используйте явную проверку ТипЗнч() или проверку на Неопределено, и ваше регламентное задание станет гораздо стабильнее.

← На главную