Как исправить ошибку при выгрузке данных и проверке метаданных объекта в событиях конвертации 1С?

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

При выгрузке обмена данными через механизмы конвертации данных (КД 2.0 / Универсальный обмен данными XML) часто возникает необходимость отфильтровать выгружаемые объекты по определенному условию — например, по подразделению или организации. Попытка написать универсальный код фильтрации в глобальном или локальном обработчике ПередКонвертациейОбъекта может привести к сбою выгрузки с различными ошибками.

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

Причины возникновения ошибок в обработчиках конвертации

Проанализируем две наиболее частые ошибки, возникающие при попытке получить реквизиты объекта через параметр Источник в событии ПередКонвертациейОбъекта:

  1. Ошибка «Поле объекта не обнаружено (Реквизиты)». Возникает при вызове Источник.Метаданные().Реквизиты, когда в качестве источника выступает ссылочный тип перечисления (ПеречислениеСсылка). Метод Метаданные() у перечисления возвращает объект метаданных, но у него нет коллекции Реквизиты (вместо неё используется коллекция ЗначенияПеречисления).
  2. Ошибка «Метод объекта не обнаружено (Метаданные)». Возникает при попытке вызвать метод .Метаданные() у объектов, которые не поддерживают этот метод напрямую. Например, запись регистра сведений (РегистрСведенийЗапись), ключ записи регистра или значение примитивного типа (Строка, Число, Дата, Структура), передаваемое в конвертацию.

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

Способ 1. Безопасная проверка типа через коллекции метаданных

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

Рассмотрим пример кода в обработчике ПередКонвертациейОбъекта:


ПодразделениеФильтр = Справочники.ПодразделенияОрганизаций.НайтиПоКоду("СВ0000028");

// Получаем объект метаданных по типу выгружаемого источника
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(Источник));

Если ОбъектМД <> Неопределено Тогда
    
    // Проверяем, что выгружаемый объект является документом
    Если Метаданные.Документы.Содержит(ОбъектМД) Тогда
        
        // Безопасно проверяем наличие реквизита в метаданных документа
        ИмяРеквизита = "";
        Если ОбъектМД.Реквизиты.Найти("Подразделение") <> Неопределено Тогда
            ИмяРеквизита = "Подразделение";
        ИначеЕсли ОбъектМД.Реквизиты.Найти("РК_ПодразделениеОрганизации") <> Неопределено Тогда
            ИмяРеквизита = "РК_ПодразделениеОрганизации";
        КонецЕсли;
        
        Если ЗначениеЗаполнено(ИмяРеквизита) Тогда
            ЗначениеПодразделения = Источник[ИмяРеквизита];
            
            Если ЗначениеЗаполнено(ЗначениеПодразделения) Тогда
                Если НЕ (ЗначениеПодразделения.ПринадлежитЭлементу(ПодразделениеФильтр) 
                    ИЛИ ЗначениеПодразделения = ПодразделениеФильтр) Тогда
                    
                    // Отменяем выгрузку данного документа
                    Отказ = Истина;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
        
    КонецЕсли;
    
КонецЕсли;

Способ 2. Проверка принадлежности типа через коллекцию типов ссылок

Альтернативный подход заключается в использовании метода СодержитТип() у системных типов ссылок. Это позволяет в одну строку определить, относится ли параметр Источник к документам или справочникам.

Разберем пример такой проверки:


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

КонецЕсли;

Особенности применения `Отказ = Истина` в обработчиках конвертации

При отмене выгрузки объектов с помощью установки флага Отказ = Истина в событиях правил конвертации объектов (ПКО) важно учитывать следующие нюансы работы механизмов 1С:

Рекомендации по архитектуре отбора данных

Для более чистой и производительной настройки обменов рекомендуется выполнять фильтрацию на следующих уровнях:

  1. На этапе выборки в ПВД (Правилах выгрузки данных): Вместо отсечения объектов на этапе конвертации напишите запрос в ПВД, выбирающий только нужные документы по подразделению. Это ускоряет обмен, так как лишние объекты даже не считываются платформой.
  2. В Правилах регистрации объектов (ПРО): При использовании планов обмена настраивайте фильтрацию по подразделению непосредственно в правилах регистрации. Документы сторонних подразделений не будут попадать в таблицу изменений плана обмена, снижая нагрузку на систему.
← На главную