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