Как программно получить список документов-регистраторов для регистров в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

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

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

  1. Запрос работает только с фактическими данными: если в базе еще нет проведенных документов конкретного вида или по ним не формировались движения, запрос не вернет такой тип документа.
  2. Метаданные не хранятся в таблицах ИБ: состав регистраторов настраивается в дереве конфигурации, поэтому анализировать допустимые типы необходимо исключительно через объектную модель метаданных.

Способ 1. Получение регистраторов через стандартный реквизит регистра

Рассмотрим основной способ решения задачи. У каждого регистра накопления, бухгалтерии, расчета, а также регистра сведений подчиненного типа существует стандартный реквизит Регистратор. Через свойства метаданных мы можем получить его описание типов, извлечь массив типов данных и затем сопоставить их с объектами метаданных документов.

Разберем по шагам реализацию функции, которая принимает массив или список метаданных регистров и возвращает массив метаданных документов-регистраторов:


&НаСервере
Функция ПолучитьМассивДокументовРегистраторов(СписокРегистров)
    
    Результат = Новый Соответствие;
    
    Для Каждого МетаРегистр Из СписокРегистров Цикл
        
        // Проверяем наличие стандартного реквизита Регистратор
        РеквизитРегистратор = МетаРегистр.СтандартныеРеквизиты.Найти("Регистратор");
        Если РеквизитРегистратор = Неопределено Тогда
            Продолжить;
        КонецЕсли;
        
        // Извлекаем массив допустимых типов
        МассивТипов = РеквизитРегистратор.Тип.Типы();
        Для Каждого ТекущийТип Из МассивТипов Цикл
            
            // Находим метаданные документа по типу ссылки
            МетаДокумент = Метаданные.НайтиПоТипу(ТекущийТип);
            Если МетаДокумент <> Неопределено Тогда
                Результат.Вставить(МетаДокумент, Истина);
            КонецЕсли;
            
        КонецЦикла;
        
    КонецЦикла;
    
    // Преобразуем ключи соответствия в массив для исключения дублей
    МассивДокументов = Новый Массив;
    Для Каждого КлючИЗначение Из Результат Цикл
        МассивДокументов.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;
    
    Возврат МассивДокументов;
    
КонецФункции

Посмотрим на важный нюанс: свойство Типы() возвращает системные значения с типом Тип (например, Тип("ДокументСсылка.ПриходнаяНакладная")). Чтобы получить имя, синоним или сам объект метаданных, мы применяем метод Метаданные.НайтиПоТипу(ТекущийТип). Использование коллекции Соответствие позволяет автоматически исключить дублирование документов, если один и тот же документ является регистратором для нескольких регистров из переданного списка.

Способ 2. Обратная проверка через коллекцию «Движения» документов

Проанализируем альтернативный подход: вместо разбора типов у каждого регистра мы можем обойти коллекцию всех документов конфигурации и проверить, входит ли целевой регистр в состав движений документа. У каждого объекта ОбъектМетаданных: Документ есть коллекция Движения, содержащая метаданные регистров.

Рассмотрим пример кода, реализующий такую логику:


&НаСервере
Функция НайтиДокументыПоДвижениям(ЦелевойРегистр)
    
    СписокДокументов = Новый Массив;
    
    Для Каждого МетаДокумент Из Метаданные.Документы Цикл
        
        // Проверяем, может ли документ двигать указанный регистр
        Если МетаДокумент.Движения.Содержит(ЦелевойРегистр) Тогда
            СписокДокументов.Добавить(МетаДокумент);
        КонецЕсли;
        
    КонецЦикла;
    
    Возврат СписокДокументов;
    
КонецФункции

Этот метод удобен тем, что работает напрямую с объектами метаданных без необходимости преобразовывать типы через Метаданные.НайтиПоТипу().

Особенности работы с различными видами регистров

При реализации универсального алгоритма обязательно учтем особенности структуры метаданных платформы 1С:

  1. Регистры сведений: реквизит Регистратор присутствует только у тех регистров сведений, у которых свойство РежимЗаписи установлено в значение РежимЗаписиРегистраСведений.ПодчинениеРегистратору. У независимых регистров сведений попытка прямого обращения к реквизиту Регистратор вызовет исключение.
  2. Регистры накопления, бухгалтерии и расчета: всегда подчинены регистратору, поэтому свойство СтандартныеРеквизиты.Регистратор доступно у них безусловно.

Как автоматически отобрать группу нетиповых регистров

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

  1. Использование отдельной подсистемы: выделим все добавленные при доработке регистры в специальную служебную подсистему. Программный обход в таком случае выполняется по коллекции Метаданные.Подсистемы.ИмяПодсистемы.Состав.
  2. Фильтрация по префиксу: если в компании принят стандарт разработки с префиксами для нетиповых объектов (например, бит_ или мп_), обойдем метаданные регистров в цикле и проверим вхождение префикса в свойство Имя:
    
    Для Каждого МетаРег Из Метаданные.РегистрыНакопления Цикл
        Если СтрНачинаетсяС(МетаРег.Имя, "бит_") Тогда
            // Обрабатываем нетиповой регистр
        КонецЕсли;
    КонецЦикла;
    

Важное замечание: наличие документа в списке регистраторов регистра в метаданных означает лишь потенциальную возможность формировать движения. Фактическое создание записей управляется программным кодом в модуле объекта документа (событие ОбработкаПроведения) либо в общих обработчиках подписок на события. Если цель анализа — отследить влияние типового обновления на алгоритмы проведения, рекомендуется также проверить состав объектов метаданных Метаданные.ПодпискиНаСобытия.

← На главную