Как исправить ошибку «Метод объекта не обнаружен (Метаданные)» при загрузке данных через Конвертацию данных

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

При организации обмена данными между конфигурациями 1С:Предприятие (например, при переносе данных из «Управление торговлей 10.3» в «Бухгалтерия предприятия 2.0») разработчики часто используют правила, созданные в конфигурации «Конвертация данных 2.1». В процессе доработки типовых правил под нужды бизнеса легко допустить архитектурную ошибку в глобальных обработчиках событий. Одна из самых частых и неприятных ошибок на этапе импорта — «Метод объекта не обнаружен (Метаданные)» в событии ПослеЗагрузкиОбъекта.

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

Выясняем причину технического сбоя

Для начала проанализируем текст ошибки, с которой сталкивается пользователь при импорте XML-файла:

Ошибка в глобальном обработчике события ПослеЗагрузкиОбъекта (конвертация) ИмяПКО = КонтактнаяИнформация ТипОбъекта = Регистр сведений запись: Контактная информация Объект = РегистрСведенийМенеджерЗаписи.КонтактнаяИнформация Обработчик = ПослеЗагрузкиОбъекта (глобальный) ОписаниеОшибки = Метод объекта не обнаружен (Метаданные)

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

Для документов и справочников переменная Объект принимает тип ДокументОбъект.[ИмяДокумента] или СправочникОбъект.[ИмяСправочника] соответственно. У этих типов в платформе 1С существует встроенный метод Метаданные(), который возвращает объект описания метаданных конфигурации.

Однако при загрузке независимого регистра сведений (в нашем случае это регистр «Контактная информация») система оперирует объектом типа РегистрСведенийМенеджерЗаписи.КонтактнаяИнформация. У этого типа данных в платформе 1С отсутствует метод Метаданные(). Попытка вызвать этот метод у менеджера записи регистра закономерно приводит к аварийному завершению работы обработчика импорта.

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

МетаданныеДокумента = Объект.Объект.Метаданные;

Проанализируем это выражение. У документов нет реквизита Объект, поэтому для них эта строка вызовет ошибку обращения к несуществующему свойству. А вот у регистра сведений «Контактная информация» есть ключевое измерение Объект (в котором хранится ссылка на контрагента или физическое лицо). При импорте записи регистра выражение Объект.Объект вернет ссылку на элемент справочника (например, СправочникСсылка.Контрагенты). Но у ссылочных типов (в отличие от объектных) нет прямого свойства Метаданные, из-за чего система также выдаст ошибку.

Анализ исходного кода обработчика

Рассмотрим структуру типового кода, который часто пишется для автоматического заполнения реквизитов (например, организации, склада или подразделения) при загрузке документов:


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

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

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

Решение 1. Фильтрация по типу объекта через проверку типа (Рекомендуемое решение)

Наиболее надежный и правильный с точки зрения архитектуры 1С способ — это явная проверка типа загружаемого объекта. Мы должны убедиться, что обрабатываемый объект относится к классу документов, прежде чем обращаться к его методам. Реализуем это с помощью анализа строкового представления типа значения.

Посмотрим на пример безопасного кода:


// Получаем строковое представление типа загруженного объекта
ТипОбъектаСтрокой = Строка(ТипЗнч(Объект));

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

КонецЕсли;

Этот способ является максимально быстрым, так как строковые операции в памяти выполняются мгновенно, и мы полностью избегаем вызова тяжелых или неподдерживаемых методов платформы для неподходящих типов данных.

Решение 2. Использование системных переменных Конвертации данных

В самой конфигурации «Конвертация данных» при выполнении обработчиков событий доступен ряд предопределенных параметров и переменных. Одна из таких полезных переменных — ИмяТипаОбъекта. Она хранит строковое обозначение базового метакласса (например, "Документ", "Справочник", "РегистрСведений").

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


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

Использование встроенной переменной ИмяТипаОбъекта избавляет от необходимости вручную вычислять тип через ТипЗнч и преобразовывать его в строку, что делает код более понятным и чистым.

Решение 3. Локализация ошибки через блок Попытка...Исключение

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

Посмотрим на пример правильного, точечного использования конструкции:


МетаданныеДокумента = Неопределено;
ДанныеКорректны = Истина;

Попытка
    // Пытаемся получить метаданные объекта. 
    // Если объект не поддерживает этот метод, управление передается в блок Исключение.
    МетаданныеДокумента = Объект.Метаданные();
Исключение
    ДанныеКорректны = Ложь;
КонецПопытки;

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

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

Пошаговый план по исправлению правил в Конвертации данных

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

  1. Откройте конфигурацию «Конвертация данных» (версия 2.1) и загрузите туда ваши текущие правила обмена (файл правил XML).
  2. Перейдите на вкладку «Параметры конвертации» или откройте настройки непосредственно вашей конвертации.
  3. Найдите вкладку «Глобальные обработчики» и выберите событие ПослеЗагрузкиОбъекта.
  4. Найдите фрагмент кода, где происходит обращение к методу Метаданные() (как в нашем примере из сообщения 7).
  5. Оберните этот фрагмент кода в проверку типа (как показано в Решении 1 или Решении 2).
  6. Сохраните изменения в правилах конвертации и выгрузите обновленный XML-файл правил.
  7. Загрузите новые правила в базу-приемник (в нашем случае — «Бухгалтерия предприятия 2.0») через обработку «Универсальный обмен данными в формате XML» или обновите их в настройках узла обмена данными.
  8. Запустите повторную загрузку данных и убедитесь, что ошибка пропала, а все документы и контактная информация успешно загрузились в информационную базу.

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

← На главную