Почему запрос через COM-соединение не возвращает контактную информацию контрагентов в 1С и как это исправить?

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

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

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

Выясним причину возникновения проблемы

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

  1. Измерение Тип — хранит значение перечисления ПеречислениеСсылка.ТипыКонтактнойИнформации.
  2. Измерение Вид — хранит ссылку на элемент справочника СправочникСсылка.ВидыКонтактнойИнформации.

Если в коде внешней обработки передавать в параметры обычные текстовые строки, как показано ниже:


Запрос.УстановитьПараметр("Т1", "Телефон");
Запрос.УстановитьПараметр("В1", "Телефон контрагента");

Язык запросов 1С при выполнении левого соединения сравнивает ссылку из регистра со строковым значением. Из-за разницы типов левое соединение не находит совпадающих записей, и в результат выгрузки попадают значения NULL (пустые поля).

Способ 1. Передача ссылочных типов через объект внешней базы

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

Рассмотрим подробнее пример реализации данного подхода с подключением через V82.COMConnector (или V83.COMConnector):


COM1с = Новый COMObject("V82.COMConnector");

Попытка
    ВнешняяБаза = COM1с.Connect("Srvr=serv1cv82;Ref=workbase;Usr=Пользователь;Pwd=Пароль123");
Исключение
    Предупреждение("Ошибка открытия базы!");
    Сообщить(ОписаниеОшибки());
    ВнешняяБаза = Неопределено;
    Возврат;
КонецПопытки;

Запрос = ВнешняяБаза.NewObject("Запрос");
Запрос.Текст = "
|ВЫБРАТЬ
|	ПРЕДСТАВЛЕНИЕ(Контрагенты.Ссылка) КАК Ссылка,
|	Контрагенты.ИНН КАК ИНН,
|	Контрагенты.КПП КАК КПП,
|	Контрагенты.Наименование КАК Наименование,
|	Контрагенты.НаименованиеПолное КАК НаименованиеПолное,
|	КИ_Телефон.Представление КАК Телефон,
|	КИ_Адрес.Представление КАК АдресЮридический,
|	КИ_Адрес2.Представление КАК АдресФактический,
|	Контрагенты.ОсновнойВидДеятельности.Наименование КАК ВидДеятельности,
|	Контрагенты.ПометкаУдаления,
|	Контрагенты.Родитель
|ИЗ
|	Справочник.Контрагенты КАК Контрагенты
|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Телефон
|		ПО (КИ_Телефон.Объект = Контрагенты.Ссылка)
|		И (КИ_Телефон.Тип = &Т1)
|		И (КИ_Телефон.Вид = &В1)
|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Адрес
|		ПО (КИ_Адрес.Объект = Контрагенты.Ссылка)
|		И (КИ_Адрес.Тип = &Т2)
|		И (КИ_Адрес.Вид = &В2)
|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Адрес2
|		ПО (КИ_Адрес2.Объект = Контрагенты.Ссылка)
|		И (КИ_Адрес2.Тип = &Т3)
|		И (КИ_Адрес2.Вид = &В3)
|ГДЕ
|	НЕ Контрагенты.ПометкаУдаления
|	И НЕ Контрагенты.ЭтоГруппа";

// Устанавливаем параметры с использованием объектов внешней базы
Запрос.УстановитьПараметр("Т1", ВнешняяБаза.Перечисления.ТипыКонтактнойИнформации.Телефон);
Запрос.УстановитьПараметр("В1", ВнешняяБаза.Справочники.ВидыКонтактнойИнформации.ТелефонКонтрагента);

Запрос.УстановитьПараметр("Т2", ВнешняяБаза.Перечисления.ТипыКонтактнойИнформации.Адрес);
Запрос.УстановитьПараметр("В2", ВнешняяБаза.Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента);

Запрос.УстановитьПараметр("Т3", ВнешняяБаза.Перечисления.ТипыКонтактнойИнформации.Адрес);
Запрос.УстановитьПараметр("В3", ВнешняяБаза.Справочники.ВидыКонтактнойИнформации.ФактАдресКонтрагента);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Счетчик = 0;
Пока Выборка.Следующий() Цикл
    Счетчик = Счетчик + 1;
    Сообщить("Ссылка: " + СокрЛП(Выборка.Ссылка) + 
             " | ИНН: " + СокрЛП(Выборка.ИНН) + 
             " | Наименование: " + СокрЛП(Выборка.Наименование) + 
             " | Телефон: " + СокрЛП(Выборка.Телефон) + 
             " | Адрес Юр.: " + СокрЛП(Выборка.АдресЮридический) + 
             " | Адрес Факт.: " + СокрЛП(Выборка.АдресФактический));
    Если Счетчик >= 50 Тогда
        Прервать;
    КонецЕсли;
КонецЦикла;

// Закрываем соединение
ВнешняяБаза = Неопределено;

Способ 2. Использование функции ЗНАЧЕНИЕ в тексте запроса

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

При использовании этого метода параметры &Т1, &В1 и прочие не требуются, так как ссылки на предопределенные значения перечислений и справочников задаются в самом запросе:


Запрос = ВнешняяБаза.NewObject("Запрос");
Запрос.Текст = "
|ВЫБРАТЬ
|	Контрагенты.Наименование КАК Наименование,
|	КИ_Телефон.Представление КАК Телефон,
|	КИ_Адрес.Представление КАК АдресЮридический
|ИЗ
|	Справочник.Контрагенты КАК Контрагенты
|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Телефон
|		ПО (КИ_Телефон.Объект = Контрагенты.Ссылка)
|		И (КИ_Телефон.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон))
|		И (КИ_Телефон.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтрагента))
|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Адрес
|		ПО (КИ_Адрес.Объект = Контрагенты.Ссылка)
|		И (КИ_Адрес.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес))
|		И (КИ_Адрес.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ЮрАдресКонтрагента))
|ГДЕ
|	НЕ Контрагенты.ПометкаУдаления
|	И НЕ Контрагенты.ЭтоГруппа";

Результат = Запрос.Выполнить();

Важные особенности работы с COM-соединением

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

  1. Освобождение ресурсов сервера: После завершения работы с переменной соединения всегда явно обнуляйте её (ВнешняяБаза = Неопределено). Это предотвратит зависание фоновых сеансов во внешней информационной базе и освободит занятые лицензии.
  2. Получение представлений ссылок: Обращение к полю типа Ссылка из выборки COM-запроса возвращает COM-объект. Если требуется получить простое текстовое значение (например, наименование родителя или контрагента), используйте в запросе функцию ПРЕДСТАВЛЕНИЕ(Поле).
  3. Имена предопределенных элементов: Проверьте имя предопределенного элемента в конфигураторе подключаемой базы. Например, вид контактной информации юридического адреса может именоваться как ЮрАдресКонтрагента или ЮридическийАдресКонтрагента в зависимости от конфигурации.
← На главную