При разработке обработок в 1С часто возникает ситуация, когда пользователю необходимо сохранить введенные данные (реквизиты формы), чтобы не заполнять их повторно при каждом запуске. Традиционно для этого используется механизм ХранилищеОбщихНастроек. Однако, если ту же самую логику требуется запускать автоматически по расписанию через регламентные задания, разработчики сталкиваются с тем, что метод ХранилищеОбщихНастроек.Загрузить() возвращает Неопределено. Разберем подробно, почему так происходит, и какие архитектурные решения позволяют обойти это ограничение.
Для начала проанализируем, как работает механизм хранилища настроек. Объекты ХранилищеОбщихНастроек, ХранилищеНастроекДанныхФорм и другие подобные им жестко привязаны к контексту текущего пользователя 1С. Когда вы вызываете метод Загрузить(КлючОбъекта, КлючНастроек), система неявно обращается к настройкам именно того пользователя, под которым запущен текущий сеанс.
Рассмотрим ситуацию в фоновом задании:
Загрузить() не находит соответствующих записей в базе данных и возвращает Неопределено.Таким образом, использование ХранилищеОбщихНастроек для передачи параметров в регламентные задания является архитектурно неверным подходом.
Если вы используете конфигурацию на базе Библиотеки стандартных подсистем (БСП), самым правильным и надежным способом будет использование стандартного механизма хранения параметров внешних обработок. Рассмотрим этот процесс по шагам.
В подсистеме ДополнительныеОтчетыИОбработки при настройке регламентного задания для внешней обработки предусмотрена возможность хранения параметров. Эти параметры передаются в экспортную процедуру обработки в виде структуры. Проанализируем, как должна выглядеть структура экспортной процедуры в модуле объекта обработки:
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
// ПараметрыВыполненияКоманды содержит настройки,
// сохраненные в справочнике "Дополнительные отчеты и обработки"
Если ПараметрыВыполненияКоманды.Свойство("ПараметрыЗапуска") Тогда
Настройки = ПараметрыВыполненияКоманды.ПараметрыЗапуска;
// Здесь мы получаем структуру настроек, которую сохранили ранее
ВыполнитьОсновнуюЛогику(Настройки);
КонецЕсли;
КонецПроцедуры
При таком подходе вам не нужно вручную вызывать Загрузить(). БСП сама извлекает настройки из своего внутреннего хранилища (обычно это реквизит типа ХранилищеЗначения в справочнике) и передает их в обработку. Это гарантирует работоспособность кода вне зависимости от того, какой пользователь инициировал задание.
Если конфигурация не использует БСП или вам требуется более гибкий контроль, разберем способ с использованием собственного Регистра Сведений. Это наиболее универсальный метод, позволяющий хранить настройки в разрезе любых измерений (например, "Организация" или "Склад"), а не только пользователей.
Шаг 1. Создание регистра:
Создадим регистр сведений (например, НастройкиФоновыхЗаданий). В качестве ресурсов добавим реквизит ЗначениеНастроек с типом ХранилищеЗначения. Это позволит сериализовать любую структуру параметров формы.
Шаг 2. Сохранение настроек из формы:
В модуле формы обработки, там, где пользователь нажимает кнопку "Сохранить настройки" или перед запуском задания, напишем следующий код:
&НаСервере
Процедура СохранитьНастройкиДляФоновогоЗаданияНаСервере()
НастройкиДляСохранения = Новый Структура;
НастройкиДляСохранения.Вставить("Организация", Объект.Организация);
НастройкиДляСохранения.Вставить("ДатаНачала", Объект.ДатаНачала);
НастройкиДляСохранения.Вставить("ИспользоватьФильтр", Объект.ИспользоватьФильтр);
МенеджерЗаписи = РегистрыСведений.НастройкиФоновыхЗаданий.СоздатьМенеджерЗаписи();
МенеджерЗаписи.КлючНастроек = "МояУникальнаяОбработка";
МенеджерЗаписи.ЗначениеНастроек = Новый ХранилищеЗначения(НастройкиДляСохранения);
МенеджерЗаписи.Записать();
КонецПроцедуры
Шаг 3. Загрузка настроек в фоновом задании:
Теперь в функции, которая выполняется регламентно, мы заменим некорректный вызов ХранилищеОбщихНастроек на чтение из нашего регистра:
Процедура ВыполнитьРегламентно() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| НастройкиФоновыхЗаданий.ЗначениеНастроек КАК ЗначениеНастроек
|ИЗ
| РегистрСведений.НастройкиФоновыхЗаданий КАК НастройкиФоновыхЗаданий
|ГДЕ
| НастройкиФоновыхЗаданий.КлючНастроек = &КлючНастроек";
Запрос.УстановитьПараметр("КлючНастроек", "МояУникальнаяОбработка");
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Настройки = Выборка.ЗначениеНастроек.Получить();
Если ТипЗнч(Настройки) = Тип("Структура") Тогда
// Теперь у нас есть доступ к данным реквизитов формы
ВыполнитьОбработкуДанных(Настройки);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим еще один важный механизм платформы — передачу параметров непосредственно при создании задания. Если ваше фоновое задание запускается не жестко по расписанию, а программно из кода (например, при нажатии кнопки "Выполнить в фоне"), параметры можно передать напрямую.
Метод ФоновыеЗадания.Выполнить() принимает массив параметров, которые будут переданы в экспортную процедуру. Проанализируем пример:
// В коде формы
ПараметрыПроцедуры = Новый Массив;
ПараметрыПроцедуры.Добавить(СтруктураРеквизитовФормы);
ФоновыеЗадания.Выполнить("МойОбщийМодуль.ВыполнитьОбработку", ПараметрыПроцедуры);
Важное ограничение: Все данные, передаваемые в фоновое задание, должны быть сериализуемыми. Вы не можете передать саму форму или объект обработки. Вы должны собрать все необходимые значения в Структуру, Массив или ТаблицуЗначений.
Разберем несколько важных нюансов, которые помогут избежать ошибок при работе с регламентными заданиями:
Попытка...Исключение внутри кода регламентного задания. Ошибки в фоне не выводятся на экран, их можно увидеть только в Журнале регистрации.C:\). Если ваша обработка должна читать файлы, используйте общие сетевые папки или предварительно загружайте файлы в базу данных в виде ДвоичныеДанные.Подведем итог: для передачи данных в фоновые задачи мы отказываемся от ХранилищеОбщихНастроек в пользу регистров сведений с ХранилищемЗначения или механизмов БСП. Это делает систему устойчивой к смене контекста пользователя и гарантирует стабильную работу регламентных операций.