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