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