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

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

В процессе разработки конфигураций часто возникает задача: ограничить совместную работу с одним и тем же документом. Необходимо реализовать стандартное поведение платформы: когда один пользователь открывает документ на редактирование, второй пользователь, пытающийся открыть этот же документ, должен увидеть сообщение "Не удалось начать редактирование" и получить форму в режиме "только просмотр". Давайте разберемся, как внедрить этот функционал в самописный документ.

Проанализируем стандартные механизмы платформы и рассмотрим альтернативные подходы.

Решение 1: Стандартный механизм платформы

Самый правильный и предпочтительный способ — использовать встроенные возможности платформы 1С. Для этого предназначен метод ЗаблокироватьДанныеФормыДляРедактирования(). Этот метод автоматически пытается установить управляемую блокировку на данные, связанные с основным реквизитом формы.

Принцип работы очень прост:

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

Чтобы все работало корректно, важно разместить вызов этого метода в правильном обработчике событий. Наиболее подходящим местом является обработчик ПриЧтенииНаСервере. Он срабатывает каждый раз, когда форма открывается для уже существующего, записанного в базу данных объекта.

Посмотрим на пример реализации:


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

Этот код является самодостаточным и в большинстве случаев полностью решает поставленную задачу. Блок Попытка...Исключение обеспечивает корректную обработку ситуации, когда блокировку установить не удалось.

Что делать, если стандартный метод не работает?

Иногда, как в ситуации на форуме, вызов ЗаблокироватьДанныеФормыДляРедактирования() отрабатывает без ошибок у обоих пользователей, и никакой блокировки не происходит. Это значит, что что-то мешает платформе корректно определить объект для блокировки. Выясним основные причины.

1. Не указан или неверно указан основной реквизит формы.

Это самая частая причина. Механизм автоматической блокировки тесно связан с основным реквизитом формы (обычно это реквизит типа ДокументОбъект.<ИмяДокумента>). Если он не задан, платформа просто не знает, какие данные нужно блокировать. Для анализа и настройки свойств открытых форм можно использовать инструмент для редактирования свойств форм в режиме предприятия.

Как проверить:

  1. Откройте форму документа в конфигураторе или используйте редактор форм в режиме предприятия для анализа свойств "на лету" — для этого есть редактор форм и свойств объектов 1С.
  2. В дереве элементов формы выберите корневой элемент ("Форма").
  3. В палитре свойств найдите свойство "Основной реквизит".
  4. Убедитесь, что в этом свойстве выбран ваш реквизит-объект (например, "Объект" или "Документ").

2. Особенности работы в расширениях конфигурации.

Если ваш документ находится в расширении, иногда могут возникать нюансы с наследованием свойств и поведением форм. Чтобы избежать ошибок, можно реализовать программное изменение форм для корректной настройки интерфейса в расширении. Для решения этой задачи подойдёт модуль для программного изменения элементов форм и команд.

3. Неверное использование методов блокировки.

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

Решение 2: Ручное управление блокировкой

Если стандартный механизм не сработал, а причина не найдена, можно прибегнуть к более "ручному" способу управления блокировкой. Для этого используется тот же метод, но с параметрами: ЗаблокироватьДанныеДляРедактирования(<Данные>, , <ИдентификаторБлокировки>).

В этом случае мы явно указываем, что блокировать (ссылку на наш документ) и кто является владельцем блокировки (наша форма, идентифицируемая по ее уникальному идентификатору).

Разберем по шагам реализацию этого подхода.

Шаг 1. В обработчике ПриОткрытии() на клиенте добавим вызов серверной функции, которая будет пытаться установить блокировку.

Шаг 2. Создадим серверную функцию, которая будет выполнять саму блокировку и возвращать результат (успех/неудача).

Посмотрим на готовый пример кода:


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


&НаСервере
Функция УстановитьБлокировкуОбъекта(СсылкаНаОбъект, УИДФормы)

    Результат = Истина;
    Попытка
        // Явно указываем, что блокируем данные по Ссылке, 
        // а владельцем блокировки является форма с ее УИД.
        ЗаблокироватьДанныеДляРедактирования(СсылкаНаОбъект, , УИДФормы);
    Исключение	
        // В этом случае платформа не выводит сообщение автоматически,
        // поэтому мы должны сделать это сами.
        ОшИнфо = ИнформацияОб Ошибке();
        ТекстОшибки = ОшИнфо.Описание;
        
        Сообщить("Объект заблокирован для редактирования! (" + ТекстОшибки + "). Документ открыт в режиме просмотра.");
        
        Результат = Ложь;
    КонецПопытки;
    
    Возврат Результат;
    
КонецФункции

Ключевые отличия этого подхода:

В заключение, всегда начинайте с простого и стандартного решения. В 99% случаев вызов ЗаблокироватьДанныеФормыДляРедактирования() в обработчике ПриЧтенииНаСервере — это все, что вам нужно. Если же вы столкнулись с проблемой, в первую очередь проверьте основной реквизит формы. И только как крайнюю меру используйте ручное управление блокировкой.

← На главную