В практике разработки на платформе 1С:Предприятие 8.3 часто возникает ситуация: программист создает внешнюю обработку, в которой пользователь настраивает параметры (например, отборы, почтовые адреса или правила загрузки). Эти параметры сохраняются с помощью стандартного механизма Автоматического сохранения данных в настройках формы. Однако, когда эту же обработку нужно запустить по расписанию через регламентное задание, форма не создается, и ЭтаФорма оказывается недоступной. Рассмотрим, как программно «выковырять» нужные данные из системных хранилищ в модуле объекта.
Механизм автоматического сохранения привязан к уникальному ключу формы и конкретному пользователю. Когда вы открываете форму интерактивно, платформа сама подставляет значения в реквизиты. Но регламентное задание выполняется на сервере в контексте специального пользователя (часто это USR1CV8 или выделенный пользователь для фоновых заданий), у которого нет «открытой формы». Наша задача — имитировать процесс загрузки настроек, обратившись напрямую к системным таблицам базы данных.
Если данные были сохранены штатно через настройки формы, они попадают в ХранилищеСистемныхНастроек. Чтобы извлечь их в модуле объекта, нам нужно знать три вещи: ключ объекта, ключ настроек и имя пользователя. Проанализируем пример кода, который позволяет прочитать структуру настроек:
// В модуле объекта или в экспортной процедуре
Процедура ЗагрузитьНастройкиДляФоновогоЗадания() Экспорт
// Ключ объекта для внешних форм часто формируется динамически.
// Если обработка добавлена в справочник ДополнительныеОтчетыИОбработки,
// ключ может выглядеть как "ВнешняяОбработка.ИмяОбработки/Форма.ИмяФормы"
КлючОбъекта = "ВнешняяОбработка.МояОбработка.Форма.Форма";
КлючНастроек = "НастройкиФормы"; // Стандартный ключ или ваш программный
// Загружаем данные. Обратите внимание: метод возвращает Неопределено, если настроек нет.
СтруктураНастроек = ХранилищеСистемныхНастроек.Загрузить(КлючОбъекта, КлючНастроек);
Если СтруктураНастроек <> Неопределено Тогда
// Заполняем реквизиты текущего объекта из полученной структуры
ЗаполнитьЗначенияСвойств(ЭтотОбъект, СтруктураНастроек);
КонецЕсли;
КонецПроцедуры
Важный нюанс: при регламентном запуске ХранилищеСистемныхНастроек.Загрузить будет искать настройки того пользователя, под которым запущено задание. Если настройки сохранял «Администратор», а задание выполняет «Робот», метод вернет Неопределено. Чтобы этого избежать, используйте четвертый параметр метода — ИмяПользователя.
Выясним причину, почему полагаться на «автосохранение» формы в регламентных заданиях — плохая идея. Архитектура 1С предполагает, что интерфейсные настройки могут измениться при обновлении платформы или переименовании формы. Рассмотрим более надежный вариант: программное сохранение настроек в ХранилищеОбщихНастроек по кнопке на форме.
В модуле формы создадим команду «Сохранить настройки для расписания»:
&НаСервере
Процедура СохранитьНастройкиНаСервере()
СтруктураСохр = Новый Структура;
СтруктураСохр.Вставить("Организация", Объект.Организация);
СтруктураСохр.Вставить("СписокСкладов", Объект.СписокСкладов.ВыгрузитьЗначения());
// Используем фиксированный ключ, который не зависит от имени формы
ХранилищеОбщихНастроек.Сохранить("РегламентнаяЗагрузкаДанных", "ТекущиеНастройки", СтруктураСохр);
Сообщить("Настройки сохранены для регламентного задания");
КонецПроцедуры
Теперь в модуле объекта мы можем гарантированно получить эти данные, используя ХранилищеОбщихНастроек.Загрузить(). Этот метод более стабилен для фоновых процессов.
Проанализируем ситуацию, когда нам нужно хранить сложные типы данных (Таблицы значений, Деревья) или настройки, специфичные для разных экземпляров одной и той же внешней обработки. В конфигурациях, где нет БСП или нужно обойти ограничения прав доступа хранилищ, часто используют РегистрСведений.СохраненныеНастройки (или создают свой аналогичный).
Рассмотрим пример кода для модуля объекта, который позволяет сохранить все реквизиты обработки в ХранилищеЗначения:
Процедура СохранитьРеквизитыВБД() Экспорт
РеквизитыДляСохранения = Новый Структура;
Для каждого ТекРеквизит Из Метаданные().Реквизиты Цикл
РеквизитыДляСохранения.Вставить(ТекРеквизит.Имя, ЭтотОбъект[ТекРеквизит.Имя]);
КонецЦикла;
// Создаем запись в регистре или используем константу
// Ключом может выступать ИмяОбъекта или Ссылка (если обработка в справочнике)
Запись = РегистрыСведений.МоиНастройкиОбработок.СоздатьМенеджерЗаписи();
Запись.ОбъектНастройки = "МояУникальнаяОбработка";
Запись.Настройка = Новый ХранилищеЗначения(РеквизитыДляСохранения);
Запись.Записать();
КонецПроцедуры
Процедура ВосстановитьРеквизитыИзБД() Экспорт
Запись = РегистрыСведений.МоиНастройкиОбработок.СоздатьМенеджерЗаписи();
Запись.ОбъектНастройки = "МояУникальнаяОбработка";
Запись.Прочитать();
Если Запись.Выбран() Тогда
Данные = Запись.Настройка.Получить();
Если ТипЗнч(Данные) = Тип("Структура") Тогда
ЗаполнитьЗначенияСвойств(ЭтотОбъект, Данные);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В современных конфигурациях на базе БСП внешние обработки запускаются через справочник ДополнительныеОтчетыИОбработки. Посмотрим на архитектурно правильный путь:
ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды).ПараметрыВыполненияКоманды часто передается ссылка на сам элемент справочника (ДополнительнаяОбработкаСсылка).ХранилищеНастроек этого самого элемента справочника.Выясним, почему настройки могут не загружаться. Основные причины:
1. Разные пользователи. Если вы сохранили настройки под собой, а регламентное задание работает под системной учетной записью, Загрузить() вернет пустоту. Всегда проверяйте, под кем выполняется фоновое задание в Консоли регламентных заданий.
2. Несериализуемые типы. Если вы пытаетесь сохранить в структуру настроек элементы формы (например, ПолеФормы) вместо значений, платформа выдаст ошибку при попытке записи в хранилище. Сохраняйте только данные: числа, строки, даты, ссылки, массивы и структуры.
3. Кэширование. Иногда после изменения состава реквизитов старые сохраненные настройки могут конфликтовать с новыми. Используйте очистку настроек через Инструменты разработчика или программный вызов ХранилищеСистемныхНастроек.Удалить().
Таким образом, для решения задачи в модуле объекта внешней обработки оптимально использовать либо явное сохранение в ХранилищеОбщихНастроек с указанием конкретного ключа, либо хранение данных в регистре сведений. Это обеспечит стабильную работу регламентных заданий независимо от действий пользователя в интерфейсе.