В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача сохранения состояния элементов формы, которые не связаны напрямую с реквизитами объекта (документа или справочника). Стандартный механизм платформы СохранениеДанныхВНастроек отлично справляется с запоминанием последних введенных значений для конкретного пользователя, но он не умеет привязывать эти данные к конкретному экземпляру документа. В результате, открыв новый документ, пользователь видит данные из предыдущего, что часто является ошибкой логики.
Разберем детально, как реализовать сохранение данных именно в разрезе каждого документа, рассмотрим несколько подходов — от классических до более «хитрых» методов, которые позволяют обойти ограничения по изменению структуры конфигурации.
Проанализируем самый надежный и прозрачный способ с точки зрения архитектуры базы данных — создание вспомогательного регистра сведений. Это решение идеально подходит, если вам запрещено добавлять реквизиты непосредственно в документ, но необходимо обеспечить 100% сохранность данных.
Для реализации этого метода выполним следующие шаги:
ЗначенияРеквизитовФормОбъектов).Объект с типом ЛюбаяСсылка (или ссылкой на конкретный документ).Значение (тип зависит от ваших нужд, например, Булево или ХранилищеЗначения для сложных структур).Теперь рассмотрим программную реализацию в модуле формы документа. Нам необходимо считать данные при открытии и записать их при сохранении документа.
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Читаем значение из регистра по ссылке текущего документа
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗначенияРеквизитовФормОбъектов.Значение КАК Значение
|ИЗ
| РегистрСведений.ЗначенияРеквизитовФормОбъектов КАК ЗначенияРеквизитовФормОбъектов
|ГДЕ
| ЗначенияРеквизитовФормОбъектов.Объект = &Объект";
Запрос.УстановитьПараметр("Объект", ТекущийОбъект.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Объект.МойРеквизитФормы = Выборка.Значение;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// Записываем значение в регистр
МенеджерЗаписи = РегистрыСведений.ЗначенияРеквизитовФормОбъектов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = ТекущийОбъект.Ссылка;
МенеджерЗаписи.Значение = МойРеквизитФормы; // Реквизит формы
МенеджерЗаписи.Записать();
КонецПроцедуры
Этот метод гарантирует, что данные будут храниться вечно, доступны в запросах и не пропадут при очистке настроек пользователя.
Если создание новых объектов метаданных (регистров) нежелательно, проанализируем возможность использования системного хранилища настроек. Платформа позволяет сохранять произвольные значения, используя уникальные ключи. Чтобы данные привязывались к документу, мы используем УникальныйИдентификатор ссылки документа в качестве ключа настроек.
Рассмотрим, как это реализовать программно. Мы будем использовать объект ХранилищеОбщихНастроек.
&НаСервере
Процедура ВосстановитьЗначениеИзНастроек()
Если Объект.Ссылка.Пустая() Тогда
Возврат;
КонецЕсли;
// Ключ объекта - это путь к форме, Ключ настроек - уникальный ID документа
КлючОбъекта = "НастройкиМоейФормыДокумента";
КлючНастроек = Строка(Объект.Ссылка.УникальныйИдентификатор());
МойРеквизитФормы = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек);
КонецПроцедуры
&НаСервере
Процедура СохранитьЗначениеВНастройки()
Если Объект.Ссылка.Пустая() Тогда
Возврат;
КонецЕсли;
КлючОбъекта = "НастройкиМоейФормыДокумента";
КлючНастроек = Строка(Объект.Ссылка.УникальныйИдентификатор());
ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, КлючНастроек, МойРеквизитФормы);
КонецПроцедуры
Важный нюанс: Стандартные события ПриЗагрузкеДанныхИзНастроекНаСервере срабатывают раньше, чем документ успевает прочитаться из базы, поэтому в них ссылка объекта может быть еще не определена. Рекомендуем вызывать восстановление данных в событии ПриЧтенииНаСервере или ПриОткрытии (через серверный вызов).
Выясним причину, по которой руководители часто запрещают добавлять реквизиты: это усложняет обновление типовых конфигураций. Однако использование Расширений полностью решает эту проблему. Вы можете добавить реквизит к документу в расширении, и он будет вести себя как родной реквизит объекта: храниться в таблице документа, быть доступным в запросах и при этом не менять основную конфигурацию.
Пошаговый алгоритм работы с расширением:
Преимущество: Это самый "чистый" профессиональный метод. Платформа сама позаботится о сохранении, чтении и разграничении прав доступа.
Рассмотрим ситуацию, когда нельзя менять ни конфигурацию, ни расширения, ни добавлять регистры. Если в документе есть существующее строковое поле достаточной длины (например, Комментарий или какое-то служебное поле), мы можем хранить данные там в зашифрованном или структурированном виде (JSON или XML).
Посмотрим на пример реализации с использованием JSON:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Допустим, мы храним данные в начале комментария в формате [Flag=True]
Если Найти(ТекущийОбъект.Комментарий, "[Flag=True]") > 0 Тогда
МойРеквизитФормы = Истина;
Иначе
МойРеквизитФормы Ложь;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Очищаем старую метку и пишем новую
ТекущийОбъект.Комментарий = СтрЗаменить(ТекущийОбъект.Комментарий, "[Flag=True]", "");
ТекущийОбъект.Комментарий = СтрЗаменить(ТекущийОбъект.Комментарий, "[Flag=False]", "");
Метка = ?(МойРеквизитФормы, "[Flag=True]", "[Flag=False]");
ТекущийОбъект.Комментарий = Метка + ТекущийОбъект.Комментарий;
КонецПроцедуры
Этот метод считается "костылем", но в экстремальных условиях жестких запретов он позволяет добиться цели. Однако помните, что пользователи могут случайно удалить эти данные при редактировании комментария.
Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), проанализируем механизм "Дополнительные реквизиты и сведения". Этот механизм специально создан для добавления свойств объектам без изменения метаданных.
Вам достаточно в режиме "1С:Предприятие" зайти в раздел "Администрирование" -> "Дополнительные сведения" и добавить новое свойство для вашего документа. После этого оно появится в специальном окне, а при желании его можно вывести программно прямо на форму документа. Данные хранятся в стандартном регистре сведений ДополнительныеСведения, который уже оптимизирован для работы под нагрузкой.
Мы рассмотрели различные подходы к сохранению данных формы. Выбор метода зависит от ваших условий:
Помните, что "профессионализм", о котором шла речь в обсуждении на форуме, заключается не только в знании обходных путей, но и в умении выбрать наиболее поддерживаемое и масштабируемое решение.