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