Как определить, кем открыта форма документа в 1С при загрузке данных?

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

Проанализируем ситуацию, с которой часто сталкиваются разработчики при интеграции базов 1С с внешними системами. Допустим, в фоновом режиме загружаются данные из другой системы, обновляя существующие документы. При этом какой-либо пользователь может в этот самый момент открыть данный документ на редактирование. Возникает логичная задача: как определить, кем именно открыта форма, чтобы послать ему оповещение через систему взаимодействия или запретить загрузку? Разберем по шагам, почему стандартные методы не всегда срабатывают и какие существуют пути решения.

Почему стандартная блокировка не срабатывает при простом открытии

Рассмотрим подробнее поведение платформы 1С при работе с формами. Зачастую разработчики пытаются использовать метод ЗаблокироватьДанныеДляРедактирования или метод объекта Заблокировать, ожидая, что если пользователь просто открыл форму, система выдаст отказ в доступе. Однако на практике при загрузке мы получаем сообщение, что объект не заблокирован.

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

Если же пользователь начал вносить изменения, мы можем перехватить этот момент. Посмотрим на пример реализации.

Метод 1: Парсинг текста ошибки (перехват пессимистической блокировки)

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

Для этого мы можем использовать конструкцию Попытка-Исключение и встроенную функцию ОписаниеОшибки. Напишем следующий код:


ТекстОшибки = "";
Попытка
    ДокументОбъект.Заблокировать();
Исключение
    ТекстОшибки = ОписаниеОшибки();
КонецПопытки;

Если объект действительно заблокирован другим сеансом, переменная ТекстОшибки будет содержать стандартизированную строку платформы, которая выглядит примерно так: «Объект уже заблокирован: компьютер: [ИмяПК], пользователь: [ИмяПользователя], сеанс: [Номер]...».

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

Метод 2: Отслеживание просмотра документов через Регистр Сведений

Если бизнес-логика вашей задачи жестко требует знать, кто именно сейчас просто смотрит документ (даже если он не нажимал никаких кнопок и Модифицированность равна Ложь), стандартными методами платформы обойтись не получится. Создадим кастомный механизм отслеживания.

Разберем по шагам алгоритм создания такого механизма:

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

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

Метод 3: Использование API администрирования кластера серверов

Если ваша информационная база работает в клиент-серверном варианте, мы можем пойти более "цивилизованным" путем и получить данные о блокировках напрямую от сервера 1С, избегая парсинга текста.

Для реализации этого метода используется COM-соединение с агентом сервера через V83.COMConnector или утилиты администрирования RAS/RAC. В коде необходимо подключиться к объекту кластера, запросить текущие соединения и вызвать метод получения блокировок. Платформа вернет готовый массив структур, где будут четко указаны заблокированные объекты и пользователи, удерживающие эти блокировки.

Однако учитывайте, что данный метод требует административных прав на кластер серверов 1С и отрабатывает достаточно медленно. Вызывать его при загрузке каждого документа в интенсивном потоке обмена не рекомендуется из-за высокой нагрузки на сервер.

Что будет, если пользователь решит сохранить открытый документ?

Иногда возникает резонный вопрос: что произойдет, если пользователь просто открыл документ и долго его изучает, а в это время наша фоновая загрузка успешно перезаписала данные этого документа? Не затрет ли пользователь новые данные, когда нажмет кнопку записи?

Ответим на этот вопрос: нет, не затрет. В платформу встроена автоматическая оптимистическая блокировка. Если фоновый обмен изменил данные, версия объекта в базе данных обновилась. Когда пользователь попытается нажать кнопку «Записать» или «Провести» в своей старой открытой форме, система проверит версии и выдаст штатную ошибку: «Данные были изменены другим пользователем». Таким образом, данные из сторонней системы останутся в сохранности, а пользователю придется переоткрыть форму, чтобы увидеть актуальную информацию.

Интерактивное взаимодействие с пользователями

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

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

← На главную