1с причтениинасервере не работает
Многие начинающие разработчики игнорируют свойство команды объекта "Изменяет данные"то ли не замечают его, то ли не хотят разбираться с ним. Давайте выясним, каким образом данное свойство влияет на поведение команды и почему не стоит его игнорировать.
Создадим для справочника две команды, одна с установленным свойством "Изменяет данные", другая без (см. рисунок 1).
Рисунок 1. Команды объекта |
Команды выполняют одинаковое действие - запись случайного числа в реквизит СлучайноеЧисло элемента справочника.
В режиме 1С:Предприятие открываем форму списка и выделяем элемент списка. Если нажать на команду без установленного свойства, то никаких изменений в списке мы не увидим, хотя новое случайное число записано в реквизит. Если же нажать на команду с установленным свойством, то сразу увидим в списке новое случайное число. Открываем форму элемента и так же поочередно нажимаем на команды, поведение платформы будет аналогичным.
Установим для пользователя право только просмотра элементов справочника (см. рисунок 2).
Рисунок 2. Права на чтение и просмотр элементов справочника |
В режиме 1С:Предприятие в форме списка обе команды доступны, но, в форме элемента команда с установленным свойством не доступна (см. рисунок 3).
Рисунок 3. Доступность команд на формах при праве только просмотра |
Возвращаем пользователю право редактирования элементов справочника, а в форме списка и в форме элемента в обработчике ПриСозданииНаСервере установим свойство формы ТолькоПросмотр в значение Истина.
В режиме 1С:Предприятие в форме списка и в форме элемента команда с установленным свойством не доступна, а другая команда доступна (см. рисунок 4).
Рисунок 4. Доступность команд на формах, открытых только на просмотр |
Данное свойство необходимо устанавливать, если выполнение команды приводит к изменению данных объекта базы данных, например, выполняется заполнение на основании или рассчитывается значение реквизита.
Для команды с установленным свойством платформа:
- обновляет список в форме списка (срабатывает событие ПриПолученииДанныхНаСервере)
- перечитывает данные объекта в форме объекта (срабатывает событие ПриЧтенииНаСервере)
- делает команду не доступной при отсутствии права редактирования объекта
- делает команду не доступной в форме, открытой только на просмотр
Конечно, все выше перечисленное можно прописать в самой команде и проигнорировать свойство "Изменяет данные", но зачем усложнять команду, если можно установить свойство в значение Истина и платформа все выполнит сама?
Почему при наличии права только просмотра, команда с установленным свойством "Изменяет данные" в форме списка доступна, а в форме элемента нет? Не знаю, но есть решение. В обработчике ПриСозданииНаСервере в форме списка анализируем право доступа "Изменение", при отсутствии данного права у текущего пользователя делаем команду не доступной.
При открытии формы нового объекта (элемента справочника, документа) и при открытии формы существующего объекта возникает различная последовательность событий.
Форма нового объекта
Если открывается форма нового объекта, то сначала происходит начальное заполнение объекта данными (событие Обработка заполнения в модуле объекта, форма которого открывается), а затем вызываются два события формы: сначала на сервере (При создании на сервере) и затем на клиенте (При открытии). Эти два события позволяют подготовить форму к открытию (рис. 1).
Рис. 1. Последовательность событий при открытии формы нового объекта
№ | Модуль | Метод (процедура) |
1 | Модуль объекта (сервер) | Компиляция и код внизу модуля |
2 | Модуль объекта (сервер) | ОбработкаЗаполнения() |
3 | Модуль формы (сервер) | ПриСозданииНаСервере() |
4 | Модуль формы (клиент) | ПриОткрытии() |
Слева показан клиентский контекст, в котором вызываются события формы. Посередине и справа – серверный контекст, в котором вызываются как события формы, так и события самого прикладного объекта, форма которого открывается.
Форма существующего объекта
Если открывается форма существующего объекта, то последовательность событий будет иной (рис. 2). Сначала на сервере вызываются два события формы. Одно (При чтении на сервере) – чтобы подготовить дополнительные данные, которые зависят от данных объекта. Другое (При создании на сервере) – чтобы максимально подготовить форму к открытию. И наконец, на клиенте вызывается еще одно событие формы (При открытии), чтобы выполнить действия, связанные с открытием формы, которые на сервере выполнить невозможно.
Рис. 2. Последовательность событий при открытии формы существующего объекта
№ | Модуль | Метод (процедура) |
1 | Модуль объекта (сервер) | Компиляция и код внизу модуля |
2 | Модуль формы (сервер) | ПриЧтенииНаСервере() |
3 | Модуль формы (сервер) | ПриСозданииНаСервере() |
4 | Модуль формы (клиент) | ПриОткрытии() |
Из всех перечисленных событий нас прежде всего будут интересовать два события формы: При создании на сервере и При открытии.
Все, что можно сделать на сервере для подготовки формы к открытию, нужно делать в обработчике события При создании на сервере.
В обработчике события При открытии нужно делать только то, что на сервере сделать невозможно. Например, выдать предупреждение, задать вопрос. Или же выполнить те действия, которые выполняются именно тогда, когда форма наверняка открывается. Например, открыть связанную форму, которая «сама по себе» не существует, а существует, только если открыта родительская форма. Потому что обработчик При открытии – последний перед открытием формы, в котором можно отказаться от ее открытия. И если не происходит отказа от открытия родительской формы, то, значит, она наверняка будет открыта.
В этой статье мы покажем, как взаимодействуют клиентская и серверная части платформы и какие есть особенности в использовании директив компиляции.
Это будет полезно начинающим разработчикам и тем, у кого есть пробелы в области клиент-серверного взаимодействия – всё объясним «на пальцах» :)
Клиент-серверная архитектура заложена в платформе изначально – со времен «1С:Предприятие 8.0».
Однако при разработке на 8.0 и 8.1 о разделении кода на клиентскую и серверную часть можно было не заботиться, поскольку на клиенте (на толстом клиенте) был доступен тот же функционал, что и на сервере.
Всё изменилось с выходом платформы «1С:Предприятие 8.2», когда появился тонкий клиент. Теперь на клиенте доступен один функционал, на сервере – другой. Клиент и сервер «общаются» между собой с помощью серверного вызова.
Конечно, это усложнило процесс разработки, но с другой стороны – можно создавать более оптимальные (быстрые) решения, поскольку все сложные задачи выполняются на сервере.
Немного базовой теории
Перед тем, как перейти к содержательной части, договоримся о некоторых ограничениях:
- Мы подразумеваем, что Вы знаете о существовании четырёх директив компиляции, доступных в модулях формы: «&НаКлиенте», «&НаСервере», «&НаСервереБезКонтекста» и «&НаКлиентеНаСервереБезКонтекста».
- Все примеры будут опираться на работу «1С:Предприятие 8» в клиент-серверном режиме. Файловый вариант по сути является эмуляцией клиент-серверного режима, с небольшими отклонениями (для данной статьи это не критично)
- В рамках этого материала рассматривается исключительно взаимодействие клиента и сервера 1С. Работа с базой данных, преобразование данных и прочие нюансы работы системы – это темы других статей.
Далее, освежим в памяти немного теории.
Директивы, в имени которых упоминается «Клиент», устанавливают ограничение на обращение к базе данных.
Процедуры или функции, написанные под директивой «Без контекста», не имеют доступа к контексту (данным) формы. Исходя из этой информации, легко представить ограничения директив по доступу к данным в виде следующей таблицы:
Опережая вопрос «Для чего же директива с самым длинным названием, если она ограничивает и использование контекста форм, и обращения к базе данных?», напомню: любая процедура и функция поддерживает обработку информации, переданной в неё в качестве параметров.
Отсюда делаем вывод: у методов, описанных под директивой «&НаКлиентеНаСервереБезКонтекста», единственным источником данных являются эти самые переданные параметры.
Не стоит забывать и про доступность вызова одних процедур и функций из других. Для этого стоит запомнить, что можно вызывать только те процедуры и функции, которые находятся под одноимённой (с родительским методом) директивой или под директивой, находящейся ниже (чем у родительского метода) согласно списку:
- &НаКлиенте
- &НаСервере
- &НаСервереБезКонтекста
- &НаКлиентеНаСервереБезКонтекста.
То есть из метода, описанного под директивой «&НаКлиенте», можно вызывать процедуры и функции, описанные под любой директивой. А вот «из-под» директивы «&НаСервереБезКонтекста» можно вызывать только то, что описано под директивой «&НаСервереБезКонтекста» или «&НаКлиентеНаСервереБезКонтекста».
Теперь про серверный вызов
Серверный вызов – это передача какой-то информации с клиентской части «1С:Предприятие 8» на серверную часть с целью вернуть обратно некий набор данных.
Самый первый серверный вызов инициализируется в момент начала сеанса работы 1С. То есть когда пользователь выполняет вход в информационную базу:
«Оу! При чём тут Библиотека?!» – спросите Вы.
Всё очень просто:
Обратите внимание, что доступ к базе данных есть только на серверной части, а соединение между клиентом и сервером имеет ограниченную пропускную способность. Это и неудивительно – ведь соединение между клиентской и серверной частью может быть установлено даже по нестабильному низкоскоростному каналу связи (например, посредством мобильного интернета).
Кроме этого, передача данных между клиентом и сервером возможна только посредством серверного вызова.
Но, для того чтобы перейти к основной теме данной статьи, необходимо сначала разобраться – где будет выполняться программный код, написанный под определенными директивами. То есть на какой части приложения «1С:Предприятие 8» будут доступны процедуры и функции, описанные под директивами «&НаКлиенте», «&НаСервере», «&НаСервереБезКонтекста» и «&НаКлиентеНаСервереБезКонтекста»:
Видим, что на стороне клиента у нас будут доступны процедуры и функции, написанные под двумя директивами из четырёх, а на стороне сервера – под тремя из четырёх.
Сразу возникают вопросы: «Зачем такое многообразие и чем оно полезно?», «Как метод, описанный под директивой «&НаКлиентеНаСервереБезКонтекста» может выполняться и на клиенте, и на сервере?».
Сейчас мы постараемся понять особенности работы системы при использовании директив и почему необходимо уметь правильно использовать каждую из существующих директив компиляции.
И в этом нам помогут наши новые друзья, знакомьтесь!
Это процесс клиентской части приложения «1С:Предприятие 8». Он запускается на компьютере пользователя и сожительствует в оперативной памяти с другими процессами (38 вкладок браузера, поток аудио из социальной сети, telegram и другие). Может порождать серверный вызов.
Это процесс серверной части приложения «1С:Предприятие 8». Он существует на сервере 1С. Знает, какие клиентские сеансы в данный момент запущены, но самостоятельно не может инициировать взаимодействие с ними. Работает с клиентской частью только через полученный от неё серверный вызов.
А это серверный вызов. Как было сказано выше, он порождается процессом клиентской части и призван «прислуживать» ему. Он передает запросы со стороны клиента на сторону сервера, а также занимается транспортировкой данных с клиента на сервер и обратно.
Итак, давайте рассмотрим несколько особенностей работы программного кода в «1С:Предприятие 8», написанного под разными директивами.
Действие 1. Открытие пользователем формы с данными.
В момент нажатия Пользователем кнопки открытия формы из интерфейса, происходит передача управления на Сервер. По переданным параметрам получаются необходимые для построения данные из БД и происходит формирование контекста формы, который затем отправляется на клиентскую часть. У пользователя на экране отображается запрошенная форма.
Действие 2. Получение из открытой Пользователем формы дополнительных данных из Базы данных.
Получение этих данных может быть описано под двумя директивами – «&НаСервере» и «&НаСервереБезКонтекста». Рассмотрим оба случая.
Явление 1. Директива «&НаСервере»
При вызове процедуры или функции под директивой «&НаСервере» из формы со стороны клиента происходит «упаковка» всего контекста формы и отправка его на сторону сервера.
После выполнения метода на сервере, весь этот «пакет» транспортируется обратно. Таким образом, форма со всеми элементами и данными дважды проходит через самое узкое место системы.
Явление 2. Директива «&НаСервереБезКонтекста»
При вызове процедуры или функции под директивой «&НаСервереБезКонтекста» из формы со стороны клиента происходит передача на сторону сервера только тех данных, которые были указаны в качестве параметров. Обратно же передаётся только необходимая информация в уже подготовленном виде.
Таким образом, серверный вызов не несёт лишней нагрузки, и для передачи данных между клиентом и сервером потребуется меньше ресурсов.
Из примеров видно, что далеко не всегда оправдано указание директивы компиляции «&НаСервере» с точки зрения использования контекста (данных) формы на сервере.
Если возможно решить возникшую задачу путём отправки на сервер только определённого набора данных, то надо эту возможность использовать и описывать метод под директивой «&НаСервереБезКонтекста». Это позволит уменьшить нагрузку на серверный вызов, а также не занимать сервер обработкой и хранением ненужной в текущий момент информации.
Кстати, именно поэтому до версии платформы 8.3.7.1759 на сложных формах для управления видимостью элементов рекомендовалось использовать панели со страницами, а не свойство «Видимость». Только начиная с этого релиза отработка изменения видимости элементов стала выполняться на стороне клиента.
До этого момента при каждом изменении свойства «Видимость» происходил серверный вызов, как при использовании директивы «&НаСервере».
Но использование директивы «&НаСервереБезКонтекста» не является панацеей. Помимо нагрузки на серверный вызов, всегда необходимо задумываться ещё над одним параметром.
Действие 3. Обработка данных табличной части формы с получением дополнительной информации из Базы данных.
Явление 1. Построчная обработка табличной части на стороне клиента с организацией серверного вызова для получения дополнительной информации из базы данных.
Мы уже знаем – лучше использовать директиву «&НаСервереБезКонтекста».
При таком построении программного кода происходит множественное обращение со стороны клиента на сервер – по количеству элементов цикла, запущенного на стороне клиента.
Явление 2. Предварительная обработка табличной части на стороне клиента с целью подготовки требуемых к обработке на сервере данных и «упаковки» их в набор параметров. Затем передача этого набора на сервер для получения дополнительной информации из базы данных.
Используем всё ту же директиву «&НаСервереБезКонтекста».
В данном случае количество серверных вызовов сведено к минимуму за счёт предварительной подготовки параметров.
Большое количество текущих серверных вызовов может свидетельствовать о неоптимальном программном коде.
Избегайте создания серверных вызовов внутри цикла. Подготовьте набор параметров и единожды выполните его передачу для обработки на сервер. Если предполагается сложная обработка большого количества данных формы – передайте её полностью на сервер (при помощи директивы «&НаСервере») и выполните все действия на стороне сервера.
Если цель серверного вызова, созданного внутри цикла – получить какую-либо информацию из базы данных, то данная операция включает в себя запрос в цикле. А это очень негативно влияет на производительность всей системы в целом.
С директивой «&НаСервереБезКонтекста» вроде бы разобрались. Она нужна для того, чтобы уменьшить объем информации, передаваемой в рамках одного серверного вызова. Дополнительно разобрались с количеством текущих серверных вызовов – необходимо стремиться к их минимизации.
Давайте теперь попробуем разобраться, для чего нужна директива «&НаКлиентеНаСервереБезКонтекста».
Действие 4. Выполнение обработки данных.
Когда предполагается выполнение одной и той же обработки данных из нескольких участков программного кода, разумно этот код поместить в самостоятельную процедуру или функцию. Остаётся только решить, под какой директивой её написать.
Та-дам!
Для копирования у нас есть ксерокс. Но куда его поставить? На сторону клиента или сервера? Под какой директивой его разместить?
Как было озвучено ранее – любая процедура и функция поддерживает обработку информации, переданной в неё в качестве параметров.
Давайте для начала попробуем разместить копировальный аппарат на стороне клиента. Для этого описываем процедуру или функцию «Ксерокс» под директивой «&НаКлиенте». Тогда процесс клиентской части в любой момент сможет без проблем обратиться к ней и все действия будут выполнены в соответствии с программным кодом.
Но что произойдёт, если потребность в копировании возникнет на стороне сервера? Например, для подготовки данных, передаваемых на сторону клиента, потребуется сделать копию? Напомню – процесс серверной части не имеет возможности самостоятельно инициировать клиентские вызовы.
Получается, что использовать директиву «&НаКлиенте» неправильно, а директиву «&НаСервере», как мы изучили ранее – нежелательно. Давайте посмотрим поведение системы при использовании директивы «&НаСервереБезКонтекста».
Вроде бы результат достигнут – и с сервера, и с клиента доступно копирование. Но для того, чтобы получить копию данных, используемых на клиенте, приходится делать серверный вызов. А это опять ведет к лишней нагрузке на соединение и временным затратам.
Избавиться от излишней передачи на сервер при сохранении возможности копирования на клиенте и на сервере можно при помощи директивы «&НаКлиентеНаСервереБезКонтекста».
Не углубляясь в детали, отметим, что метод, описанный под данной директивой управления, создаётся в двух копиях – и на стороне клиента, и на стороне сервера. Это позволяет выполнить необходимые действия там, где появилась потребность в них (клиент/сервер), без лишних серверных вызовов.
Конечно, вместо того чтобы выделять повторяющийся программный код, описывать его в отдельном методе под директивой «&НаКлиентеНаСервереБезКонтекста», можно поступить по-другому. Просто взять и написать один и тот же участок кода и в клиентской, и в серверной процедуре.
С точки зрения выполнения программы результат будет одинаков. Но объяснение «почему так не надо делать» – это уже совершенно другая тема…
Вместо заключения
В данной статье мы на наглядных примерах рассмотрели влияние различных директив компиляции на такое явление системы «1С:Предприятие 8», как серверный вызов. Как видно, основная причина для выбора правильной директивы – производительность транспортировки данных между клиентской и серверной частью.
Придерживайтесь при разработке следующих правил:
- По возможности не передавайте контекст формы на сторону сервера
- Минимизируйте количество текущих серверных вызовов
- Длительные и ресурсоёмкие задачи запускайте на выполнение на стороне сервера (при возможности – в фоновом режиме).
Учитывайте потребность в доступности тех или иных видов данных, обоснованность передачи управления и не стесняйтесь при необходимости дробить процедуры и функции. И будет Вашему серверному вызову всегда легко, а Вы от пользователей Вашей программы получите «молчаливую благодарность»!
Программист Иван при доработке 1С на своём предприятии сделал ошибку в выборе директивы компиляции. Из-за неё длительность одного из серверных вызовов была больше возможной на полсекунды.
Пользователей, применяющих этот функционал, – 25 человек, и каждый из них за рабочий день в среднем совершает 110 таких операций. Всего впустую за рабочий месяц потрачено 28875 секунд (21 рабочий день * 25 человек * 110 операций * 0,5 секунды) = 8,02 часов.
Иван, каково тебе осознавать, что за месяц ты задолжал своему предприятию целый рабочий день?
Об авторе
Автор статьи – Павел Ванин
PDF-версия статьи для участников группы ВКонтакте
Если Вы еще не вступили в нее – сделайте это сейчас, и в блоке ниже (на этой странице) появятся ссылки на скачивание материалов.
Если Вы уже участник группы – нужно просто повторно авторизоваться в ВКонтакте, чтобы скрипт Вас узнал. В случае проблем решение стандартное: очистить кэш браузера или подписаться через другой браузер.
Комментарии / обсуждение (158):
Всё предельно понятно, спасибо за статью!
Хотелось бы увидеть правильные практические примеры с директивой &НаКлиентеНаСервереБезКонтекста
Добрый день, Ruby!
Много примеров использования директив находится в типовых конфигурациях.
Например, в 1С:УНФ есть вот такая функция под директивой «&НаКлиентеНаСервереБезКонтекста»:
&НаКлиентеНаСервереБезКонтекста
Функция ПолучитьЗаголовокНастроек(ТекущийРежим, НовыйЗаголовок)
Результат = “Настройки”;
Если НЕ ТекущийРежим Тогда
Результат = НовыйЗаголовок;
КонецЕсли;
C какой радости “Отсюда делаем вывод: у методов, описанных под директивой «&НаКлиентеНаСервереБезКонтекста», единственным источником данных являются эти самые переданные параметры.” ? С этой директивой можно сделать с базой все что угодно, если код реально будет выполняться в серверном контексте или в толстом клиенте. В тонком просто синтаксический контроль может не пройти. И что за 5 лет никто этого не заметил? Табличка выше этой цитаты тоже вдохновляет. База недоступна. Дальше читать не стал.
Добрый день, . Хочется вам сказать “Браво!” и поаплодировать! (сарказм)
Вы правы – технологических ограничений на доступ к базе данных при серверном исполнении процедуры или функции под директивой «&НаКлиентеНаСервереБезКонтекста» нет. Можно ли считать этот факт опровержением всей статьи? Я считаю – нет, и давайте поясню почему.
В сути данной директивы заложена возможность исполнения одного и того-же кода как на стороне клиента, так и на стороне сервера. И если мы в ней напишем, например, запрос к базе данных, то при компиляции формы возникнет ошибка. Так как со стороны клиентского экземпляра программного модуля формы доступа к базе данных нет.
Про директиву «&НаКлиентеНаСервереБезКонтекста».
Ваши оговорки про толстый клиент и возможность выполнения запроса к базе данных на сервере (игнорируя ошибки, возникающие при компиляции формы) ничто иное, как исключения из правил. Это все равно, что пассатижами гвозди заколачивать – в принципе возможно, но молотком удобнее.
Примеры про доступ к Access и COM-объектам тоже больше похожи на частный случай. Напомню – в ограничениях статьи (которые вы должны были по-идее прочитать, так как они выше описания директив приведены) указано, что рассматривается клиент-серверный вариант работы системы. А это означает, что доступность ресурсов (файлы, объекты, оборудование, …) со стороны клиента и со стороны сервера может иметь существенные отличия.
P.S.
Давайте поясню причину агрессии в своем предыдущем комментарии. Вы не удосужились прочитать статью, но повесили на нее ярлык «плохой контент». В наше время часто перед тем как читать длинный текст, люди пробегаются по комментариям – понять, стоит ли тратить свое время на материал. Увидев ваш комментарий, кто-то может засомневаться в пользе статьи и уйти со страницы. А мне, как автору материала, хотелось бы принести пользу максимальному количеству людей.
Рассмотрим какие обработчики событий вызываются и в какой последовательности в 1С 8.3, 8.2 в управляемых формах.
Рассмотрим на примере объекта Документ:
Обработчики событий для модуля объекта.
У модулей, указанных на картинке ниже, дополнительно имеется обработчик, связанный с активацией модуля, то есть тело модуля это и есть обработчик активации модуля, который не отображается в подсказке…
Далее, на картинке ниже, показана последовательность вызова обработчиков событий при открытии формы объекта. А под самой картинкой, читайте описание.
1. В модуле менеджера срабатывает обработчик события ОбработкаПолученияФормы(). Он служит для переопределения открываемой формы, поэтому выполняется самым первым.
2. Срабатывает обработчик активации модуля формы на сервере, то есть код, написанный в модуле формы, выполняется на стороне сервера.
3. Срабатывает обработчик активации модуля объекта, то есть выполняется код, написанный в модуле объекта.
4. Если открывается форма для существующего объекта, то срабатывает обработчик ПриЧтенииНаСервере(). Обработчик вызывается при чтении объекта на сервере. Если создается новый объект, то обработчик игнорируется.
5. Срабатывает обработчик ПриСозданииНаСервере(), вызывается при создании формы на сервере.
6. Срабатывает обработчик активации модуля формы на клиенте, то есть код, написанный в модуле формы, выполняется на стороне клиента.
7. Срабатывает обработчик ПриОткрытии(), вызывается при открытии формы на клиенте, до показа окна пользователю.
Заметьте, активация модуля формы выполняется два раза, первый раз на стороне сервера, второй раз на стороне клиента
Так же не стоит злоупотреблять изменением заголовков элементов или их видимость на стороне клиента, т.к. это приводит к неявной активации модуля формы на стороне сервера. Все дело в том, что, например, изменение видимости элементов приводит к перерисовке формы на стороне сервера (выполняется вызов сервера).
Эта замечательная статья была опубликована на сайте: АйТиБложик (Маленький IT блог с характером 1С).
Последовательность вызова обработчиков событий при открытии управляемой формы (УФ)
При открытии формы нового объекта (элемента справочника, документа) и при открытии формы существующего объекта возникает различная последовательность событий.
Форма нового объекта
Если открывается форма нового объекта, то сначала происходит начальное заполнение объекта данными (событие Обработка заполнения в модуле объекта, форма которого открывается), а затем вызываются два события формы: сначала на сервере (При создании на сервере) и затем на клиенте (При открытии). Эти два события позволяют подготовить форму к открытию (рис. 1).
Рис. 1. Последовательность событий при открытии формы нового объекта
№ | Модуль | Метод (процедура) |
1 | Модуль объекта (сервер) | Компиляция и код внизу модуля |
2 | Модуль объекта (сервер) | ОбработкаЗаполнения() |
3 | Модуль формы (сервер) | ПриСозданииНаСервере() |
4 | Модуль формы (клиент) | ПриОткрытии() |
Слева показан клиентский контекст, в котором вызываются события формы. Посередине и справа – серверный контекст, в котором вызываются как события формы, так и события самого прикладного объекта, форма которого открывается.
Форма существующего объекта
Если открывается форма существующего объекта, то последовательность событий будет иной (рис. 2). Сначала на сервере вызываются два события формы. Одно (При чтении на сервере) – чтобы подготовить дополнительные данные, которые зависят от данных объекта. Другое (При создании на сервере) – чтобы максимально подготовить форму к открытию. И наконец, на клиенте вызывается еще одно событие формы (При открытии), чтобы выполнить действия, связанные с открытием формы, которые на сервере выполнить невозможно.
Рис. 2. Последовательность событий при открытии формы существующего объекта
№ | Модуль | Метод (процедура) |
1 | Модуль объекта (сервер) | Компиляция и код внизу модуля |
2 | Модуль формы (сервер) | ПриЧтенииНаСервере() |
3 | Модуль формы (сервер) | ПриСозданииНаСервере() |
4 | Модуль формы (клиент) | ПриОткрытии() |
Из всех перечисленных событий нас прежде всего будут интересовать два события формы: При создании на сервере и При открытии.
Все, что можно сделать на сервере для подготовки формы к открытию, нужно делать в обработчике события При создании на сервере.
В обработчике события При открытии нужно делать только то, что на сервере сделать невозможно. Например, выдать предупреждение, задать вопрос. Или же выполнить те действия, которые выполняются именно тогда, когда форма наверняка открывается. Например, открыть связанную форму, которая «сама по себе» не существует, а существует, только если открыта родительская форма. Потому что обработчик При открытии – последний перед открытием формы, в котором можно отказаться от ее открытия. И если не происходит отказа от открытия родительской формы, то, значит, она наверняка будет открыта.
Последовательность событий, которые происходят при открытии формы нового элемента, можно представить следующей схемой:
Прежде всего, при заполнении нового объекта данными, можно попробовать обойтись вообще без написания какого-либо кода. Для этого у реквизитов объектов конфигурации есть свойства ЗначениеЗаполнения и ЗаполнятьИзДанныхЗаполнения.
Эти свойства позволяют визуально (в конфигураторе) задать правила, по которым реквизит будет заполняться данными при создании нового объекта.
Если этих возможностей недостаточно, то тогда нужно использовать возможности встроенного языка.
Действия с данными объекта нужно выполнять в модуле объекта, в обработчике события ОбработкаЗаполнения. Этот событие возникает только при создании новых объектов, при открытии форм существующих объектов это событие не вызывается. Поэтому в нем не нужно узнавать, новый это объект, или нет. Нужно только описать алгоритм заполнения объекта данными. При этом следует учитывать, что это событие будет вызываться в нескольких случаях:
- при интерактивном создании нового объекта,
- при вводе на основании,
- при выполнении метода объекта Заполнить().
При этом параметр Основание, передаваемый в этот обработчик, может иметь различные значения в зависимости от того, каким образом создается новый элемент.
Например, он может иметь тип ссылки, если новый объект вводится на основании.
Или он может иметь тип Структура, если новый объект создается интерактивной командой из списка, в котором установлен отбор. В этом случае структура будет содержать значения элементов отбора этого списка.
Также этот параметр может иметь тип Неопределено, если новый элемент создается интерактивной командой из панели действий. То есть в своем алгоритме начального заполнения полезно анализировать этот параметр.
Что касается внешнего вида формы нового объекта, то им нужно управлять в обработчике события формы ПриСозданииНаСервере.
Это событие возникает и для новых, и для существующих объектов. Поэтому в нем нужно убедиться в том, что открывается форма именно нового объекта. Убедиться в этом можно проанализировав параметр формы Ключ.
Если объект новый, в этом параметре будет пустая ссылка. Если это существующий объект – в этом параметре будет ссылка на этот объект:
Если требуется выполнять какие-то действия в обработчике события формы ПриОткрытии, то в нем ситуация аналогичная, нужно анализировать параметр формы Ключ.
Для тех кто не хочет читать все что выше, код проверки на ЭтоНовый в Управляемом приложении:
Маленький IT блог с характером 1С.
Поиск по блогу
воскресенье, 14 августа 2016 г.
Последовательность вызова обработчиков событий при открытии формы объекта
При открытии формы объекта, задействованы не только обработчики событий формы, но и модуль менеджера и модуль объекта. Перед рассмотрением последовательности вызова событий, хочу заметить, что количество обработчиков событий для модуля объекта и модуля формы равно не количеству отображаемых процедур в подсказке (см. рисунок 1), а на единицу больше.
Рисунок 1. Обработчики событий модуля объекта Документ |
У этих модулей дополнительно имеется обработчик, связанный с активацией модуля, т.е. тело модуля это и есть обработчик активации модуля, который не отображается в подсказке.
Последовательность вызова обработчиков событий при открытии формы объекта, например объекта Документ, включая активацию модуля, изображена на рисунке 2.
Рисунок 2. Последовательность вызова обработчиков событий при открытии формы |
1. Срабатывает обработчик события ОбработкаПолученияФормы() в модуле менеджера. Обработчик предназначен для переопределения открываемой формы, поэтому выполняется самым первым.
2. Срабатывает обработчик активации модуля формы на сервере, т.е. код, написанный в модуле формы, выполняется на стороне сервера.
3. Срабатывает обработчик активации модуля объекта, т.е. выполняется код, написанный в модуле объекта.
4. Если открывается форма для существующего объекта, то срабатывает обработчик ПриЧтенииНаСервере(). Обработчик вызывается при чтении объекта на сервере. Если создается новый объект, то обработчик игнорируется.
5. Срабатывает обработчик ПриСозданииНаСервере(), вызывается при создании формы на сервере.
6. Срабатывает обработчик активации модуля формы на клиенте, т.е. код, написанный в модуле формы, выполняется на стороне клиента.
7. Срабатывает обработчик ПриОткрытии(), вызывается при открытии формы на клиенте, до показа окна пользователю.
Заметьте, активация модуля формы выполняется два раза, первый раз на стороне сервера, второй раз на стороне клиента
Так же не стоит злоупотреблять изменением заголовков элементов или их видимость на стороне клиента, т.к. это приводит к неявной активации модуля формы на стороне сервера. Все дело в том, что, например, изменение видимости элементов приводит к перерисовке формы на стороне сервера (выполняется вызов сервера).
Читайте также: