Когда мы сталкиваемся с необходимостью сохранения пользовательских настроек в 1С:Предприятии, например, выбранного физического лица, мы можем попытаться использовать объект метаданных ХранилищеНастроек. Однако, иногда при попытке сохранить данные с помощью собственного хранилища, такого как ХранилищаНастроек.НастроекиТекущейРаботы, а затем их загрузить, мы получаем значение Неопределено. Разберем, почему так происходит и как правильно работать с различными типами хранилищ настроек в 1С.
Первоначальная проблема, с которой сталкивается автор, заключается в попытке использовать свой собственный объект метаданных НастроекиТекущейРаботы, созданный как тип ХранилищеНастроек, для сохранения переменной типа "Физическое лицо". Код, который он использует, выглядит следующим образом:
ХранилищаНастроек.НастроекиТекущейРаботы.Сохранить("МобильноеПроизводство","Продукция_ФизЛицо_Выбранный",ТекФизЛицо);
// ...
Значение = ХранилищаНастроек.НастроекиТекущейРаботы.Загрузить("МобильноеПроизводство","Продукция_ФизЛицо_Выбранный");
При этом Значение оказывается Неопределено. Мы можем предположить, что проблема не в самом типе сохраняемого значения (например, ФизЛицо), так как документация 1С указывает на возможность сохранения любого значения в хранилище. Ключевым моментом здесь является то, что НастроекиТекущейРаботы — это пользовательское хранилище настроек, созданное разработчиком.
Выясним причину, по которой наше самописное хранилище настроек не работает, и как это исправить. Объект метаданных ХранилищеНастроек в 1С не является самостоятельным хранилищем данных по умолчанию. Это скорее каркас или механизм, который позволяет нам определить, где и как будут физически храниться настройки. Если мы создали такой объект и его модуль менеджера остался пустым, то, по сути, мы не определили никакой логики сохранения и загрузки. Отсюда и возникает Неопределено при попытке загрузки – просто нет механизма, который бы сохранял и затем извлекал данные.
Для того чтобы наше пользовательское хранилище заработало, нам необходимо реализовать логику сохранения и загрузки в его модуле менеджера. Мы должны прописать обработчики событий ПриЗагрузке и ПриСохранении. Эти процедуры будут отвечать за взаимодействие с реальным местом хранения данных, например, с регистром сведений, справочником или другим прикладным объектом конфигурации.
ХранилищеНастроек: В данном случае, это уже сделано – НастроекиТекущейРаботы.НастройкиПользователей с измерениями Пользователь, КлючОбъекта, КлючНастроек и ресурсом ЗначениеНастройки типа ХранилищеЗначения.НастроекиТекущейРаботы: Откройте модуль менеджера вашего объекта метаданных НастроекиТекущейРаботы и добавьте в него процедуры ПриЗагрузке и ПриСохранении.Вот как мы могли бы реализовать логику сохранения и загрузки в модуле менеджера, если бы использовали регистр сведений НастройкиПользователей:
// Модуль менеджера объекта метаданных ХранилищеНастроек.НастроекиТекущейРаботы
Процедура ПриЗагрузке(КлючОбъекта, КлючНастроек, Пользователь, Значение) Экспорт
// Формируем уникальный ключ для записи в регистре
Перем ЗаписьРегистра;
ЗаписьРегистра = РегистрыСведений.НастройкиПользователей.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Пользователь = Пользователь;
ЗаписьРегистра.КлючОбъекта = КлючОбъекта;
ЗаписьРегистра.КлючНастроек = КлючНастроек;
Попытка
ЗаписьРегистра.Прочитать();
Если ЗаписьРегистра.ЭтоНовый() Тогда
Значение = Неопределено;
Иначе
Значение = ЗаписьРегистра.ЗначениеНастройки.Получить();
КонецЕсли;
Исключение
Значение = Неопределено;
КонецПопытки;
КонецПроцедуры
Процедура ПриСохранении(КлючОбъекта, КлючНастроек, Пользователь, Значение) Экспорт
// Формируем уникальный ключ для записи в регистре
Перем ЗаписьРегистра;
ЗаписьРегистра = РегистрыСведений.НастройкиПользователей.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Пользователь = Пользователь;
ЗаписьРегистра.КлючОбъекта = КлючОбъекта;
ЗаписьРегистра.КлючНастроек = КлючНастроек;
Попытка
ЗаписьРегистра.Прочитать();
ЗаписьРегистра.ЗначениеНастройки = Новый ХранилищеЗначения(Значение);
ЗаписьРегистра.Записать();
Исключение
// Обработка ошибки сохранения
КонецПопытки;
КонецПроцедуры
В этом примере мы видим, как процедуры ПриЗагрузке и ПриСохранении получают параметры КлючОбъекта, КлючНастроек, Пользователь и Значение. Внутри этих процедур мы сами определяем, как эти данные будут записываться или считываться из нашего прикладного объекта (в данном случае, регистра сведений). Без такой реализации модуль менеджера просто "ничего не делает" по умолчанию, поэтому и возвращается Неопределено.
Собственное хранилище имеет смысл создавать, когда нам требуется особая структура хранения настроек, специальные механизмы управления или необходимость обмена настройками между пользователями или конфигурациями.
Для большинства задач по хранению общих пользовательских настроек в 1С, таких как выбранное физическое лицо, отборы, видимость колонок и т.д., нам не нужно создавать собственное хранилище настроек. Платформа 1С предоставляет готовый, удобный и надежный механизм — ХранилищеОбщихНастроек. Это системное хранилище, предназначенное специально для сохранения пользовательских параметров, и оно работает "из коробки" без дополнительной реализации в модулях менеджеров.
Давайте рассмотрим, как мы можем использовать ХранилищеОбщихНастроек для решения нашей задачи.
Для сохранения значения мы используем статический метод Сохранить() объекта ХранилищеОбщихНастроек. Нам понадобятся три обязательных параметра: КлючОбъекта, КлючНастроек и Значение. Значение может быть любым сериализуемым объектом, включая ссылки на объекты метаданных, такие как ФизЛицо.
// В нашем случае, 'ТекФизЛицо' - это ссылка на объект ФизическоеЛицо
Перем ТекФизЛицо;
// ... получение значения ТекФизЛицо ...
// Сохраняем выбранное ФизЛицо для текущего пользователя
// "МобильноеПроизводство" - это КлючОбъекта (например, имя обработки или модуля)
// "Продукция_ФизЛицо_Выбранный" - это КлючНастроек (уникальное имя настройки)
ХранилищеОбщихНастроек.Сохранить("МобильноеПроизводство", "Продукция_ФизЛицо_Выбранный", ТекФизЛицо);
Мы видим, что синтаксис практически идентичен тому, что использовал автор с пользовательским хранилищем. Главное отличие в том, что ХранилищеОбщихНастроек уже имеет встроенную логику хранения.
Для загрузки значения мы используем статический метод Загрузить(). Здесь нам необходимо точно указать те же КлючОбъекта и КлючНастроек, которые мы использовали при сохранении.
// Загружаем сохраненное ФизЛицо
Перем ВыбранноеФизЛицо;
ВыбранноеФизЛицо = ХранилищеОбщихНастроек.Загрузить("МобильноеПроизводство", "Продукция_ФизЛицо_Выбранный");
Если ВыбранноеФизЛицо = Неопределено Тогда
Сообщить("Настройка 'Продукция_ФизЛицо_Выбранный' не найдена или не была сохранена.");
Иначе
Сообщить("Загружено ФизЛицо: " + ВыбранноеФизЛицо.Наименование);
КонецЕсли;
Если настройка существует и была сохранена, ВыбранноеФизЛицо будет содержать ссылку на объект "Физическое лицо". Если настройка не найдена (например, не была сохранена ранее или были указаны неверные ключи), метод вернет Неопределено.
Методы Сохранить() и Загрузить() ХранилищеОбщихНастроек также имеют необязательный четвертый параметр — ИмяПользователя. Это позволяет нам сохранять или загружать настройки не только для текущего, но и для другого пользователя.
// Сохранить настройку для конкретного пользователя (например, "Администратор")
ХранилищеОбщихНастроек.Сохранить("МобильноеПроизводство", "Продукция_ФизЛицо_Выбранный", ТекФизЛицо, "Администратор");
// Загрузить настройку, сохраненную для конкретного пользователя
ВыбранноеФизЛицоАдминистратора = ХранилищеОбщихНастроек.Загрузить("МобильноеПроизводство", "Продукция_ФизЛицо_Выбранный", "Администратор");
Мы должны быть внимательны при использовании этого параметра: имя пользователя должно точно совпадать с тем, что задано в конфигураторе. При переименовании пользователя старые настройки не будут автоматически перенесены, и для нового имени нужно будет сохранять их заново.
Помимо основной причины, рассмотренной выше, существуют и другие факторы, которые могут привести к получению Неопределено при загрузке настроек из хранилища:
ХранилищеОбщихНастроек. Однако, для чтения настроек другого пользователя или при работе с кастомным хранилищем, могут потребоваться дополнительные права или использование привилегированного режима (например, через общий модуль).КлючОбъекта и КлючНастроек, используемые в методах Сохранить(), в точности совпадали с теми, что используются в Загрузить(). Даже малейшее отличие (регистр символов, лишний пробел) приведет к тому, что настройка не будет найдена.ИмяПользователя), то при загрузке необходимо указать того же пользователя. Если не указать пользователя при загрузке, будет попытка получить настройку для текущего пользователя, что может привести к Неопределено, если настройка была сохранена для другого.ХранилищеОбщихНастроек может хранить большинство типов значений, некоторые сложные объекты или объекты, специфичные для сеанса, могут не сериализоваться должным образом или терять контекст. Однако, такие типы как ссылки на объекты метаданных (ФизЛицо) обычно сохраняются без проблем.Рассмотрев ситуацию с хранилищем настроек в 1С, мы приходим к выводу, что ключевой момент кроется в понимании различий между стандартными механизмами платформы и собственными разработками.
ХранилищеНастроек (как в примере НастроекиТекущейРаботы), нам обязательно нужно реализовать логику сохранения и загрузки в его модуле менеджера. Без этой реализации, наш каркас хранилища не будет выполнять никаких действий по сохранению данных.ФизЛицо) мы должны использовать стандартный механизм ХранилищеОбщихНастроек. Он предоставляет готовую функциональность и значительно упрощает разработку.Внимательно проверяя ключи настроек, права доступа и, при необходимости, реализуя логику в модулях менеджеров для собственных хранилищ, мы сможем эффективно управлять пользовательскими параметрами в наших информационных системах на платформе 1С:Предприятие.