Как решить проблему с переносом перечислений при конвертации данных из 1С 8.1 в 1С 8.3?

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

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

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

Анализ технической стороны проблемы и текста ошибки

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


Ссылка на несуществующий объект метаданных в правилах обмена
    Объект                 =  Статус заявки
    ОписаниеОшибки         =  Значение не является значением объектного типа (ПКО)
    ПозицияМодуля          =  ВнешняяОбработка.УниверсальныйОбменДаннымиXML.МодульОбъекта(2175)
    КодСообщения           =  11
 Начало выгрузки:   16.10.2019 13:36:39
 Не найдено соответствие для значения Источника
    Источник               =  Зарегистрирована
    ТипИсточника           =  Статус заявки

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

В модуле обработки это выглядит следующим образом: выполняется обращение к внутренней структуре (соответствию) менеджеров типов:

ПКОСвойств = Менеджеры[ТипЗначения].ПКО;

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

Почему происходит сбой для объекта «Статус заявки»?

Обратим внимание на строку лога: Объект = Статус заявки. В платформе «1С:Предприятие» имена объектов метаданных принципиально не могут содержать пробелов. Правильное имя должно выглядеть как СтатусЗаявки или СтатусыЗаявок. Наличие пробела однозначно указывает на одну из двух системных ошибок:

  1. Использование синонима вместо имени: При выгрузке метаданных из баз-источников (особенно на платформе 8.1 с использованием старых версий обработки MD81Exp.epf) в XML-файл описания конфигурации вместо уникального имени (Name) мог записаться синоним (Synonym) объекта метаданных.
  2. Различия версий обработок выгрузки: Обработка для платформы 8.1 выгрузила перечисление по старому формату идентификации, а обработка для платформы 8.3 — по новому. Из-за этого в самой конфигурации «Конвертация данных 2.1» типы данных не сопоставились корректно.

Анализ временного «костыля» (почему он сработал?)

Для быстрого решения проблемы разработчики часто прибегают к обходным путям. Например, удаляют ПКО для перечисления и ПКС для реквизита, а в обработчике события «Перед выгрузкой» свойства прописывают код напрямую:


Если Источник.СтатусЗаявки = Перечисления.СтатусыЗаявок.Закрыта Тогда
    Значение = "Закрыта";
ИначеЕсли Источник.СтатусЗаявки = Перечисления.СтатусыЗаявок.Запланирована Тогда
    Значение = "Запланирована";
ИначеЕсли Источник.СтатусЗаявки = Перечисления.СтатусыЗаявок.Ошибочная Тогда
    Значение = "Ошибочная";
КонецЕсли;

Проанализируем, почему этот код успешно работает. Когда мы очищаем ПКО для свойства и вручную присваиваем переменной Значение текстовую строку, КД выгружает это свойство в XML-файл как простой тип «Строка». При загрузке в базу-приемник XML-анализатор видит строковое представление значения. Если тип принимающего реквизита в 1С 8.3 — ПеречислениеСсылка, платформа автоматически пытается сопоставить полученную строку с именем значения перечисления в конфигурации-приемнике. Если имена совпадают, значение заполняется успешно.

Главный минус такого подхода — это «жесткое кодирование» (хардкод). При добавлении нового статуса перечисления в конфигурацию обмен перестанет корректно переносить это значение до тех пор, пока программист вручную не допишет очередное условие ИначеЕсли в код правил.

Системные способы решения проблемы

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

Способ А. Исправление и синхронизация метаданных (Рекомендуемый метод)

Этот способ устраняет первопричину сбоя — расхождение в описании типов конфигураций источника и приемника в самой «Конвертации данных».

  1. Откройте конфигуратор базы 1С 8.1 и базы 1С 8.3. Убедитесь, что у перечисления СтатусЗаявки свойство «Имя» (не синоним!) совпадает в обеих конфигурациях и не содержит пробелов.
  2. Выполните повторную выгрузку метаданных обеих баз. Используйте строго актуальные версии обработок, поставляемые с вашим релизом «Конвертации данных 2.1» (например, MD81Exp.epf для платформы 8.1 и MD83Exp.epf для платформы 8.3).
  3. В базе КД 2.1 обновите описания метаданных для обеих конфигураций через стандартную процедуру загрузки описания метаданных.
  4. Пересоздайте Правило конвертации объектов (ПКО) для этого перечисления. Убедитесь, что в качестве источника выбран правильный тип ПеречислениеСсылка.СтатусЗаявки, а не его синоним.

Способ Б. Прямой перенос по идентификаторам без создания ПКО

Если имена значений перечисления в базах 8.1 и 8.3 абсолютно идентичны (например, Зарегистрирована, Запланирована, Ошибочная), то создавать отдельное ПКО для этого перечисления вообще не требуется.

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

Способ В. Настройка сопоставления через ПКЗ (при разных именах значений)

Если имена значений перечисления в источниках отличаются от приемника (например, в 8.1 значение называется Запланирована, а в 8.3 оно переименовано в Запланировано), нам обязательно потребуется ПКО и таблица сопоставления значений.

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

Проанализировав эти способы, мы видим, что корректная работа с метаданными и использование стандартных механизмов сопоставления (ПКЗ) избавляют от необходимости писать сложные условия в обработчиках событий КД и делают правила обмена стабильными и масштабируемыми.

← На главную