Как предотвратить запись объекта в 1С, если данные не были изменены

Программист 1С v8.3 (Управляемые формы)
← На главную

Часто в практике разработчика 1С возникает ситуация, когда пользователи открывают карточку справочника или документ «просто посмотреть», но по привычке закрывают её нажатием кнопки «Записать и закрыть». Это приводит к созданию лишних записей в журнале регистрации, версионировании объектов и ненужной синхронизации данных в распределенных базах (РИБ). В этой статье мы разберем, как программно и интерфейсно ограничить запись, если объект фактически не редактировался.

Анализ механизма модифицированности

Прежде чем переходить к коду, проанализируем, как платформа понимает, что данные были изменены. В управляемых формах за это отвечает свойство Модифицированность. Этот флаг взводится в истину системой автоматически, как только пользователь меняет значение любого реквизита, связанного с данными формы. Однако стоит помнить, что программное изменение реквизитов в коде формы также может взвести этот флаг, если не использовать специальные методы загрузки данных.

Наша основная задача — перехватить процесс записи в тот момент, когда флаг Модифицированность еще доступен, и отменить действие, если изменений нет.

Решение 1: Обработка события в модуле формы

Самый простой и быстрый способ — прописать логику непосредственно в модуле формы объекта (справочника или документа). Мы воспользуемся клиентским событием ПередЗаписью. Рассмотрим пример кода:


&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    
    // Проверяем, менял ли пользователь что-то в форме
    Если Не ЭтаФорма.Модифицированность Тогда
        
        // Отменяем стандартный процесс записи
        Отказ = Истина;
        
        // Если пользователь нажал "Записать и закрыть", просто закрываем форму
        Закрыть();
        
    КонецЕсли;    
    
КонецПроцедуры

Разберем, что здесь происходит. Параметр Отказ = Истина сообщает платформе, что запись производить не нужно. Вызов Закрыть() необходим для того, чтобы форма не осталась висеть перед пользователем после нажатия кнопки. Однако у этого метода есть нюанс: если пользователь нажмет просто «Записать» (без закрытия), форма всё равно закроется. Чтобы этого избежать, можно анализировать ПараметрыЗаписи, но в простейших случаях достаточно и такой логики.

Решение 2: Использование подписки на события (Глобальный подход)

Если нам нужно реализовать это поведение сразу для множества объектов (например, для всех справочников в конфигурации), редактировать каждую форму вручную нецелесообразно. В этом случае мы применим Подписку на событие ПередЗаписью.

Рассмотрим алгоритм действий:

  1. Создадим новый общий модуль (например, РаботаСФормамиСервер).
  2. Создадим подписку на событие ПередЗаписью для нужных типов объектов.
  3. В обработчике сравним текущее состояние объекта с данными, хранящимися в базе.

Пример кода для серверного обработчика:


Процедура ПроверитьИзмененияПередЗаписью(Источник, Отказ) Экспорт
    
    // Если это новый объект, его обязательно нужно записать
    Если Источник.ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем текущие данные из базы данных по ссылке
    СсылкаНаОбъект = Источник.Ссылка;
    ОбъектВБазе = СсылкаНаОбъект.ПолучитьОбъект();
    
    // Сравниваем реквизиты (упрощенный пример)
    // В реальной задаче лучше использовать сравнение через ЗначениеЗаполнено или БСП
    Если Источник.Модифицирован() = Ложь Тогда
        // Если платформа считает, что объект не модифицирован на уровне сервера
        // Но подписка может срабатывать и при программной записи, будьте осторожны
    КонецЕсли;

КонецПроцедуры

Важное замечание: Метод Модифицирован() на сервере работает иначе, чем флаг в форме. Для надежности программисты часто сравнивают реквизиты объекта и его ссылки вручную или используют функции Библиотеки Стандартных Подсистем (БСП), такие как ОбщегоНазначения.ДанныеСовпадают().

Решение 3: Интерфейсные ограничения (UX)

Иногда лучше предотвратить проблему на уровне интерфейса, чем бороться с её последствиями в коде. Рассмотрим несколько стратегий:

  1. Режим «Только просмотр» по умолчанию: Выясним, почему пользователи заходят в карточку. Если чаще всего это происходит для чтения данных, мы можем открывать форму в режиме ТолькоПросмотр = Истина. Для редактирования добавим кнопку «Разрешить редактирование», как это сделано во многих типовых решениях 1С (ERP, УТ 11).
  2. Управление доступностью кнопок: Проанализируем состояние формы. Можно программно отключать кнопку «Записать», пока флаг Модифицированность равен Ложь. Это визуально подскажет пользователю, что записывать сейчас нечего.

Решение 4: Использование расширений

Если конфигурация типовая и находится на поддержке, оптимальным вариантом будет использование Расширения. Мы можем создать общую процедуру, которая будет подключаться к событию ПриСозданииНаСервере для всех форм объектов.

В этой процедуре мы можем программно установить обработчик ожидания или изменить поведение стандартных команд:


&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    // Устанавливаем свойство формы, чтобы она всегда спрашивала о сохранении
    // или блокируем кнопку записи, если не было изменений
    ЭтаФорма.ТолькоПросмотр = Истина; // Пример принудительного режима просмотра
КонецПроцедуры

Проблема связанных данных

Проанализируем ситуацию, когда данные хранятся не в самом объекте, а в регистрах (например, контактная информация или дополнительные сведения). В этом случае стандартная Модифицированность объекта может остаться Ложь, хотя данные на форме изменились.

Рекомендация: При использовании собственных форм для редактирования связанных данных всегда принудительно устанавливайте ЭтаФорма.Модифицированность = Истина; при изменении этих данных. Это гарантирует, что система отработает штатно и предложит сохранить изменения.

Резюме

Для решения задачи «пустых записей» наиболее эффективным является сочетание двух методов:

Выяснив причину, по которой пользователи совершают лишние действия, вы сможете выбрать наиболее подходящий инструмент — от простой вставки кода в одну форму до глобальной подписки на события для всей системы.

← На главную