Использование предопределенных элементов. Ошибки в предопределённых элементах Что такое предопределенные элементы 1с

Доброго времени суток.

Сегодня поговорим о новшестве в платформе 8.3 касающегося предопределенных элементов.

Вступление

Напомню, что раньше на практике, очень часто хотелось глядя в элемент справочника узнать его предопределенное имя. Например Вы создали два предопределнных контрагента и назвали его ИПСидоров и ОООМетеор. И зашили на них некую логику.

Когда все отладили и отработали, выяснилось, что задача была поставлена наоборот и логика для ИП нужна для ООО, а логика ООО для ИП. "Нет проблем", говорим мы и в режиме предприятия переименовываем элементы. Ведь лезть в код гораздо сложнее. Проходит год и Вам поставлена новая задача: для ИП Сидорова настроить еще какую-то логику. Вы лезете в конфигуратор, пишите логику, начинаете проверять и ничего не работает, т.к. в конфигураторе ИПСидоров, а в предприятии - ОООМетеор. Мозг сломан и эти грабли хочется уничтожить. Самое простое и наглядное - это вывести имя предопределенного элемента в форму списка. Вот тут засада, получить имя предопределенного в 8.2 можно только методом. А метод это свои неудобства, его нельзя получить в запросе. Т.е. первое неудобство - получить имя предопределенного по ссылке на справочник.

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

Теперь по делу

Первое, это то, что у справочника появилось свойство "Обновление предопределенных данных".

Что нам дает это поле? Если оно установлено в "Не обновлять автоматически", то добавив предопределенный элемент, мы его не увидим в справочнике сразу. Т.е. метаданные никак не связаны с данными. И если его не создать в справочнике, то и обращение к нему по его имени через менеджер справочника вызовет синтаксическую ошибку.

Очень интересно, а зачем? Как же нам создать элемент в справочнике? А как хотите, можете создать, а можете и связать его с уже существующим. Теперь у справочника есть реквизит "ИмяПредопределенныхДанных". Мы создаем элемент справочника программно как обычно через "Справочники.Контрагенты.СоздатьЭлемент()" и заполняем его реквизит "ИмяПредопределенныхДанных" равным имени предопределенного элемента. Или же если элемент уже есть, получаем его объект и в нем опять таки заполняем "ИмяПредопределенныхДанных". Все.

И на последок немного сиропа

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

Спасибо за внимание.

Действует для версии платформы 1С:Предприятие 8.3.3 и выше без режима совместимости с версией 8.2

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

1.2. В большинстве случаев, предопределенные элементы рекомендуется создавать автоматически, поскольку они постоянно нужны и требуется упростить обращение к этим элементам из кода.
Например, предопределенная страна Россия в справочнике Страны мира , предопределенные профиль групп доступа Администратор и т.п.

Для этого

  • в свойстве справочника, плана счетов , плана видов характеристик или плана видов расчета должно быть установлено значение Авто (по умолчанию), а также не следует допускать программных вызовов метода УстановитьОбновлениеПредопределенныхДанных этих объектов для переключения этого режима.
  • запретить удаление предопределенных элементов пользователями, выключив во всех ролях следующие права (по умолчанию выключены):
    • ИнтерактивноеУдалениеПредопределенныхДанных
    • ИнтерактивнаяПометкаУдаленияПредопределенныхДанных
    • ИнтерактивноеСнятиеПометкиУдаленияПредопределенныхДанных
    • ИнтерактивноеУдалениеПомеченныхПредопределенныхДанных

1.3. Исключение составляют дочерние узлы РИБ, в котором предопределенные элементы автоматически не создаются (и не обновляются при изменении в метаданных), а должны быть переданы из главного узла вместе с изменениями конфигурации.

При этом:

а) конфигурация должна обеспечивать загрузку сообщения обмена в подчиненный узел РИБ до выполнения другого прикладного кода, который обращается к получаемым из главного узла предопределенным элементам;

б) в прикладной логике загрузки данных из главного узла (обработчик события ПриПолученииДанныхОтГлавного , правила регистрации объектов) следует избегать обращений к предопределенным элементам, поскольку нет гарантии, что они уже были загружены из сообщения обмена;

