1с проверить открыта ли форма

Обновлено: 02.07.2024

Как при открытии формы определить, что создается новый элемент?

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

Основной смысл заключается в том, что все действия, которые разработчику требуется сделать при создании нового объекта, должны быть выполнены на сервере.

Причем действия с данными самого объекта и действия с внешним видом его формы должны быть разделены. Действия с данными нужно выполнять в самом объекте, а внешним видом формы нужно управлять уже в форме, но в серверной процедуре.

Кроме этого могут понадобиться и другие действия при открытии формы, например открыть связанную форму, выдать предупреждение и т.д., которые нельзя сделать на сервере – их нужно выполнять в форме, но уже в клиентской процедуре.

Последовательность событий, которые происходят при открытии формы нового элемента, можно представить следующей схемой:


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

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

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

  • при интерактивном создании нового объекта
  • при вводе на основании
  • при выполнении метода объекта Заполнить()

При этом параметр ДанныеЗаполнения , передаваемый в этот обработчик, может иметь различные значения в зависимости от того, каким образом создается новый элемент. Например, он может иметь тип ссылки, если новый объект вводится на основании. Или он может иметь тип Структура , если новый объект создается интерактивной командой из списка, в котором установлен отбор. В этом случае структура будет содержать значения элементов отбора этого списка. Также этот параметр может иметь тип Неопределено , если новый элемент создается интерактивной командой из панели действий. То есть в своем алгоритме начального заполнения полезно анализировать этот параметр.

Подробнее о событии ОбработкаЗаполнения можно прочитать в синтакс-помощнике: ПрикладныеОбъекты - <Вид объектов конфигурации (Справочники, Документы и т.п.)> - <Вид объектов конфигурации>Объект - События .

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

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Параметры.Ключ.Пустая() Тогда

Сообщить("Создается новый объект");

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

Открытие форм

Область применения: управляемое приложение, мобильное приложение.

1. Для открытия форм следует применять метод глобального контекста ОткрытьФорму (при использовании версии платформы 1С:Предприятие 8.2 и более ранних версий - также ОткрытьФормуМодально ). Применение альтернативного способа, с получением формы и ее последующим открытием с помощью метода ПолучитьФорму , не рекомендуется.

Рекомендация обусловлена соображениями

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

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

2. В случаях когда форма требует параметризации при открытии, все ее параметры следует указывать в наборе параметров формы. Таким образом, набор параметров формы декларативно описывает возможности формы по ее параметризации.

Параметры формы из этого набора могут быть указаны в вызывающем коде при открытии формы ( ОткрытьФорму ).

3. Не следует применять другие способы параметризации формы при открытии. Например, нужно избегать обращения к методам и свойствам формы после ее открытия.
Например, вместо

следует по той же причине использовать параметры формы:

ОткрытьФорму("ОбщаяФорма.ПутеводительПоСистеме", Новый Структура("РежимОткрытия", "Приветствие"));

4. Для получения результата работы формы, вместо непосредственного обращения к элементам и реквизитам формы

ФормаВопроса = ПолучитьФорму("ОбщаяФорма.ФормаВопроса");
ФормаВопроса.ОткрытьМодально();
Если ФормаВопроса.БольшеНеПоказыватьНапоминание Тогда
// …

следует использовать процедуры-обработчики оповещений, которые будут вызваны при завершении работы пользователя с формой:

Оповещение = Новый ОписаниеОповещения("БольшеНеПоказыватьНапоминаниеЗавершение", ЭтотОбъект);
ОткрытьФорму("ОбщаяФорма.ФормаВопроса". Оповещение, РежимОткрытияОкнаФормы.БлокироватьВеcьИнтерфейс);
.

&НаКлиенте
Процедура БольшеНеПоказыватьНапоминаниеЗавершение(БольшеНеПоказыватьНапоминание, Параметры) Экспорт

Если БольшеНеПоказыватьНапоминание = Неопределено Тогда
Возврат;
КонецЕсли;

Если БольшеНеПоказыватьНапоминание Тогда
// …

При этом возвращаемое значение формы формируется в коде модуля формы с помощью метода формы Закрыть .

5. Другие ограничения:

  • Обработчик события формы ПриОткрытии не должен содержать код по открытию какой-либо другой формы, так как это может привести к нарушению порядка отображения окон. В этом случае рекомендуется использовать обработчик ожидания на короткий интервал или открывать другие формы интерактивно, например, по нажатию на кнопку.
  • Не рекомендуется выполнять программное открытие и закрытие формы в одном обработчике. Такие действия должны быть разнесены по времени. Например, закрытие формы можно выполнять в обработчике ожидания.
  • При использовании в конфигурации Библиотека стандартных подсистем и разработке форм (рабочих мест), предназначенных только для внешних пользователей, следует явно блокировать открытие таких форм в сеансах "обычных" пользователей. Для этого следует устанавливать параметр Отказ при создании формы на сервере с помощью функции ЭтоСеансВнешнегоПользователя общего модуля Пользователи или ПользователиКлиент :

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Не ПользователиКлиентСервер.ЭтоСеансВнешнегоПользователя() Тогда
Отказ = Истина;
Возврат;
КонецЕсли;

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

