Как исправить ошибку «Значение не является значением объектного типа» в обработчике ПослеЗагрузкиОбъекта

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

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

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

Причина ошибки при обращении к коллекции ПараметрыОбъекта

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

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

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

Исправление кода и безопасная проверка параметров

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


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

Критическая ошибка: чтение и запись набора записей без отбора

В исходном обработчике присутствует опасная конструкция работы с регистром сведений ДокументыФизическихЛиц:


Набор = РегистрыСведений.ДокументыФизическихЛиц.СоздатьНаборЗаписей();
Набор.Прочитать();
НовЗапись = Набор.Добавить();
...
Набор.Записать();

Выясним причину опасности этого кода:

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

Вариант 1. Запись через СоздатьНаборЗаписей с установкой отбора

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


Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда
    Объект.Записать();
КонецЕсли;

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

Вариант 2. Использование Менеджера записи

Для независимых периодических и непериодических регистров сведений наиболее компактным и надежным решением является использование СоздатьМенеджерЗаписи(). Он работает точечно с одной записью по ключевым полям:


Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда
    Объект.Записать();
КонецЕсли;

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

Как включить отладку обработчиков в Универсальном обмене

Чтобы детально изучить состав коллекций в момент загрузки данных:

  1. Откроем обработку Универсальный обмен данными в формате XML на вкладке загрузки данных.
  2. Установим флаг Режим отладки обработчиков (или сформируем внешний файл отладки обработчиков через соответствующую настройку).
  3. Подключимся конфигуратором 1С к сеансу и установим точку останова внутри сгенерированного модуля или алгоритма. Это позволит в окне табло просмотреть тип и состав переменной ПараметрыОбъекта.

Архитектурная рекомендация

Ручное создание записей в обработчиках загрузки считается временным решением. В конфигурации Конвертация данных рекомендуется создать отдельное Правило конвертации объектов (ПКО) для регистра сведений ДокументыФизическихЛиц и вызывать его при выгрузке физлица через функцию ВыгрузитьПоПравилу(). Это обеспечит стандартную обработку транзакций и предотвратит дублирование логики записи.

← На главную