Почему функция КонтактнаяИнформацияОбъекта не возвращает адрес организации?

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

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

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

Анализ исходной проблемы

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


// Получаем ссылку на организацию, этот шаг отрабатывает верно
Оргнизация = Справочники.Организации.НайтиПоНаименованию("ООО Организация"); 
// Пытаемся найти вид контактной информации по наименованию "адрес"
ТипНашегоАдрес = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("адрес"); 
// Вызываем функцию для получения адреса
ОтКого = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(Оргнизация, ТипНашегоАдрес, ТекущаяДата());
// В результате переменная "ОтКого" остается пустой

Ключевая ошибка кроется в строке поиска вида контактной информации:

ТипНашегоАдрес = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("адрес");

Чтобы понять причину, нужно разобраться в структуре хранения контактной информации. Справочник ВидыКонтактнойИнформации является подчиненным. В нем хранятся не просто названия ("адрес", "телефон"), а виды информации, привязанные к конкретным типам объектов-владельцев. Например, в системе могут существовать:

Хотя наименования могут совпадать, это разные элементы справочника с разными владельцами. Когда мы выполняем поиск НайтиПоНаименованию("адрес") без уточнения, для какого объекта мы ищем этот адрес, система не может однозначно определить нужный элемент и, как следствие, не находит его. Именно поэтому для контрагентов код мог случайно сработать (например, если такой элемент без владельца был первым в поиске), а для организации — нет.

Решение 1: Указание владельца при поиске по наименованию

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

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

Посмотрим на исправленный, работающий пример:


Оргнизация = Справочники.Организации.НайтиПоНаименованию("ООО Организация");

// Ищем "Юридический адрес", но теперь с указанием владельца
ТипНашегоАдрес = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию(
    "Юридический адрес", // Наименование
    , // Родитель (пропускаем)
    Справочники.ВидыКонтактнойИнформации.СправочникОрганизации // Владелец
);

// Теперь функция вернет корректный результат
ОтКого = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(Оргнизация, ТипНашегоАдрес, ТекущаяДата());

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

Решение 2: Использование предопределенных элементов (рекомендуемый способ)

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

Преимущества этого метода:

Вот как будет выглядеть код с использованием предопределенного элемента:


// Получаем ссылку на организацию
ОрганизацияСсылка = Справочники.Организации.НайтиПоНаименованию("ООО Организация");

// Используем предопределенный элемент для вида контактной информации
ВидАдреса = Справочники.ВидыКонтактнойИнформации.ЮрАдресОрганизации;

// Получаем адрес в виде готовой строки
ЮридическийАдресСтрокой = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(ОрганизацияСсылка, ВидАдреса, ТекущаяДата());

В большинстве конфигураций на БСП существуют следующие предопределенные элементы:

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


// Устанавливаем последний параметр в Ложь, чтобы получить таблицу значений
АдресВвидеТаблицы = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(ОрганизацияСсылка, ВидАдреса, ТекущаяДата(), Ложь);

// Теперь можно обращаться к полям адреса
// Например, Для Каждого Строка Из АдресВвидеТаблицы Цикл ...

Для массовых операций: прямой запрос к регистру

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

В таких случаях гораздо эффективнее написать прямой запрос к регистру сведений КонтактнаяИнформация. Это позволит получить все необходимые данные за одно обращение к серверу.

Рассмотрим пример запроса для получения юридических и фактических адресов для списка контрагентов.


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

// Устанавливаем параметры, используя предопределенные элементы
Запрос.УстановитьПараметр("ЮрАдрес", Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента);
Запрос.УстановитьПараметр("ФактАдрес", Справочники.ВидыКонтактнойИнформации.ФактАдресКонтрагента);
Запрос.УстановитьПараметр("СписокКонтрагентов", НужныйСписокКонтрагентов);

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

Этот подход является наиболее производительным для обработки больших объемов данных.

← На главную