6. Следующие виды форм должны быть всегда доступны пользователю в режиме 1С:Предприятия из меню "Все функции" вне зависимости от того, размещены ли соответствующие объекты в командном интерфейсе приложения или нет:

ФормаДМ.Открыта() - всегда ложь, независимо от того, что я устанавливаю ПолучитьФорму. Судя по отладчику, ключ уникальности записывается в форму, и владелец записывается, но получается, что всегда форма закрыта.

Пробовал в процедуре ПередОткрытие дать отказ:

Тоже самое. Ключ уникальности в форме есть, владелец есть. Но ЭтаФорма.Открыта() все-равно ложь.

Не пойму, что не так?

Откуда ФормаДМ.Открыта() будет равно Истина, когда вы только получаете форму, но не открываете. После выполнения ПолучитьФорму(), она будет находиться в оперативной памяти, но открыта не будет.

(4)
(3)В чем суть - Когда я провожу документ, открывается форма документа созданного на основании. Если я еще раз нажму проведение, то снова откроется форма документа созданного на основании. И так до бесконечности.

А мне нужно, если форма уже открыта, то новую не открывать. Получается так я не могу сделать?


Но, ФормаДМ.Открыта() - ложь.
Хотя через отладчик я вижу, что ФормаДМ.КлючУникальности = "Уникальность", как я и указывал. (7) иди кофе попей отдохни, тебе уже говорили про ФормаДМ
ты ее получаешь но не открываешь поэтому она не открыта
ключ уникальности у нее Уникальность - потому что ты в методе получить форму указывыаешь этот ключ

(8) Все верно. Получаю, но не открываю. После получения - открываю, с ключом уникальности.
Но при следующем проведении, все равно откроется новая форма. Хотя предыдущая форма уже открыта.

Т.е. ключ уникальности ничего не решает в этом случае. Действительно, сначала нужно записать документ, а после этого уже пользоваться ключом уникальности.

(11) по ссылке там написано ключ уникальности можно менять
при открытии у всех форм ставить известный ключ уникальности хоть ту же "Уникальность"
теоретически теперь ты если форма открыта получишь ее (5)Ставьте в параметрах для открываемой формы БлокироватоОкноВладельца. Или весь интерфейс. Тогда второй раз нажать не сможете физически :) Сначала надо записать документ, а потом проверять открыта форма или нет.

То есть в ДокументДМ.ПолучитьФорму в качестве владельца во втором параметре вы передаете еще не открытую форму ЭтотОбъект.ПолучитьФорму("ФормаДокумента")
Это вообще законно? :)

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

Пишу в обработке проведения
. ДокументДМ.ПолучитьФорму

Исходя из вышеизложенного возникает вопрос, а не троллинг ли вообще вся эта тема.

(10) Владелец формы указан, поскольку я вообще проверял повлияет он на что-то или нет. Так я ни одного параметра не передаю.

На счет обработки проведения - согласен.
Перенес в после записи.
Но в любом случае проблемы это не решает.

На сервере есть форма. Нужно проверить открыта она или нет.

Но как я понимаю, это можно сделать только на клиенте. И приходится добавлять реквизит формы "ФормаОткрыта" типа Булево и заполнять его в ПриОткрытии()

(3) И очищать в ПриЗакрытии, тогад уж. Закрытые формы тоже существуют.
Но скорей всего у тебя косяк в сценариях и архитектуре, если требуется такой знатный костыль.

Например, мой конкретный кейс.
Нужно отключать пользовательские настройки при открытии формы списка. Просто снимать галочки с пользовательских отборов. Но только при открытии. Далее, если пользователь подгрузит свои настройки, то их обрабатывать не нужно.

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

(4), к сожалению, в 1С мало доступно событий в отношении динамических списков.
(5) а при открытии самой формы разве нельзя привязаться к событию?
(7), при открытии формы настройки уже загружены. Мне нужно это делать до загрузки в событии ПередЗагрузкойПользовательскихНастроекНаСервере()
(7) вы не поняли видимо меня, или я вас. У вас есть форма, на ней динамический список. У списка есть какие то отборы пользовательские. Из вашего кейса вам нужно всегда, при открытии формы со списком очищать пользовательские настройки. Ну так привяжитесь к событию формы, а не к событию дин списка. При открытии очистили пользовательские отборы и ничего проверять не нужно.
(9) так же есть процедура при создании на сервере, она явно раньше отрабатывает и 1 раз при открытии.
(10) в этом то вся проблема, человек увидел решение через этот обработчик и начал все под него подстраивать (лепить велосипед), ладно хоть глобальный параметр не замутил для этой формы или какой нить виндовый комобъект для отслеживания открытых форм)

Во-первых, это не так оптимально.

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

В-третьих, если нужно отлавливать события в ПередЗагрузкойПользовательскихНастроекНаСервере() и часть действий выполнять при открытии, часть при нажатии кнопки, а часть и там и там, то легче уже использовать признак ФормаОткрыта

Читайте также: