Процедуры-обработчики событий
Особенностью обработки событий среде 1С:Предприятия 8 является то, что имя процедуры-обработчика в одних случаях должно совпадать с именем события, а в других случаях может от него отличаться. Данная статья написана, чтобы внести ясность в этом вопросе.
Обратите внимание, что термин «Предопределенная процедура», который использовался в версии 7.х, теперь заменен на «процедура-обработчик события» или просто «обработчик события».
ПРАВИЛО №1. Если процедура-обработчик события относится к форме или элементу управления, то ее обязательно нужно указывать в палитре свойств для формы или элемента управления. |
Ниже показана палитра свойств для формы элемента справочника «Номенклатура» с несколькими назначенными обработчиками событий:
За информацией о приемах работы с этой частью палитры свойств обращайтесь к документации: книга «Конфигурирование и администрирование», «Глава 3. Объекты конфигурации => Свойства элементов управления => Категория свойств События» (стр. 1 — 204)
Обратите внимание на важный момент, имя процедуры-обработчика событий может не совпадать с именем события . Для элементов управления чаще всего так и бывает, например, процедура «ТипЦенПриИзменении» обрабатывает событие «ПриИзменении» поля ввода для реквизита «ТипЦен», как показано на следующем рисунке:
Как правило, процедура-обработчик имеет тот же набор параметров, что и событие. Если у нее нет соответствующих параметров, то обработка события может получиться неполной. Поэтому рекомендуется создавать процедуры-обработчики конструктором через палитру свойств, нажимая кнопку с лупой или выбирая процедуру из выпадающего списка.
Есть еще одна интересная возможность: одна и та же процедура может «обслуживать» несколько событий формы или элементов управления, в том числе от разных источников. Элемент управления, который инициировал событие, передается в качестве первого параметра в эту процедуру-обработчик (параметр «Элемент»), и при необходимости алгоритм может проанализировать, откуда пришло событие, и выполнить соответствующие действия.
ПРАВИЛО №2. Процедуры-обработчики событий, расположенные в модуле приложения, модуле внешнего соединения, модуле прикладного объекта должны называться точно так, как называются соответствующие события. |
Поясним это правило на конкретных примерах:
1. Процедуры-обработчики событий, расположенные в модуле приложения или модуле внешнего соединения, совпадают с именами событий:
- ПередНачаломРаботыСистемы
- ПриНачалеРаботыСистемы
- ПриЗавершенииРаботыСистемы
- ПередЗавершениемРаботыСистемы
- ОбработкаВнешнегоСобытия
2. Имена процедур-обработчиков событий, расположенных в модуле объекта, тоже строго соответствуют именам событий:
для модуля документа (события объекта типа «ДокументОбъект»)
- ПередЗаписью
- ПриЗаписи
- ПриУдалении
- ПриКопировании
- ОбработкаЗаполнения (для обработки «ввода на основании»)
- ОбработкаПроведения
- ОбработкаУдаленияПроведения
- ПриУстановкеНовогоНомера
Аналогичные обработчики событий могут располагаться в модуле справочника и модулях других прикладных объектов.
3. Есть также модуль набора записей для всех видов регистров, который подобен модулям прикладных объектов. Модуль набора записей может содержать следующие процедуры-обработчики событий (имена процедур должны совпадать с именами событий):
- ПередЗаписью
- ПриЗаписи
Ниже приведены несколько важных моментов, которые полезно помнить при работе с событиями:
Примечание 1. Событие ПередЗаписью прикладного объекта отличается от события ПередЗаписью формы, связанной с этим прикладным объектом. Обработчик события в модуле формы вызывается при интерактивной записи, а обработчик в модуле объекта при любом способе записи элемента в базу данных.
Примечание 2. Если в процедурах-обработчиках модуля объекта нужно обратиться к самому объекту (текущий элемент справочника, текущий документ и т.д.), то для этого можно использовать свойство ЭтотОбъект. Оно содержит объект типа «СправочникОбъект», «ДокументОбъект» и т.д.
Примечание 3. Считается грубой ошибкой в процедурах-обработчиках событий объектов вызывать такие интерактивные команды, как Вопрос и Предупреждение. Эти команды показывают на экране диалоговое окно и ждут реакции пользователя. Так как событие обрабатывается в рамках транзакции, то это вызовет значительную задержку в обработке события и часть данных (или вся таблица) будет заблокирована на время ожидания.
Структура модуля
Область применения: управляемое приложение, мобильное приложение, обычное приложение.
1.1. В программном модуле (общие модули, модули объектов, модули менеджеров объектов, модули форм, команд и т.п.) в общем случае могут присутствовать следующие разделы в приведенной ниже последовательности:
- заголовок модуля
- раздел описания переменных
- экспортные процедуры и функции модуля, составляющие его программный интерфейс
- обработчики событий объекта (формы)
- служебные процедуры и функции модуля
- раздел инициализации
Некоторые разделы могут присутствовать только в модулях определенного вида. Например, обработчики событий элементов форм могут присутствовать только в модулях форм, а раздел описания переменных и раздел инициализации не могут быть определены в неглобальных общих модулях, модулях менеджеров объектов, наборов записей, значений констант и модуле сеанса.
Требование о разделении кода модуля на разделы призвано повысить читаемость кода и упростить внесение изменений в код разными авторами (разработчиками) как при коллективной разработке, так и при доработке прикладных решений на конкретных внедрениях.
1.2. Объемные разделы модулей рекомендуется разбивать на подразделы по функциональному признаку.
1.3. Разделы и подразделы оформляются в виде областей. При этом имена областей должны удовлетворять требованиям стандарта Правила образования имен переменных
1.4. Шаблон (заготовка для копирования) разделов для общих модулей:
#Область ПрограммныйИнтерфейс // Код процедур и функций #КонецОбласти #Область СлужебныйПрограммныйИнтерфейс // Код процедур и функций #КонецОбласти #Область СлужебныеПроцедурыИФункции // Код процедур и функций #КонецОбласти
#Region Public // Enter code here. #EndRegion #Region Internal // Enter code here. #EndRegion #Region Private // Enter code here. #EndRegion
- Раздел «Программный интерфейс» содержит экспортные процедуры и функции, предназначенные для использования другими объектами конфигурации или другими программами (например, через внешнее соединение).
- Раздел « Служебный программный интерфейс » предназначен для модулей, которые являются частью некоторой функциональной подсистемы. В нем должны быть размещены экспортные процедуры и функции, которые допустимо вызывать только из других функциональных подсистем этой же библиотеки.
- Раздел «Служебные процедуры и функции» содержит процедуры и функции, составляющие внутреннюю реализацию общего модуля. В тех случаях, когда общий модуль является частью некоторой функциональной подсистемы, включающей в себя несколько объектов метаданных, в этом разделе также могут быть размещены служебные экспортные процедуры и функции, предназначенные только для вызова из других объектов данной подсистемы.
#Область ОбновлениеИнформационнойБазы // Код процедур и функций #КонецОбласти
#Region InfobaseUpdate // Enter code here. #EndRegion
1.5. Шаблон оформления разделов для модулей объектов, менеджеров, наборов записей, обработок, отчетов и т.п.:
#Область ОписаниеПеременных #КонецОбласти #Область ПрограммныйИнтерфейс // Код процедур и функций #КонецОбласти #Область ОбработчикиСобытий // Код процедур и функций #КонецОбласти #Область СлужебныйПрограммныйИнтерфейс // Код процедур и функций #КонецОбласти #Область СлужебныеПроцедурыИФункции // Код процедур и функций #КонецОбласти #Область Инициализация #КонецОбласти
#Region Variables #EndRegion #Region Public // Enter code here. #EndRegion #Region EventHandlers // Enter code here. #EndRegion #Region Internal // Enter code here. #EndRegion #Region Private // Enter code here. #EndRegion #Region Initialize #EndRegion
- Раздел «Программный интерфейс» содержит экспортные процедуры и функции, предназначенные для использования в других модулях конфигурации или другими программами (например, через внешнее соединение). Не следует в этот раздел помещать экспортные функции и процедуры, которые предназначены для вызова исключительно из модулей самого объекта, его форм и команд. Например, процедуры заполнения табличной части документа, которые вызываются из обработки заполнения в модуле объекта и из формы документа в обработчике команды формы не являются программным интерфейсом модуля объекта, т.к. вызываются только в самом модуле и из форм этого же объекта. Их следует размещать в разделе «Служебные процедуры и функции».
- Раздел «Обработчики событий» содержит обработчики событий модуля объекта ( ПриЗаписи , ПриПроведении и др.)
- Раздел « Служебный программный интерфейс » имеет такое же предназначение, как и в общих модулях.
- Раздел «Служебные процедуры и функции» имеет такое же предназначение, как и в общих модулях.
1.6. Шаблон оформления разделов для модулей форм:
#Область ОписаниеПеременных #КонецОбласти #Область ОбработчикиСобытийФормы // Код процедур и функций #КонецОбласти #Область ОбработчикиСобытийЭлементовШапкиФормы // Код процедур и функций #КонецОбласти #Область ОбработчикиСобытийЭлементовТаблицыФормы // Код процедур и функций #КонецОбласти #Область ОбработчикиКомандФормы // Код процедур и функций #КонецОбласти #Область СлужебныеПроцедурыИФункции // Код процедур и функций #КонецОбласти
#Region Variables #EndRegion #Region FormEventHandlers // Enter code here. #EndRegion #Region FormHeaderItemsEventHandlers // Enter code here. #EndRegion #Region FormTableItemsEventHandlers // Enter code here. #EndRegion #Region FormCommandsEventHandlers // Enter code here. #EndRegion #Region Private // Enter code here. #EndRegion
- Раздел «Обработчики событий формы» содержит процедуры-обработчики событий формы: ПриСозданииНаСервере , ПриОткрытии и т.п.
- Раздел «Обработчики событий элементов шапки формы» содержит процедуры-обработчики элементов, расположенных в основной части формы (все, что не связано с таблицами на форме).
- В разделах «Обработчики событий элементов таблицы формы » размещаются процедуры-обработчики таблиц формы и элементов таблиц. Для процедур-обработчиков каждой таблицы должен быть создан свой раздел.
- Раздел «Обработчики команд формы» содержит процедуры-обработчики команд формы (имена которых задаются в свойстве Действие команд формы).
- Раздел «Служебные процедуры и функции» имеет такое же предназначение, что и в общих модулях.
1.7. Шаблон оформления разделов для модулей команд:
#Область ОбработчикиСобытий // Код процедур и функций #КонецОбласти #Область СлужебныеПроцедурыИФункции // Код процедур и функций #КонецОбласти
#Region EventHandlers // Enter code here. #EndRegion #Region Private // Enter code here. #EndRegion
- Раздел «Обработчики событий» содержит процедуру-обработчик команды ОбработкаКоманды .
- Раздел «Служебные процедуры и функции» имеет такое же предназначение, что и в общих модулях.
1.8. В модуле не должно быть пустых областей.
2. Общие требования к разделам программных модулей.
2.1. Заголовок модуля представляет собой комментарий в самом начале модуля. В заголовке модуля приводится его краткое описание и условия применения.
Например:
//////////////////////////////////////////////////////////////////////////////// // Клиентские процедуры и функции общего назначения: // - для работы со списками в формах; // - для работы с журналом регистрации; // - для обработки действий пользователя в процессе редактирования // многострочного текста, например комментария в документах; // - прочее. // ////////////////////////////////////////////////////////////////////////////////
Для модулей форм в заголовке рекомендуется размещать описание параметров формы.
2.2. Раздел описания переменных . Имена переменных назначаются согласно общим правилам образования имен переменных, а их использование описывается в статье Использование глобальных переменных в программных модулях.
Все переменные модуля должны быть снабжены комментарием, достаточным для понимания их назначения. Комментарий рекомендуется размещать в той же строке, где объявляется переменная.
Пример:
#Область ОписаниеПеременных Перем ВалютаУчета; Перем АдресПоддержки; . #КонецОбласти
#Region Variables Var PresentationCurrency; Var SupportEmail; . #EndRegion
2.3. Программный интерфейс . Экспортные процедуры и функции, составляющие программный интерфейс модуля, размещаются сразу же после описания переменных. Такие процедуры и функции предназначены для использования другими объектами конфигурации или другими программами (например, через внешнее соединение), поэтому должны быть расположены в модуле на «видном месте».
2.4.1. Обработчики событий формы, команд и элементов формы . Перед служебными процедурами и функциями в модуле формы располагаются обработчики событий формы, а также обработчики событий команд и элементов формы.
Методическая рекомендация (полезный совет)
2.4.2. Рекомендуется обработчики одного элемента формы располагать вместе, придерживаясь, при этом, порядка их следования в панели свойств редактора формы в конфигураторе.
2.4.3. У каждого события должна быть назначена своя процедура-обработчик. Если одинаковые действия должны выполняться при возникновении событий в разных элементах формы следует:
создать отдельную процедуру (функцию), выполняющую необходимые действия
для каждого элемента формы создать отдельный обработчик с именем, назначаемым по умолчанию
из каждого обработчика вызвать требуемую процедуру (функцию).
&НаКлиенте Процедура ПоИсполнителюПриИзменении(Элемент) ПараметрыОтбора = Новый Соответствие(); ПараметрыОтбора.Вставить("ПоАвтору", ПоАвтору); ПараметрыОтбора.Вставить("ПоИсполнителю", ПоИсполнителю); УстановитьОтборСписка(Список, ПараметрыОтбора); КонецПроцедуры &НаКлиенте Процедура ПоАвторуПриИзменении(Элемент) ПоИсполнителюПриИзменении(Неопределено); КонецПроцедуры
&НаКлиенте Процедура ПоИсполнителюПриИзменении(Элемент) УстановитьОтбор(); КонецПроцедуры &НаКлиенте Процедура ПоАвторуПриИзменении(Элемент) УстановитьОтбор(); КонецПроцедуры &НаСервере Процедура УстановитьОтбор() ПараметрыОтбора = Новый Соответствие(); ПараметрыОтбора.Вставить("ПоАвтору", ПоАвтору); ПараметрыОтбора.Вставить("ПоИсполнителю", ПоИсполнителю); УстановитьОтборСписка(Список, ПараметрыОтбора); КонецПроцедуры
Это требование обусловлено тем, что логически процедуры-обработчики событий не предназначены для использования в коде модуля, а вызываются непосредственно платформой. Смешение же этих двух сценариев в одной процедуре неоправданно усложняет ее логику и снижает ее устойчивость (вместо одного предусмотренного сценария вызова — по событию из платформы — код процедуры должен рассчитывать и на другие «прямые» вызовы из кода).
2.5. Обработчики событий модулей объекта и менеджера объекта размещаются после раздела с программным интерфейсом, но до служебных процедур и функций модуля.
Методическая рекомендация (полезный совет)
2.5.1. Рекомендуется располагать обработчики, придерживаясь порядка их следования в описании встроенного языка.
2.6. Служебные процедуры и функции модуля , которые не являются обработчиками событий, а составляют внутреннюю реализацию модуля, размещаются в модуле следом за обработчиками событий.
В тех случаях когда общий модуль является частью некоторой функциональной подсистемы, включающей в себя несколько объектов метаданных, в этом разделе также могут быть размещены служебные экспортные процедуры и функции, предназначенные только для вызова из других объектов данной подсистемы.
Процедуры и функции, связанные между собой по характеру или по логике работы рекомендуется располагать вместе. В модулях форм не рекомендуется явно группировать процедуры и функции модуля на серверные, клиентские и функции без контекста, так как такое «технологическое» упорядочивание затрудняет понимание логики модуля, отвлекая внимание разработчика на детали ее реализации.
2.7. Раздел инициализации содержит операторы, инициализирующие переменные модуля или объект (форму).
Например:
#Область Инициализация АдресПоддержки = "v8@1c.ru"; ВыполнитьИнициализацию(); . #КонецОбласти
#Region Initialize SupportEmail = "v8@1c.ru"; Ctor(); . #EndRegion
Для оформления разделов кода в виде областей рекомендуется воспользоваться приложенной обработкой.
Встроенный язык
Встроенный язык является важной частью технологической платформы «1С:Предприятия 8», поскольку позволяет разработчику описывать собственные алгоритмы функционирования прикладного решения.
Встроенный язык имеет много общих черт с другими языками, такими как Pascal, Java Script, Basic, что облегчает его освоение начинающими разработчиками. Однако он не является прямым аналогом какого-либо из перечисленных языков.
Вот лишь некоторые, наиболее значимые особенности встроенного языка:
- предварительная компиляция — перед исполнением модули, содержащие текст на встроенном языке, преобразуются во внутренний код;
- кэширование скомпилированных модулей в памяти;
- мягкая типизация — тип переменной определяется типом значения, которое она содержит, и может изменяться в процессе работы;
- отсутствие программного описания объектов конфигурации — разработчик может использовать либо встроенные в платформу объекты, либо объекты, созданные системой в результате визуального конструирования прикладного решения.
Событийная ориентированность встроенного языка
Назначение встроенного языка в системе 1С:Предприятие определяется идеологией создания прикладных решений. Прикладные решения в 1С:Предприятии 8 не кодируются целиком. Большая часть прикладного решения создается разработчиком путем визуального конструирования — создания новых объектов конфигурации, задания их свойств, форм представления, взаимосвязей и пр. Встроенный язык используется лишь для того, чтобы определить поведение объектов прикладного решения, отличное от типового, и создать собственные алгоритмы обработки данных.
По этой причине модули, содержащие текст на встроенном языке, используются системой в конкретных, заранее известных ситуациях, которые могут возникнуть в процессе работы прикладного решения. Такие ситуации называются событиями. События могут быть связаны с функционированием объектов прикладного решения или с самим прикладным решением, как таковым.
Например, с функционированием объекта прикладного решения Справочник связан ряд событий, среди которых есть событие ПередЗаписью:
Это событие возникает непосредственно перед тем, как данные элемента справочника должны быть записаны в базу данных. Разработчик, используя встроенный язык, может описать алгоритм, который, например, будет проверять корректность данных, введенных пользователем. Разместив этот алгоритм в соответствующем модуле, разработчик обеспечит то, что каждый раз, как пользователь будет выполнять запись элемента справочника, система будет выполнять созданный разработчиком алгоритм и проверять, не забыл ли пользователь заполнить обязательные реквизиты справочника.
Таким образом можно сказать, что встроенный язык является скриптовым языком для программирования бизнес-логики, а использование модулей на встроенном языке является событийно-зависимым, т. е. выполнение модулей происходит при возникновении определенных событий в процессе функционирования прикладного решения.
Универсальные коллекции значений
Встроенный язык поддерживает работу с большим количеством разнообразных объектов. Безусловно, основную группу объектов составляют прикладные объекты, позволяющие описывать алгоритмы функционирования бизнес-логики.
Однако не менее важной группой являются объекты, предназначенные для хранения временных наборов данных в течение сеанса работы пользователя. Как правило, они служат для вспомогательного сбора, группировки, анализа и обработки информации:
Перечислим кратко их возможности:
Массив
Представляет собой пронумерованную коллекцию значений произвольного типа. К элементу массива можно обращаться по его индексу. В качестве элементов массива могут выступать, в частности, другие массивы. Это позволяет создавать многомерные массивы.
Структура
Представляет собой поименованную коллекцию, состоящую из пар ключ — значение. Ключ может быть только строковым, значение — произвольного типа. К элементу структуры можно обращаться по значению его ключа, т. е. по имени. Обычно используется для хранения небольшого количества значений, каждое из которых имеет некоторое уникальное имя.
Соответствие
Также как и структура, представляет собой коллекцию пар ключ — значение. Однако, в отличие от структуры, ключ может быть практически любого типа.
Список значений
Используется, как правило, для решения интерфейсных задач. Позволяет строить динамические наборы значений и манипулировать ими (добавлять, редактировать, удалять элементы, сортировать). Он может содержать значения любого типа, кроме того, в одном списке типы хранимых значений могут быть разными.
Например, список значений может использоваться для выбора конкретного документа из списка возможных документов, сформированного по сложному алгоритму.
Таблица значений
Таблица значений позволяет строить динамические наборы значений и манипулировать ими. Она может быть наполнена значениями любого типа, и в одной таблице типы хранимых значений могут быть разными.
Одним из примеров использования таблицы значений может служить организация представления в форме списка элементов справочника, отобранных по сложному алгоритму.
Дерево значений
Дерево значений представляет собой динамически формируемый набор значений любого типа, похожий на таблицу значений. В отличие от таблицы значений, строки дерева значений могут образовывать иерархические структуры: каждая строка дерева может иметь набор подчиненных строк, каждая из подчиненных строк, в свою очередь, также может иметь набор подчиненных строк и так далее. При этом поиск значений, сортировка, получение итогов могут осуществляться либо по текущему уровню иерархии, либо включая все подчиненные.
COMSafeArray
Представляет собой объектную оболочку над многомерным массивом SAFEARRAY из COM. Позволяет создавать и использовать SAFEARRAY для обмена данными между COM-объектами.
Фиксированный массив
Неизменяемый массив. Массив заполняется системой при инициализации объектов данного типа или разработчиком, с помощью конструктора.
Редактор текстов и модулей
Для создания и изменения текстов на встроенном языке разработчик может использовать редактор текста и модуля, обладающий удобными средствами создания, редактирования и синтаксической проверки модулей. Подробнее…
Обработчик события ОбработкаПроверкиЗаполнения
Область применения: управляемое приложение, мобильное приложение, обычное приложение.
1.1. В данном обработчике модуля объекта выполняются действия, связанные с проверкой правильности заполнения значений реквизитов объектов (измерений, ресурсов, реквизитов табличных частей и т.п., далее: просто «реквизиты»).
1.2. Данным обработчиком следует пользоваться в случаях, когда для проверки корректности значений реквизитов обычной проверки на заполненность уже недостаточно (например, значение реквизита логически связано со значением другого реквизита), или же требование к тому, чтобы значение реквизита было заполнено не является безусловным.
Если проверка заполнения какого-либо реквизита — условная (т.е. зависит от значений других реквизитов или значения параметризированной функциональной опции) в обработчике следует предусмотреть код, который удаляет имя такого реквизита из массива проверяемых реквизитов ПроверяемыеРеквизиты . В общем виде, схема проверки заполнения выглядит следующим образом:
- создать массив НепроверяемыеРеквизиты ;
- в процессе проверки условий, добавлять в этот массив имена непроверяемых реквизитов (табличных частей);
- вызвать процедуру для удаления непроверяемых реквизитов (текст процедуры УдалитьНепроверяемыеРеквизитыИзМассива приведен ниже).
При этом не рекомендуется использовать другие схемы проверки заполнения значений реквизитов, так как они затрудняют анализ логики работы конфигурации, поскольку скрывают из свойства «Проверка заполнения» случаи условной проверки заполнения значений объектов.
Например, неправильно:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Проверка значения реквизита на соответствие некоторым требованиям
Если НЕ ИННСоответствуетТребованиям(ИНН) Тогда
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = НСтр(«ru = ‘ИНН задан неверно.'»);
Сообщение.Поле = «ИНН»;
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
.
// Значение реквизита не должно быть пустым в зависимости от значения другого реквизита
Если ЮрФизЛицо = Перечисления.ЮрФизЛицо.ФизЛицо Тогда
// Для индивидуального предпринимателя должно быть сопоставлено физ. лицо
ПроверяемыеРеквизиты.Добавить(«ИндивидуальныйПредприниматель»);
КонецЕсли;
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
НепроверяемыеРеквизиты = Новый Массив();
.
// Проверка значения реквизита на соответствие некоторым требованиям
Если НЕ ИННСоответствуетТребованиям(ИНН) Тогда
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = НСтр(«ru = ‘ИНН задан неверно.'»);
Сообщение.Поле = «ИНН»;
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
НепроверяемыеРеквизиты.Добавить(«ИНН»);
КонецЕсли;
.
// Значение реквизита не должно быть пустым в зависимости от другого реквизита
Если ЮрФизЛицо <> Перечисления.ЮрФизЛицо.ФизЛицо Тогда
НепроверяемыеРеквизиты.Добавить(«ИндивидуальныйПредприниматель»);
КонецЕсли;
Процедура УдалитьНепроверяемыеРеквизитыИзМассива(МассивРеквизитов, МассивНепроверяемыхРеквизитов) Экспорт
Для Каждого ЭлементМассива Из МассивНепроверяемыхРеквизитов Цикл
// перед удалением реквизита из массива необходимо проверить, что он там есть
// (не был удален ранее платформой или в коде).
ПорядковыйНомер = МассивРеквизитов.Найти(ЭлементМассива);
Если ПорядковыйНомер <> Неопределено Тогда
МассивРеквизитов.Удалить(ПорядковыйНомер);
КонецЕсли;
1.3. Следует учитывать, что обработчик ОбработкаПроверкиЗаполнения вызывается не при каждой записи объекта, в частности, он не вызывается в случаях если запись были инициирована программно.
Методическая рекомендация (полезный совет)
1.4. В случае использования в конфигурации подсистемы «Обмен данными» Библиотеки стандартных подсистем обработчик ОбработкаПроверкиЗаполнения вызывается при проведении документов, после их загрузки из сообщения обмена. Для отключения некоторых проверок в этом режиме в обработчике можно анализировать дополнительное свойство объекта ДополнительныеСвойства . ОтложенноеПроведение .
Проверки, выполняемые в и вне транзакции записи объекта
2.1. Проверки в обработчике ОбработкаПроверкиЗаполнения выполняются вне транзакции записи объекта. Поскольку в случае некорректного заполнения объекта выполнение операции будет прервано еще до записи объекта в базу данных, то размещение проверок в этом обработчике является наиболее эффективным.
При выполнении внетранзакционных проверок в обработчике ОбработкаПроверкиЗаполнения необходимо учитывать тот факт, что новое состояние объекта еще не записано. Если требуется выполнить запрос к тем или иным данным системы, например, прочитать признак ВидНоменклатуры для товаров, выбранных в табличной части документа, «отталкиваясь» от данных документа, то такую поверку можно выполнить, применяя сохранение необходимых для запроса данных во временные таблицы.
2.2. В то же время, в обработчике ОбработкаПроверкиЗаполнения не следует размещать проверки, которые должны гарантировать целостное состояние объекта или зависящих от него данных (например, движений) на которые рассчитывает система. Поэтому для реквизитов, некорректные значения которых могут привести к рассогласованности данных в информационной базе, проверку корректности следует выполнять в обработчиках событий, возникающих в транзакции записи — ПередЗаписью , ПриЗаписи , ОбработкаПроведения (для документов).
Для транзакционных проверок, в свою очередь, выделяются два случая:
- Проверка состояния движений, формируемых документами оперативного учета. Такие проверки довольно часто встречаются в приложениях с оперативным учетом.
- Проверка состояния других объектов информационной базы, ссылки на которых содержатся в текущем объекте. Такие проверки следует применять очень редко. Не следует злоупотреблять количеством проверок в транзакции записи объекта. Следует помнить, что внутри транзакции записи имеет смысл выполнять только проверки таких ресурсов или таких правил соответствия объектов друг другу, которые не изменяются без проверок всеми участниками процесса.
В первом случае, проверку остатков некоторого ресурса имеет смысл выполнять в транзакции записи только в том случае, если все документы выполняют такую же проверку в транзакции записи. Если хоть один из документов, изменяющих ресурс, делает это без проверок, выполнение проверок другими участниками процесса бессмысленно и такие проверки необходимо выполнять вне транзакции. Исключением может быть только случай, когда документ, который выполняет изменение контролируемого ресурса без проверок, вводится крайне редко. Например, не смотря на то, что документ «Инвентаризация товаров» изменяет остатки товаров без проверок, эта ситуация допустима в виду того, что он вводится крайне редко. Каждое такое исключение из правила должно быть оправданным.
Во втором случае, если при записи Подразделения в транзакции записи выполняется проверка, что сотрудник, выбранный в качестве руководителя подразделения, имеет должность «Руководитель», то при записи Сотрудника также должна выполняться и «встречная» проверка этого же правила: нельзя записать Сотрудника с должностью отличной от «Руководитель», если он указан руководителем того или иного подразделения. Поскольку правило, что «Сотрудник», выбранный руководителем подразделения, должен иметь должность «Руководитель», может быть нарушено как при записи подразделения, так и при записи сотрудника, то и проверка должна выполняться или в транзакции записи обоих объектов, или вне транзакции записи обоих объектов (а может и не выполняться вообще).