Как проверить заполненность реквизита в КД 2.0 и избежать ошибки «ИмяТипа»

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

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

Выясняем причину ошибки: почему «не канает» ЗначениеЗаполнено()?

На первый взгляд, код проверки выглядит абсолютно стандартно для платформы 1С. Разработчики пишут в обработчике ПКС (Правила конвертации свойств) следующий алгоритм:


Если ЗначениеЗаполнено(ОбъектКоллекции.Номенклатура.СчетУчетаМатериалов) Тогда
    Значение = ОбъектКоллекции.Номенклатура.СчетУчетаМатериалов.Код;
Иначе
    Если ОбъектКоллекции.Номенклатура.ТипНоменклатуры.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Товар Тогда
        Значение = "41.01";
    Иначе
        Значение = "10.09";
    КонецЕсли;
КонецЕсли;

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

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

Проанализируем работу XML-парсера во время загрузки данных в обработке УниверсальныйОбменДаннымиXML. Когда мы передаем в ПКС для ссылочного реквизита (например, счета учета) обычную строку (код счета "41.01" или "10.09"), выгружатель формирует узел свойства в XML-файле. При загрузке этого узла система видит, что для свойства назначено определенное ПКО (Правило конвертации объектов). Она пытается обработать переданное строковое значение как ссылку, выполняя следующий код в модуле обмена:


СтруктураСвойств = Менеджеры[ТипОбъекта];
ИмяТипаОбъекта = СтруктураСвойств.ИмяТипа;

Так как переданное значение является строкой, переменная ТипОбъекта принимает значение "Строка". Попытка получить менеджер для типа Строка (выражение Менеджеры["Строка"]) возвращает Неопределено. В результате обращение к свойству .ИмяТипа у объекта Неопределено вызывает критическую ошибку «Значение не является значением объектного типа (ИмяТипа)». Таким образом, ошибка происходит на этапе загрузки из-за несоответствия типов данных.

Дополнительно в исходном коде кроется еще одна опасность — разыменование пустых ссылок (обращение «через точку»). Если у номенклатуры не будет заполнен реквизит ТипНоменклатуры, то обращение к ТипНоменклатуры.ВидНоменклатуры вызовет аналогичную ошибку объектного типа еще на этапе выгрузки.

---

Вариант А. Передача ссылки вместо строки (Рекомендуемый способ)

Самый простой и методологически верный способ — передавать в переменную Значение не строковый код счета, а полноценную ссылку на объект базы данных источника. В этом случае КД сама выгрузит объект по правилу конвертации, а при загрузке сопоставит его по коду.

Рассмотрим безопасный вариант написания кода с предварительными проверками на заполненность всех уровней ссылок:


// Безопасно проверяем заполненность номенклатуры
Если ЗначениеЗаполнено(ОбъектКоллекции.Номенклатура) Тогда
    
    // Проверяем заполненность счета учета в источнике
    Если ЗначениеЗаполнено(ОбъектКоллекции.Номенклатура.СчетУчетаMaterials) Тогда
        Значение = ОбъектКоллекции.Номенклатура.СчетУчетаMaterials; // Передаем ССЫЛКУ, а не код
    Иначе
        // Если счет не заполнен, находим нужную ссылку в источнике по коду
        Если ЗначениеЗаполнено(ОбъектКоллекции.Номенклатура.ТипНоменклатуры) 
           И ОбъектКоллекции.Номенклатура.ТипНоменклатуры.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Товар Тогда
            Значение = ПланыСчетов.Хозрасчетный.НайтиПоКоду("41.01");
        Иначе
            Значение = ПланыСчетов.Хозрасчетный.НайтиПоКоду("10.09");
        КонецЕсли;
    КонецЕсли;
    
КонецЕсли;

---

Вариант Б. Настройка выгрузки по коду без источника

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

  1. Откройте настройки ПКС в конвертации свойств.
  2. Оставьте поле «Источник» пустым (выгрузка без источника).
  3. В поле «Приемник» укажите реквизит (например, СчетУчета).
  4. Укажите соответствующее ПКО для поиска счетов (например, Хозрасчетный).
  5. В обработчике «Перед выгрузкой» этого ПКС напишите код, возвращающий строку:

Если ЗначениеЗаполнено(ОбъектКоллекции.Номенклатура.СчетУчетаМатериалов) Тогда
    Значение = ОбъектКоллекции.Номенклатура.СчетУчетаМатериалов.Код;
Иначе
    // Ваша логика определения кода по умолчанию
    Значение = "41.01"; 
КонецЕсли;

Важное условие: В самом ПКО (в нашем примере это Хозрасчетный) для свойства Код обязательно должен стоять флаг «Поиск». При загрузке система получит строку, поймет, что это значение предназначено для идентификации объекта, и успешно найдет счет в базе-приемнике по этому коду.

---

Вариант В. Динамическое переопределение ПКО

Если тип выгружаемого значения может меняться динамически (в одном случае передается ссылка, а в другом — строка для поиска), мы можем принудительно указать системе, какое правило конвертации использовать для обработки этого значения.

Для этого в обработчике ПередВыгрузкой ПКС используется специальная переменная ИмяПКО:


Значение = "41.01";
ИмяПКО = "ХозрасчетныйПоКоду"; // Указываем имя ПКО, которое умеет обрабатывать строковые значения

Использование этого механизма гарантирует, что XML-парсер при загрузке не обратится к несуществующему менеджеру типа Строка, а сразу передаст управление указанному правилу конвертации объектов.

← На главную