в) код обработчиков обновления ИБ, который обрабатывает предопределенные элементы, не должен выполняться в подчиненных узлах РИБ:

Если ПланыОбмена. ГлавныйУзел() = Неопределенно Тогда // заполняем предопределенные элементы // ... КонецЕсли ;

При использовании в конфигурации подсистемы "Обмен данными" Библиотеки стандартных подсистем (БСП) версии 2.1.4 и выше требования (а) и (б) снимаются.

1.4. Для таблиц с предопределенными элементами, которые не входят в состав плана обмена РИБ (и на которые не ссылаются другие таблицы, входящие в состав плана обмена РИБ) рекомендуется устанавливать свойство ОбновлениеПредопределенныхДанных в значение ОбновлятьАвтоматически , а также при первом запуске подчиненного узла РИБ устанавливать автоматическое обновление в данных с помощью вызова:

Справочники. ИмяСправочника> . УстановитьОбновлениеПредопределенныхДанных(ОбновлениеПредопределенныхДанных. ОбновлятьАвтоматически) ;

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

Например, те или иные предопределенные виды расчетов в плане видов расчета Начисления зависят от значений функциональных опций ИспользоватьУчетВремениСотрудниковВЧасах , ИспользоватьСдельныйЗаработок и др.

Для этого

  • в свойстве ОбновлениеПредопределенныхДанных справочника, плана счетов, плана видов характеристик или плана видов расчета нужно установить в значение "Не обновлять автоматически"
  • предусмотреть код создания (и пометки недействительным) предопределенного элемента в зависимости от бизнес-логики, например:
Если ПолучитьФункциональнуюОпцию("ИспользоватьУчетВремениСотрудниковВЧасах" ) Тогда НачислениеОбъект = ПланыВидовРасчета. Начисления. СоздатьВидРасчета() ; НачислениеОбъект. ИмяПредопределенныхДанных = "ОкладПоЧасам" ; // ... НачислениеОбъект. Записать() ; КонецЕсли ;
  • учитывать в прикладном коде отсутствие предопределенных элементов в ИБ. В противном случае, при обращении к несуществующему предопределенному элементу из кода или текста запроса будет вызвано исключение:
. . . = ПланВидовРасчета. Начисления. ОкладПоЧасам; . . . = ПредопределенноеЗначение("ПланВидовРасчета.Начисления.ОкладПоЧасам" ) ;

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

При работе на платформе 1С:Предприятие 8.x часто возникает необходимость привязаться в программном коде к обычным (не предопределенным) элементам справочников. Например у организации может быть пять видов цен, которые используются практически во всех механизмах. При этом программное обращение к конкретной цене в лучшем случае осуществляется либо писком по коду в справочнике, в худшем по наименованию элемента.

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

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

К тому же, если привязываться к наименованию или коду элементов справочника, то при получении ссылки на элемент всегда будет осуществляться поиска в таблице справочника. Не смотря на то, что стандартные реквизиты системы индексируются СУБД, поиск по ним в некоторых случаях может занимать значительные ресурсы. К тому же, рациональнее было бы не выполнять поисковой запрос по таблице справочника, если, скажем так, ссылка на элемент и так "заранее известна".

Как выход, можно хранить ссылку на каждый часто используемый элемент справочника "Типы цен номенклатуры" в отдельных константах и получать из них значения в запросе. Однако, в таком случае разработчику придется добавлять отдельную константу для каждого подобного элемента. Ситуация значительно усложнится, если такие элементы будут не только в справочнике "Типы цен номенклатуры", но и в других справочниках ("Категории объектов", "Качество", "Номенклатура" и другие). Тогда количество констант в системе может увеличиться в несколько раз!

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

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

Универсальное решение

Суть универсального решения будет заключаться в следующем: будет создан справочник, в который разработчиком будут добавляться предопределенные элементы. В справочник добавлен реквизит "Значение", тип которого зависит от значений, для которых будет создаваться соответствие "Предопределенный элемент справочника -> Связанной значение". Структура метаданных справочника выглядит следующем образом (см. следующий скриншот).

Для получения предопределенного элемента наилучшим вариантом является использование глобального метода "ПредопределенноеЗначение(<Имя>)" . В качестве параметра в метод передается полный путь к предопределенному элементу. Синтаксис похож на функцию языка запросов "ЗНАЧЕНИЕ()" .

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

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

