Почему возникает ошибка при записи в поле ПолноеНаименование через COM-соединение и как её устранить?

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

При интеграции двух информационных баз 1С с использованием COM-соединения (OLE) разработчики нередко сталкиваются с ситуацией: при попытке заполнить реквизит создаваемого объекта возникает исключение «Ошибка при установке значения атрибута контекста». При этом простые текстовые поля (например, стандартное Наименование) заполняются корректно, а на поле с полным наименованием процесс аварийно прерывается. Разберем по шагам, почему возникает эта ошибка и какими способами её можно обойти.

Причина проблемы: конфликт имени реквизита и метода платформы

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

Когда разработчик выполняет прямое присвоение через внешнее соединение:


НовыйОбъект.ПолноеНаименование = лЗначение;
// или обращение по индексу:
НовыйОбъект["ПолноеНаименование"] = лЗначение;

Встроенный язык и COM-интерфейс выполняют поиск идентификатора в контексте объекта. В силу правил разрешения имен приоритет отдается стандартному системному методу платформы. Попытка записать значение в функцию приводит к невозможности изменения контекста и генерации ошибки времени выполнения.

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

Способ 1. Проверка метаданных и использование корректного имени реквизита

Выясним точное имя реквизита в подключаемой информационной базе. Чаще всего разработчик по привычке пишет ПолноеНаименование, тогда как в структуре конфигурации реквизит объявлен как НаименованиеПолное.

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


ИмяРеквизита = "";
МетаРеквизиты = OLEБаза.Метаданные.Справочники[ИмяСправочника].Реквизиты;

Если МетаРеквизиты.Найти("НаименованиеПолное") <> Неопределено Тогда
    ИмяРеквизита = "НаименованиеПолное";
ИначеЕсли МетаРеквизиты.Найти("ПолноеНаименование") <> Неопределено Тогда
    ИмяРеквизита = "ПолноеНаименование";
КонецЕсли;

Если ИмяРеквизита = "НаименованиеПолное" Тогда
    НовыйОбъект.НаименованиеПолное = лЗначение;
КонецЕсли;

Если в удаленной базе реквизит называется НаименованиеПолное, прямое присвоение выполняется без ошибок.

Способ 2. Заполнение через структуру и функцию ЗаполнитьЗначенияСвойств

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

Разберем реализацию этого обхода:

  1. Создаем объект типа Структура на стороне OLE-подключения с помощью метода NewObject.
  2. Помещаем в структуру свойство с именем ПолноеНаименование и передаем необходимое значение.
  3. Вызываем метод ЗаполнитьЗначенияСвойств внешней базы, передавая целевой объект справочника и созданную структуру.

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


// Создаем структуру в контексте удаленной базы
лСтруктура = OLEБаза.NewObject("Структура");
лСтруктура.Вставить("ПолноеНаименование", лЗначение);

// Заполняем реквизиты объекта без прямого обращения к свойству через точку
OLEБаза.ЗаполнитьЗначенияСвойств(НовыйОбъект, лСтруктура);

// Записываем элемент в удаленной базе
НовыйОбъект.Записать();

Механизм ЗаполнитьЗначенияСвойств обращается напрямую к реквизитам объекта метаданных, игнорируя интерфейсные методы, благодаря чему значение успешно записывается в базу.

Способ 3. Вызов экспортной процедуры на стороне удаленной базы

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

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


Процедура ЗаполнитьРеквизитыНоменклатуры(ОбъектНоменклатуры, СтруктураДанных) Экспорт
    ЗаполнитьЗначенияСвойств(ОбъектНоменклатуры, СтруктураДанных);
КонецПроцедуры

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

Рекомендации по стабильности интеграции через COM

При организации обмена через COM-соединение обратим внимание на следующие правила:

  1. Использование COMConnector вместо Application: для фонового обмена данными рекомендуется создавать объект V83.COMConnector, а не V83.Application. Внешнее соединение работает быстрее, расходует меньше оперативной памяти и не запускает пользовательский интерфейс, что исключает блокировку процесса модальными окнами.
  2. Унификация имен реквизитов: при доработке конфигураций всегда соблюдайте стандарты разработки фирмы «1С» и избегайте совпадения названий реквизитов с системными функциями (ПолноеНаименование, Уровень, Метаданные, Ссылка).
  3. Альтернативные механизмы интеграции: при регулярном взаимодействии баз рассмотрите переход на современные протоколы обмена — HTTP-сервисы или стандартный интерфейс OData (REST API), где подобные конфликты контекста отсутствуют по определению.
← На главную