События Типов справочников и ТКЭД. Часть 1.

11 10

Цикл статей:

События Типов справочников и ТКЭД. Часть 1.

События Типов справочников и ТКЭД. Часть 2.

События Типов справочников и ТКЭД. Часть 3.

Введение 

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

Статья написана на основе справки.

Общая информация

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

Вообще, все действия с ТС можно условно разделить на две части:

  • Работа с набором данных всего ТС
  • Работа с конкретной записью

Набор данных – Открытие

Это событие выполняется до считывания данных с сервера. Поэтому тут все сводится к тому, какие данные необходимо получить с сервера, а какие нет. Это особенно критично для ТС с большим набором данных, таких как: РКК, Поручения, Договоры и т.д. Так же влияние оказывает количество реквизитов в наборе данных, проще говоря – количество полей таблицы MBAnalit. Существуют заказные разработки DIRECTUM, где количество реквизитов справочника в несколько раз больше, чем в самых «толстых» справочниках стандартной версии.

Для ограничения загружаемых данных можно использовать метод AddWhere:

  // Получить код главной НОР
  OurOrgCode = Конст("КОДГЛОРГ") 
  // Получить ИД главной НОР (данная функция доступна с версии IS-Builder 7.9.2)
  ReferenceRequisiteValue('НОР'; OurOrgCode; SYSREQ_ID)
  AddWhereStr = Format("%s.%s = %s"; ArrayOf(
    Object.TableName;
    Object.Requisites(SYSREQ_OUR_FIRM).SQLFieldName;
    OurOrgID))
  // Отфильтровать справочник по Нашей Организации
  AddWhereID = Object.AddWhere(AddWhereStr)
  // Записать AddWhereID в переменную окружения
  Object.Environment.SetVar('ADD_WHERE_ID'; AddWhereID)
  
  // ***Событие Набор Данных – Закрытие***
  // Не забыть удалить заданное ограничение
  Environment = Object.Environment
  // Проверить, что в окружении есть переменная с нужным именем
  if Environment.IndexOfName('ADD_WHERE_ID') > -1
    AddWhereID  = Object.Environment.PopVar('ADD_WHERE_ID')
    // Удалить ограничение 
    Object.DelWhere(AddWhereID)
  endif

Также можно использовать специальную функцию СпрИзмНабДан(): 

  // Получить код главной НОР
  OurOrgCode = Конст("КОДГЛОРГ") 
  // Получить ИД главной НОР 
  OurOrgID = СпрРекв("НОР"; OurOrgCode; SYSREQ_ID)
  AddWhereStr = Format("%s.%s = %s"; ArrayOf(
    Object.TableName;
    Object.Requisites(SYSREQ_OUR_FIRM).SQLFieldName;
    OurOrgID))

  // Отфильтровать справочник по Нашей Организации
  СпрИзмНабДан(;; AddWhereStr)

Так же можно манипулировать загрузкой реквизитов с помощью свойства Preloaded:

  // Не загружать значение реквизита Дополнение
  Object.Requisites('Дополнение').Preloaded = FALSE

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

Внимание! Значения предопределенных реквизитов (ИД, Код, Состояние и т.д.) загружаются в любом случае, независимо от свойства Preloaded.

Также для увеличения производительности, стоит отказаться от вычисляемых реквизитов, или свести их количество к минимуму, если совсем отказаться нет возможности. Данный тип реквизитов не сохраняется в БД, а вычисляется при открытии набора данных. Начиная с версии IS-Builder 7.10 и выше, есть возможность воспользоваться Дополнительными реквизитами (доступны с версии IS-Builder 7.10.0), заменив ими вычисляемые реквизиты. 

Запись – Добавление До

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

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

Запись – Добавление После

В момент выполнения этого события, запись существует только на клиенте. В случае ошибки в вычислениях – добавление записи будет также отменено. Если запись создана копированием, то все копируемые реквизиты уже заполнены, и с ними можно работать. В данном событии нужно вычислять и заполнять значения реквизитов. Так как в данном событии происходит уже непосредственное изменение реквизитов, то существенное влияние на производительность могут оказать вычисления на самих реквизитах.

Вычисления на реквизитах, срабатывают после изменения значений этих реквизитов. В платформе есть возможность отключения этого механизма.

  // Получить объект типа IRequisite
  AdditionReq = Object.Requisites('Дополнение')
  // Отключить вычисления на реквизите Дополнение
  AdditionReq.Events.Events(reOnChange).Enabled = FALSE
  // Присвоить значение
  AdditionReq Value = <значение>
  // Включить вычисления на реквизите обратно
  AdditionReq.Events.Events(reOnChange).Enabled = TRUE

Также в этом событии, при необходимости, нужно очищать значения реквизитов, если запись была скопирована:

  if Object.Copied
    UncopiedReqArray = ArrayOf("Реквизит1"; "Реквизит2"; "Реквизит3")
    foreach ReqName in CArrayElement(UncopiedReqArray)  
      CurrentRequisite = Object.FindRequisite(ReqName)
      if Assigned(CurrentRequisite)
        CurrentRequisite.Value = NULL
      endif 
    endforeach
  endif

Запись – Открытие