Влияние на производительность

Проводил тест на скорость для обоих вариантов поиска: по наименованию и по ссылке из предопределенного элемента. Поиск проходил по справочнику "Товары" с 20000 записей. При проведении тестов на файловой базе были получены следующие результаты:

Результаты показали, что для файлового варианта работы использование предопределенных элементов для получения часто используемых элементов других справочников работает медленнее практически в 4 раза!

В клиент-серверном варианте работы результаты тестов показывают совсем другую картину. Скорость получения ссылка на нужный элемент не снизилась значительно (один из тестов показал 0.002 сек. для поиска по наименованию и 0.0008 сек. при работе через предопределенный элемент), однако надежность работы программы увеличилась в разы!

Выводы

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

За время работы с платформой не раз встречался с ситуациям, когда после изменения наименования, например у элемента справочника "ТипыЦенНоменклатуры", слетала работа у большинства не типовых отчетов.

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

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

Файлы для загрузки:

  1. Выгрузка тестовой базы с примерами из статьи.

Печать (Ctrl+P)

Работа с предопределенными значениями с помощью менеджера объекта

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

ТипПредопределенногоЗначения.ИмяОбъектаМетаданных.Значение


ТипПредопределенногоЗначения – для получения предопределенных значений доступно указание следующих типов данных (написание во
множественном числе):
● Справочники,
● ПланыВидовХарактеристик,
● ПланыСчетов,
● ПланыВидовРасчета,
● Перечисления.
ИмяОбъектаМетаданных

● Значение – может быть одним из следующих:
● для перечислений указывается имя значения перечисления;

● ТочкиМаршрута.ИмяТочки – точка маршрута бизнес-процесса.
В случае, если требуется получить точку маршрута бизнес-процесса, строка, описывающая получаемое значение, будет выглядеть следующим образом:

БизнесПроцессы.ИмяОбъектаМетаданных.ТочкиМаршрута.ИмяТочкиМаршрута
Пример:


Вид = Перечисления.ВидыТоваров.Товар;
// Получение предопределенных данных справочника.
Элемент = Справочники.Валюта.Рубль;
// Точка маршрута бизнес-процесса
Точка = БизнесПроцесс.Согласование.ТочкиМаршрута.Одобрение;

Работа с предопределенными значениями С помощью функции ПредопределенноеЗначение()

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

Рассмотрим составляющие этой строки подробнее:
ТипПредопределенногоЗначения – для получения предопределенных значений доступно указание следующих типов данных (написание в
единственном числе):
● Справочник ,
ПланВидовХарактеристик ,
● ПланСчетов ,
ПланВидовРасчета ,
● Перечисление,
● БизнесПроцесс .
● ИмяОбъектаМетаданных – указывается имя объекта метаданных так, как оно задано в конфигураторе.
● Значение – может быть одним из следующих

● для перечислений указывается имя значения перечисления;
● для получения предопределенного значения указывается его имя, как оно задано в конфигураторе;
● ТочкаМаршрута.ИмяТочки – точка маршрута бизнес-процесса;
● ПустаяСсылка – для получения пустой ссылки.
В случае необходимости получить значение системного перечисления параметр метода будет выглядеть следующим образом:
ИмяСистемногоПеречисления.ЗначениеСистемногоПеречисления.
Например:

ТипДиаграммы = ПредопределенноеЗначение(“ТипДиаграммы.ВогнутаяПоверхность “);
В случае если требуется получить точку маршрута бизнес-процесса, строка, описывающая получаемое значение, будет выглядеть следующим образом:
Пример:

// Получение значения перечисления.
Вид = ПредопределенноеЗначение (“Перечисление.ВидыТоваров.Товар”);
// Получение значения пустой ссылки.
ПустаяСсылка =
ПредопределенноеЗначение (“Документ.РасходнаяНакл.ПустаяСсылка”);
// Получение предопределенных данных справочника.
Элемент = ПредопределенноеЗначение (“Справочник.Валюта.Рубль”);
// Точка маршрута бизнес-процесса
Точка = ПредопределенноеЗначение (“БизнесПроцесс.Согласование. ТочкаМаршрута.Одобрение”);