При разработке универсальных механизмов, обработок переноса данных или процедур группового перепроведения документов часто возникает задача программно выяснить: связан ли конкретный регистр с документом-регистратором или же он может записываться независимо. Разберем особенности платформы 1С:Предприятие при работе с метаданными регистров, типичные ошибки разработчиков и несколько корректных способов решения этой задачи.
Прежде чем приступать к написанию программного кода, проанализируем структуру регистров платформы 1С:Предприятие:
РежимЗаписи у таких регистров вызовет исключение «Поле агрегатного объекта не обнаружено».РежимЗаписи.Таким образом, если перед нами регистр накопления, бухгалтерии или расчета — он гарантированно подчинен регистратору. Основная задача проверки сводится к анализу регистров сведений либо к созданию универсального алгоритма для произвольного объекта метаданных.
Рассмотрим самый распространенный случай, когда мы работаем с объектом метаданных регистра сведений. Обратите внимание на важную тонкость: системное перечисление РежимЗаписиРегистра недоступно напрямую в глобальном контексте платформы. Обращение к его значениям должно выполняться строго через ветку Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.
Посмотрим на пример правильной проверки:
Если Метаданное.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору Тогда
// Регистр сведений подчинен регистратору
Подчинен = Истина;
Иначе
// Регистр сведений является независимым
Подчинен = Ложь;
КонецЕсли;
Чтобы избежать ошибок при анализе имени метаданного через строковые функции (например, через Лев() или ПолноеИмя()), правильнее использовать проверку на принадлежность к коллекции метаданных с помощью метода Содержит():
Если Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
Если ОбъектМетаданных.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору Тогда
// Обработка подчиненного регистра сведений
КонецЕсли;
КонецЕсли;
Разберем ситуацию, когда на вход функции подается совершенно произвольный объект описания метаданных, и нам нужно точно сказать, подчинен ли он регистратору. Объединим проверку видов регистров и анализ свойства РежимЗаписи:
Функция РегистрПодчиненРегистратору(ОбъектМетаданных) Экспорт
Если Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных)
Или Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных)
Или Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
Возврат Истина;
ИначеЕсли Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
Возврат ОбъектМетаданных.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору;
КонецЕсли;
Возврат Ложь;
КонецФункции
Этот метод безопасен, так как проверяет тип объекта метаданных перед обращением к специфическим свойствам и исключает возникновение непредвиденных ошибок времени выполнения.
Часто программисты пытаются проверить подчиненность через коллекцию СтандартныеРеквизиты, обращаясь напрямую: ОбъектМетаданных.СтандартныеРеквизиты.Регистратор. Разберем, почему этот подход требует осторожности.
Коллекция СтандартныеРеквизиты не содержит методов Найти() или Содержит(), а прямое обращение по точке к свойству Регистратор у независимого регистра сведений сразу вызывает фатальную ошибку. Однако обойти эту коллекцию циклом — вполне допустимый универсальный прием:
ПодчиненРегистратору = Ложь;
Для Каждого СтандартныйРеквизит Из ОбъектМетаданных.СтандартныеРеквизиты Цикл
Если СтандартныйРеквизит.Имя = "Регистратор" Тогда
ПодчиненРегистратору = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если в коллекции стандартных реквизитов присутствует реквизит Регистратор, значит, данный объект метаданных гарантированно подчинен регистратору.
Если установлено, что регистр подчинен регистратору, следующей задачей обычно становится выяснение списка документов, которые могут делать в него записи. Чтобы не перебирать все документы конфигурации и их коллекции Движения, достаточно получить типы документов напрямую из реквизита Регистратор:
Если РегистрПодчиненРегистратору(ОбъектМетаданных) Тогда
МассивТиповРегистратора = ОбъектМетаданных.СтандартныеРеквизиты.Регистратор.Тип.Типы();
Для Каждого ТекущийТип Из МассивТиповРегистратора Цикл
МетаданныеДокумента = Метаданные.НайтиПоТипу(ТекущийТип);
Если МетаданныеДокумента <> Неопределено Тогда
// Получили объект метаданных документа-регистратора
КонецЕсли;
КонецЦикла;
КонецЕсли;
Такой подход работает быстрее полного перебора дерева конфигурации и обеспечивает надежный результат при работе с любыми прикладными решениями.