Событие выполняется при открытии карточки существующей записи и при открытии карточки вновь добавляемой записи. В случае ошибки в вычислениях события выводится сообщение об ошибке и  открытие записи отменяется.

Если идет работа с версией IS-Builder (до 7.7.0.1601/7.8.3.1011), в которой еще нет события «Форма-карточка – Показ», то в этом событии можно управлять доступностью реквизитов, кнопок, таблиц и др. элементов формы, перед этим обязательно проверив, что происходит визуальная работа с карточкой.

  if not VarIsNull(Object.View) and InteractiveMode()
    <вычисления>
  endif

Во всех остальных случаях управлять доступностью элементов формы нужно в событии «Форма-карточка – Показ».

В этом событии из БД загружаются значения всех реквизитов, в том числе и табличных частей. Тут можно работать с вычисляемыми реквизитами табличной части. Также можно запоминать значения каких-либо реквизитов, чтобы использовать эти значения в событиях Сохранения, для проверки, изменилось значение реквизита или нет. Либо просто вычислять значения одних реквизитов на основе значений других.

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

Внимание! Событие срабатывает не только при программном или визуальном открытии записи, но и при открытии свойств записи в списке записей (пункт меню Файл/Свойства записи).

  // Определить, открываются ли свойства записи можно таким кодом:
  if Object.Params.IndexOfName(SHOW_RECORD_PROPERTIES_FORM) > -1
    // Открылись свойства записи
  endif

Продолжение следует...

Александр Павлов

Что такое InteractiveMode() ? - в WinHelp-е про это ничего не написано.

Дмитрий Тарасов
Что такое InteractiveMode() ? - в WinHelp-е про это ничего не написано.

Это системная функция:

InteractiveMode

Определить текущий режим работы IS-Builder.

Группа:

IS-Builder. Системные функции

Синтаксис:

InteractiveMode()

Возвращаемое значение:

При работе в интерактивном режиме - True, иначе - False.

Описание:

Функция определяет текущий режим работы IS-Builder. В интерактивном режиме работы разрешен показ форм и сообщений. Такой режим установлен по умолчанию. При обработке задач службой Workflow, а также при выполнении сценариев с использованием утилиты SAJobRunner интерактивный режим выключен. При попытке показа форм и сообщений при выключенном интерактивном режиме будет сгенерировано исключение.

Примечание: показ индикатора при выключенном интерактивном режиме не приведет к генерации исключения. Индикатор в этом случае не будет показан.

 

Марина Котусева

Начиная с версии IS-Builder 7.10 и выше, есть возможность воспользоваться Дополнительными реквизитами (доступны с версии IS-Builder 7.10.0), заменив ими вычисляемые реквизиты.

IS-Builder 7.10 - это 4.8.сколько? Или даже не "8" :)?
Андрей Подкин
IS-Builder 7.10 - это 4.8.сколько? Или даже не "8" :)?
4.9.
Алексей Язынин

По первому примеру. Что будет если добавленное через AddWhere ограничение не удалить? Отразится ли это только на текущем пользователе или на всех пользователях системы?

Алексей Язынин

Написано:

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

 

Поясните, пожалуйста, а для чего это важно понимать? Из текста не понял.

Иван Чурбаков
По первому примеру. Что будет если добавленное через AddWhere ограничение не удалить? Отразится ли это только на текущем пользователе или на всех пользователях системы?
На всех точно не будет распространяться: это ограничение хранится в памяти локального клиента. По факту еще не встречался с проблемами из-за неудаления (хотя стараемся удалять, все-таки мусор после себя оставлять не стоит).
Андрей Девятьяров
По первому примеру. Что будет если добавленное через AddWhere ограничение не удалить? Отразится ли это только на текущем пользователе или на всех пользователях системы?

Иван прав - ограничение, добавленное через AddWhere, ограничивает получаемый набор данных только для конкретного пользователя. У каждого клиента в момент открытия справочника может сформироваться свое ограничение AddWhere.
 
Написано: Тут важно понимать, что после открытия набора данных, указатель всегда находится на какой-нибудь записи (если есть хотя бы одна запись в наборе данных).   Поясните, пожалуйста, а для чего это важно понимать? Из текста не понял.

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

Такой вопрос может ли кто пояснить особенность работы события Набор - Открытие Данных для таких справочников как НОР, ПОЛ, кажется еще для ТЭД и ВЭД было такое. У них данное событие вызывается дважды. Причем при первом вызове, у события странный режим - можно вызывать только системные функции, глобальные переменные с фабриками также пустые.

Андрей Девятьяров
Такой вопрос может ли кто пояснить особенность работы события Набор - Открытие Данных для таких справочников как НОР, ПОЛ, кажется еще для ТЭД и ВЭД было такое. У них данное событие вызывается дважды. Причем при первом вызове, у события странный режим - можно вызывать только системные функции, глобальные переменные с фабриками также пустые.

Проверил на IS-Builder 792 2206 на справочниках НОР/ПОЛ - событие Набор данных Открытие вызывается как и у всех - 1 раз. Возможно, повторные срабатывания события при открытии как то связаны с вашей прикладной разработкой.

Авторизуйтесь, чтобы написать комментарий