1с как узнать кто заблокировал объект
Мы ВКонтакте
JS: 2.14.23
CSS: 4.9.13
jQuery: 3.6.0
DataForLocalStorage: 2022-05-10 03:46:02-standard
jQuery
jQuery UI
Bootstrap
Font Awesome
[неизвестный]
[неизвестная рассылка]
Здравствуйте!
1С 7.7
Как программно узнать кто заблокировал документ, т.е. кто его открыл?
Возможно ли это?
Здравствуйте, Munster!
Голосую за то что это невозможно. Я точно о таком не знаю. Но я могу ошибаться.
Ноговицин Роман Викторович
Посетитель
17.04.2007, 15:21
Здравствуйте, Munster!
Стандартно - никак. Но можно добавить общий реквизит и при открытии записывать в него кто открыл и при не обходимости можно будет это узнать.
Андрей Тимофеев
Посетитель
17.04.2007, 15:44
А. Можно использовать 1С в режиме "Монитор".
Б. Если его возможности Вам не подходят, предлагаю поступить следующим образом (первое, что пришло на ум, возможны вариации):
1. Создаем справочник "ДействияПользователей", длина кода - 0, длина наименования - 100, с реквизитами:
- Пользователь (тип "Строка" или "Справочник.Пользователи", добавьте также признак "Сортировка") – фиксирование имени пользователя
- ОбъектДокумент (тип "Документ", добавьте также признак "Сортировка") – фиксирование документа как объекта (может пригодится?)
- Действие (тип "Строка" или "Число" - в зависимости от того, как Вы хотите сигнализировать о действиях - словами или иконками) – фиксирование действия
- Идентификатор (тип "Строка", добавьте также признак "Сортировка") – уникальный идентификатор, на случай если документ новый (позиционирование на нем невозможно и реквизит "ОбъектДокумент" будет не заполнен)
2. В модуль формы документа добавляем строку - Перем ТекИдентификатор;
3. В модуль формы документа в предопределенную процедуру ПриОткрытии() добавляем несколько строк кода:
ТекИдентификатор=_getPerformanceCounter(); // недокументированная возможность 1С, возвращает число миллисекунд прошедших с момента включения компьютера
Спр=СоздатьОбъект("Справочник.ДействияПользователей");
Спр.Новый();
Спр.Наименование="Документ "+Вид();
Спр. Идентификатор=ТекИдентификатор; // по этому реквизиту будем фиксировать некое случайное число, пригодится для удаления элемента справочника при закрытии формы документа
Если Выбран()=0 Тогда
Спр.Пользователь=ИмяПользователя(); // на случай, если в этом реквизите используете "Справочник.Пользователи" - подставляйте глПользователь
Спр.Действие="Ввод нового"; // на случай, если в этом реквизите используете "Число" - подставляйте, например, 0
Иначе
Спр.Пользователь=ИмяПользователя(); // на случай, если в этом реквизите используете "Справочник.Пользователи" - подставляйте глПользователь
Спр.ОбъектДокумент=ТекущийДокумент();
Если Форма.ТолькоПросмотр()=1 Тогда
Спр.Действие="Просмотр"; // на случай, если в этом реквизите используете "Число" - подставляйте, например, 1
Иначе
Спр.Действие="Изменение"; // на случай, если в этом реквизите используете "Число" - подставляйте, например, 2
КонецЕсли;
КонецЕсли;
Спр.Записать();
Спр="";
4. В модуль формы документа в предопределенную процедуру ПриЗакрытии() добавляем несколько строк кода:
Спр=СоздатьОбъект("Справочник.ДействияПользователей");
Если Спр.ВыбратьЭлементыПоРеквизиту("Идентификатор",ТекИдентификатор,0,0)>0 Тогда
Пока Спр.ПолучитьЭлемент()>0 Цикл
Если Спр.Пользователь=ИмяПользователя() Тогда
Спр.Удалить(1); // удаляем элемент справочника напрочь, но только в случае совпадения имени пользователя и уникального идентификатора
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
В результате, открыв форму списка справочника "ДействияПользователей" видим кто чем в настоящий момент занимается (с сортировкой по документам, пользователям)…
Аналогичным образом можно добавить обработку по справочникам, отчетам, константам…
Вполне возможно, что я изобретал велосипед, и решение данной задачи уже было придумано кем-то до меня и проще, но. я такого не нашел, хотя признаюсь: дальше первой страницы Google не заглядывал. Итак. Есть, конечно, еще вариант создавать регистр сведений, где будет храниться информация о блокировках, но я решил не создавать подобного, а пойти через журнал регистрации 1С.
В обработчик формы ПриОткрытии() поместим следующий код
Если ЭтоНовый() тогда
//обработчик для нового элементы
Ответ = Вопрос("Документ находится на редактировании другим пользователем"
+ ?(Блокировщик.Пустая(), "." + Символы.ПС, ":" + Символы.ПС + Блокировщик.Наименование + ", тел. " + Блокировщик.Телефон)
+ Символы.ПС + "Открыть в режиме чтения?", РежимДиалогаВопрос.ДаНетОтмена);
Если Ответ = КодВозвратаДиалога.Да тогда
ИначеЕсли Ответ = КодВозвратаДиалога.Нет тогда
ИначеЕсли Ответ = КодВозвратаДиалога.Отмена тогда
Также в модуле формы помещаем такую функцию
ЖурналРегистрации = Новый ТаблицаЗначений;
Фильтр = Новый Структура;
Фильтр.Вставить("Данные", Ссылка);
ВыгрузитьЖурналРегистрации(ЖурналРегистрации, Фильтр, "Пользователь",,1);
ПолноеИмяПользователя = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(ЖурналРегистрации[0].Пользователь).ПолноеИмя;
Возврат Справочники.Пользователи.НайтиПоНаименованию(ПолноеИмяПользователя, Истина);
Для работы в таком виде без изменений, у Вас в конфигурации должен быть справочник пользователи, куда в реквизит Наименование будет писаться полное имя ползователя ИБ и добавить реквизит Телефон в тотже справочник, тогда пользователю будет отображаться ФИО заблокировавшего и телефон по которому он может перезвонить.
Теперь, собственно о работе данного кода.
Теперь, если документ заблокировать не получилось, то происходит определение автора блокировки соответствующей процедурой. По фильтру на текущие данные мы выгружаем последнюю запись с пользователем (отбор по журналу в таком случае происходит быстро даже на машине пользователя) - из журнала регистрации выгружается УИД, после чего по полному имени пользователя ИБ находим соответствие в справочники пользователи и сообщаем его имя и телефон страждущему доступа к документу.
Вопрос подразумевает три ответа: "Нет" - закрытие формы, "Да" - открытие в режиме чтение, "Отмена" - с тем чтобы пройти процедуру в надежде, что блокировка снята. Или позвонить уже использующему объект и попросить его закрыть и по кнопке "Отмена" открыть его уже в режиме для изменения. К сожалению, стандартные диалоги в 1С не подразумевают варианта "ДаНетПовторить".
При этом, выяснить, какой же пользователь держит объект открытым, довольно проблематично. Приходится открывать журнал регистрации, долго и нудно искать нужный объект и по событиям журнала пытаться определить, кто же все же открыл данный объект.
Для её реализации требуется загрузка внешних компонент:
для DBF версии еще и
Идея очень простая - при начале работы системы проверяется наличие таблички в базе (в SQL - табличка на сервере SQL, для DBF - база sqlite и таблички в ней), в предопределенных событиях формекса пишется имя пользователя и ид-объекта в табличку блокировок, при обработке блокировки - показывается этот пользователь.
Метода не новая, просто мало кто выкладывал готовых решений.
Для реализации, нижеследующий код нужно поместить в глобальный модуль.
ЗЫ: для любителей "универсальности", предлагаю объединить оба метода в один самостоятельно.
ЗЫЫ: в монопольном режиме, база блокировок не нужна , как и их обработка в нижеописаных процедурах. Для этого
в ПриНачалеРаботыСистемы нужна всего лишь проверка на
Если МонопольныйРежим ()= 0 Тогда
//тут создать объекты запроса/базы /табличек и прочий мусор
ТекстГм = " сюда пишем текст процедур ПриНачалеБлокировкиОбъекта и ОбработкаБлокирокиОбъекта";
гСервис= СоздатьОбъект ("Сервис");
гСервис.ДобавитьГлобальныйМодуль(ТекстГМ);
КонецЕсли ;
ЗЫЫЫ: принимаю пожертвования в качесте благодарности на
яндекс деньги 41001277400750
wmr R285258832971
Версия для DBF-варианта:
Перем запросSQLLite ;
Перем глМД ;
//======================================================================
Процедура ПриНачалеБлокировкиОбъекта ( Объект )
Тип = ТипЗначенияСтр( Объект );
Если ( Тип = "Документ" )или( Тип = "Справочник" ) Тогда
ИДОбъекта = глМД . ЗначениеВДлиннуюСтрокуБД ( Объект );
ТекстЗапроса = "
| INSERT or REPLACE INTO БазаБлокировок
| VALUES ('" + ИДОбъекта + "','" +ПолноеИмяПользователя()+ "')
|-- для типовой торговли можно пользовать глПользователь:
|-- VALUES ('" + ИДОбъекта + "','" + глПользователь . Наименование + "')
|" ;
фл = 0 ;
Пока фл = 0 Цикл
Попытка
запросSQLLite . ВыполнитьЗапрос ( ТекстЗапроса );
фл = 1 ;
Исключение
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
//======================================================================
Процедура ОбработкаБлокировкиОбъекта ( Объект , Повторить , ДопТекст )
Тип = ТипЗначенияСтр( Объект );
Если ( Тип = "Документ" )или( Тип = "Справочник" )Тогда
ИДОбъекта = глМД . ЗначениеВДлиннуюСтрокуБД ( Объект );
фл = 0 ;
Пока фл = 0 Цикл
Попытка
ИмяВредителя = запросSQLLite . ВыполнитьЗапрос ( "Select База.Пользователь From БазаБлокировок База Where База.ИДОбъекта = '" + ИДОбъекта + "'" , 0 );
фл = 1 ;
Исключение
КонецПопытки;
КонецЦикла;
Сообщить( "" + Объект + " открыт пользователем " + ИмяВредителя , "!" );
//для красоты, можно писать так, заместо Сообщить:
ДопТекст = "" + Объект + " открыт пользователем " + ИмяВредителя ;
КонецЕсли;
КонецПроцедуры
//======================================================================
Процедура ПриНачалеРаботыСистемы ()
ЗагрузитьВнешнююКомпоненту( "1cpp.dll" );
ЗагрузитьВнешнююКомпоненту( "formex.dll" );
ЗагрузитьВнешнююКомпоненту( "1sqlite.dll" );
база = СоздатьОбъект( "SQLiteBase" );
Если ФС. СуществуетФайл ( КаталогИБ ()+ "ExtForms\" )= 0 Тогда
ФС. СоздатьКаталог ( КаталогИБ ()+ "ExtForms\" );
КонецЕсли;
Если ФС. СуществуетФайл ( КаталогИБ ()+ "ExtForms\DB_SQLite\" )= 0 Тогда
ФС. СоздатьКаталог ( КаталогИБ ()+ "ExtForms\DB_SQLite\" );
КонецЕсли;
ИмяБД = КаталогИБ()+ "ExtForms\DB_SQLite\baza.db3" ;
глМД = СоздатьОбъект( "MetaDataWork" );
база . Открыть ( ИмяБД );
запросSQLLite = база . НовыйЗапрос ();
//запросSQLLite.ВыполнитьЗапрос("PRAGMA journal_mode=WAL" ); //это прописать, ежели база в терминале
запросSQLLite . ВыполнитьЗапрос ( "PRAGMA journal_mode=OFF" );
ТекстЗапроса = "
|Create table if not EXISTS
|БазаБлокировок (
| ИДОбъекта varchar(13) primary key not null,
| Пользователь TEXT
|)" ;
фл = 0 ;
Пока фл = 0 Цикл
Попытка
запросSQLLite . ВыполнитьЗапрос ( ТекстЗапроса );
фл = 1 ;
Исключение
КонецПопытки;
КонецЦикла;
Если МонопольныйРежим()= 1 Тогда
запросSQLLite . ВыполнитьЗапрос ( "delete from БазаБлокировок" );
КонецЕсли;
КонецПроцедуры
В данном примере речь идет об объектных блокировках, которые могут быть установлены автоматически расширениями форм объектов либо программно с помощью метода Заблокировать().
Проверка в контексте объекта, через который и производилась сама блокировка, выполняется следующим образом:
Код 1C v 8.х
Следует отметить, что в случае если объект заблокирован через другую переменную (например, открытую форму объекта), то метод Заблокирован() вернет значение Ложь.
Блокировка данных объекта влияет только на возможность его блокировки, но не препятствует изменению данных в базе данных. Поэтому, прежде чем изменять данные объекта, следует убедиться, что эти данных не заблокированы. Для этого необходимо попытаться установить блокировку:
Код 1C v 8.х
Если попытка заблокировать объект была удачной, это означает, что объект ранее не был заблокирован.
Похожие FAQ
Еще в этой же категории
Полнотекстовый поиск в 1С (что это и пример использования) 23
Полнотекстовый поиск - позволит найти текстовую информацию, размещенную практически в любом месте используемой конфигурации. При этом искать нужные данные можно либо по всей конфигурации в целом, либо сузив область поиска до нескольких объектов Формат, функция форматирования значений 21
//Функция формирует удобное для чтения представление значений. // Примеры форматирования чисел ЗначФормат = Формат(123456.789, " ЧЦ=10; ЧДЦ=2" ); // ЗначФормат = " 123 456,79" ЗначФормат = Формат(123456.789, " ЧГ=0; ЧДЦ=2" ); // Знач Обработчики событий при записи объектов. Зачем и что за чем? 12
Программисту, имеющего немного опыта на платформе 1С 8.2, бывает сложно разобраться: ПередЗаписью, ПриЗаписи, ПослеЗаписи, на сервере, на клиенте, в модуле формы, в модуле объекта, а-а-а-а-аааа. Именно такое сложное чувство непонимания УстановитьСсылкуНового 11
Установить ссылку нового это специальный механизм программиста, который позволяет присваивать новому объекту нужную ссылку. В основном это задача обмена, во многих типовых обменах используется синхронизация по UID объекта. Рассмотрим этот метод на к МоментВремени, получение остатков до и после проведения 9
" Момент времени" - виртуальное поле, не хранится в базе данных. Содержит объект МоментВремени (который включает в себя дату и ССЫЛКУ НА ДОКУМЕНТ) В 7.7 было понятие ПозицияДокумента, а в 8.x Момент времени Для получения Остатков, Движений: М Посмотреть все в категории Встроенные Функции
Помощник программирования в 1С запись закреплена
ЗаблокироватьДанныеФормыДляРедактирования или проверяем программно открыт ли документ
Иногда бывает случаи, когда нужно узнать кто открыл нужный документ. Стандартно платформа 1С, предупреждает нас что объект заблокирован, если мы начинаем редактировать этот документ.
Согласитесь, не очень удобно, постоянно смотреть активных и искать нужный сеанс.
Для того, чтобы при открытии проверять кто сидит в документе, будем использовать стандартную функцию управляемой формы ЗаблокироватьДанныеФормыДляРедактирования().
Ниже приведен текст модуля формы, где при открытии будем блокировать данные формы для дальнейшего редактирования, т.е. кто первый открыл, тот и будет редактировать документ.
&НаКлиенте
Процедура ПроверкаНаОткрытиеДокументаДругимПользователем() Экспорт
Попытка
ЭтаФорма.ЗаблокироватьДанныеФормыДляРедактирования();
Исключение
Ошибка = ОписаниеОшибки();
Ошибка = Сред(Ошибка, Найти(Ошибка, "сеанс:") + 7, СтрДлина(Ошибка));
Ошибка = Сред(Ошибка, 1, Найти(Ошибка, ",") - 1);
ПользовательСеанса = ПолучитьПользователяСеансаИнформационнойБазы(Число(Ошибка));
ТекстВопроса = "Документ уже открыт " + ?(ПользовательСеанса = "", "другим", "") + "пользователем " + ПользовательСеанса + ". Открыть для просмотра?";
Если Вопрос(ТекстВопроса , РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Нет Тогда
Отказ = Истина;
Иначе
ЭтаФорма.ТолькоПросмотр = Истина;
КонецЕсли;
КонецПопытки;
&НаСервере
Функция ПолучитьПользователяСеансаИнформационнойБазы(Сеанс) Экспорт
СеансыИнформационнойБазы = ПолучитьСеансыИнформационнойБазы();
Для Каждого СеансИБ Из СеансыИнформационнойБазы Цикл
Если СеансИБ.НомерСеанса = Сеанс Тогда
Попытка
Возв.
Читайте также: