Как правильно проверить наличие фактического и юридического адреса контрагента в 1С:Комплексная автоматизация 2?

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

В этом подробном руководстве мы разберем распространенную проблему, с которой сталкиваются разработчики при попытке получить и проверить контактную информацию контрагента в конфигурациях 1С, таких как "Комплексная автоматизация 2". Часто возникает необходимость убедиться, что у контрагента заполнен фактический или юридический адрес, а также корректно обработать ситуацию их отсутствия. Мы рассмотрим, как избежать типичных ошибок, выясним причину их возникновения и используем правильные методы для доступа к этим данным, опираясь на лучшие практики платформы 1С:Предприятие.

Выясняем суть проблемы: почему строковое сравнение не работает?

Изначально разработчики, включая автора темы, часто пытаются проверить наличие адреса, сравнивая строковое представление поля Вид из табличной части КонтактнаяИнформация контрагента с искомым наименованием, например, "Фактический адрес". Давайте посмотрим на типичные некорректные попытки, с которыми сталкиваются пользователи:


// Пример некорректного обращения и сравнения
КонтактнаяИнформация = Объект.Контрагент.КонтактнаяИнформация;

Для Каждого Элемент Из КонтактнаяИнформация Цикл
    ВидСтрока = Элемент.Вид.Наименование; // Здесь мы получаем строку, но сравнивать надо не ее
    ПредставлениеАдреса = Элемент.Представление;

    Сообщить(ВидСтрока);
    Сообщить(ПредставлениеАдреса);

    // Некорректные попытки сравнения строковых значений:
    // Попытка 1: Поиск подстроки
    // Факт = Найти(ВидСтрока, "Фактический"); 
    // Если Найти() возвращает 0, это значит, что подстрока не найдена.
    // Это не означает, что адрес отсутствует, а лишь то, что строковое сравнение не подходит.

    // Попытка 2: Использование СтрНайти
    // Если НЕ СтрНайти(ВидСтрока, "Фактический") Тогда
    //     Сообщить("Фактический адрес не заполнен");
    // КонецЕсли;
    // Аналогично, этот метод также не работает корректно,
    // потому что мы ищем подстроку в наименовании, а не сравниваем ссылки.
КонецЦикла;

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

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

Правильный подход: сравнение ссылок на предопределенные элементы или поиск по наименованию

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

  1. Использование предопределенных элементов:

    В типовых конфигурациях 1С, таких как "Комплексная автоматизация", для стандартных видов контактной информации (например, "Фактический адрес", "Юридический адрес") часто существуют предопределенные элементы справочника ВидыКонтактнойИнформации. Обращение к ним через точку (например, Справочники.ВидыКонтактнойИнформации.ФактАдресКонтрагента) является наиболее надежным и производительным способом.

    Почему этот способ предпочтителен? Потому что ссылка на предопределенный элемент остается стабильной даже в случае изменения наименования этого элемента пользователем или в результате обновления конфигурации. Однако, важно отметить, что наименование предопределенного элемента может отличаться в разных конфигурациях или версиях.

    
    // Пример обращения к предопределенному элементу (если он существует с таким именем)
    // В Комплексной автоматизации 2.4+ имена предопределенных элементов
    // для адресов контрагентов могут выглядеть примерно так:
    // Справочники.ВидыКонтактнойИнформации.ФактАдресКонтрагента;
    // Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента;
    // Для точного определения имени всегда рекомендуется проверять в конфигураторе (через дерево конфигурации -> Справочники -> ВидыКонтактнойИнформации -> Предопределенные).
            
    // Допустим, мы нашли такое имя предопределенного элемента:
    // ВидФактическогоАдреса = Справочники.ВидыКонтактнойИнформации.ФактАдресКонтрагента;
    // Если ВидФактическогоАдреса = Неопределено Тогда
    //     Сообщить("Предопределенный вид 'ФактАдресКонтрагента' не найден.");
    //     Возврат;
    // КонецЕсли;
    

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

  2. Поиск по наименованию:

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

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

    Метод НайтиПоНаименованию() является надежным и широко используемым. Мы получили ссылку на нужный нам вид адреса и теперь можем использовать ее для сравнения.

Методы проверки наличия адреса

После того как мы получили корректную ссылку на искомый вид адреса (например, ВидФактическогоАдреса), мы можем использовать один из следующих подходов для проверки его наличия и получения значения. Рассмотрим их подробно.

1. Перебор контактной информации контрагента (на клиенте или на сервере)

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


// Пример использования наСервере или на клиенте в модуле формы или объекта
// Предполагаем, что Объект.Контрагент содержит ссылку на нужного контрагента
// В контексте документа "Заказ клиента", это будет Объект.Контрагент (если реквизит так назван).

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

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

Если ВидЮридическогоАдреса = Неопределено Тогда
    Сообщить("Вид 'Юридический адрес' не найден в справочнике 'ВидыКонтактнойИнформации'.");
    // Возврат;
КонецЕсли;

// Шаг 2: Инициализируем переменные-флаги и переменные для хранения значений адресов
ФактическийАдресНайден = Ложь;
ПредставлениеФактическогоАдреса = "";

ЮридическийАдресНайден = Ложь;
ПредставлениеЮридическогоАдреса = "";

// Шаг 3: Перебираем контактную информацию контрагента
Если Объект.Контрагент.КонтактнаяИнформация.Количество() > 0 Тогда // Проверяем, есть ли вообще записи
    Для Каждого ЭлементКонтактнойИнформации Из Объект.Контрагент.КонтактнаяИнформация Цикл
        // Сравниваем поле Вид текущего элемента с полученными ссылками
        Если ВидФактическогоАдреса <> Неопределено И ЭлементКонтактнойИнформации.Вид = ВидФактическогоАдреса Тогда
            ФактическийАдресНайден = Истина;
            ПредставлениеФактическогоАдреса = ЭлементКонтактнойИнформации.Представление;
            // Если нужен только первый найденный фактический адрес, можно использовать Прервать.
            // Однако, в КонтактнойИнформации может быть несколько адресов одного вида,
            // если мы хотим учесть все, Прервать не используем. Для типовой задачи - достаточно.
        ИначеЕсли ВидЮридическогоАдреса <> Неопределено И ЭлементКонтактнойИнформации.Вид = ВидЮридическогоАдреса Тогда
            ЮридическийАдресНайден = Истина;
            ПредставлениеЮридическогоАдреса = ЭлементКонтактнойИнформации.Представление;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

// Шаг 4: Анализируем результаты
Если ФактическийАдресНайден Тогда
    Сообщить("Фактический адрес контрагента: " + ПредставлениеФактическогоАдреса);
Иначе
    Сообщить("Фактический адрес у контрагента не заполнен.");
КонецЕсли;

Если ЮридическийАдресНайден Тогда
    Сообщить("Юридический адрес контрагента: " + ПредставлениеЮридическогоАдреса);
Иначе
    Сообщить("Юридический адрес у контрагента не заполнен.");
КонецЕсли;

Этот подход является простым и понятным. Мы явно проходим по каждой записи контактной информации, сравниваем тип вида и записываем результат. Флаги ФактическийАдресНайден и ЮридическийАдресНайден позволяют нам четко определить, был ли адрес обнаружен в списке.

2. Использование запроса к базе данных (на сервере)

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


// Пример использования запроса наСервере
// Предполагаем, что Объект.Контрагент содержит ссылку на нужного контрагента

// Шаг 1: Получаем ссылки на виды адресов
ВидФактическогоАдреса = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("Фактический адрес");
ВидЮридическогоАдреса  = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("Юридический адрес");

// Важно: Проверяем, что эти виды существуют
// Если ни один из видов не найден, нет смысла выполнять запрос
МассивВидовДляЗапроса = Новый Массив;
Если ВидФактическогоАдреса <> Неопределено Тогда
    МассивВидовДляЗапроса.Добавить(ВидФактическогоАдреса);
КонецЕсли;
Если ВидЮридическогоАдреса <> Неопределено Тогда
    МассивВидовДляЗапроса.Добавить(ВидЮридическогоАдреса);
КонецЕсли;

Если МассивВидовДляЗапроса.Количество() = 0 Тогда
     Сообщить("Для выполнения запроса не определены виды адресов. Проверьте справочник 'ВидыКонтактнойИнформации'.");
     Возврат;
КонецЕсли;

// Шаг 2: Формируем и выполняем запрос
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    КонтрагентыКонтактнаяИнформация.Представление КАК ПредставлениеАдреса,
    |    КонтрагентыКонтактнаяИнформация.Вид КАК ВидАдреса
    |ИЗ
    |    Справочник.Контрагенты.КонтактнаяИнформация КАК КонтрагентыКонтактнаяИнформация
    |ГДЕ
    |    КонтрагентыКонтактнаяИнформация.Ссылка = &СсылкаКонтрагента
    |    И КонтрагентыКонтактнаяИнформация.Вид В (&МассивВидовАдресов)"; // Используем оператор В для списка значений
            
Запрос.УстановитьПараметр("СсылкаКонтрагента", Объект.Контрагент);
Запрос.УстановитьПараметр("МассивВидовАдресов", МассивВидовДляЗапроса);
            
Выборка = Запрос.Выполнить().Выбрать();
            
// Шаг 3: Обрабатываем результаты запроса
ФактическийАдресНайден = Ложь;
ЮридическийАдресНайден = Ложь;
ПредставлениеФактическогоАдреса = "";
ПредставлениеЮридическогоАдреса = "";
            
Пока Выборка.Следующий() Цикл
    Если Выборка.ВидАдреса = ВидФактическогоАдреса Тогда
        ФактическийАдресНайден = Истина;
        ПредставлениеФактическогоАдреса = Выборка.ПредставлениеАдреса;
    ИначеЕсли Выборка.ВидАдреса = ВидЮридическогоАдреса Тогда
        ЮридическийАдресНайден = Истина;
        ПредставлениеЮридическогоАдреса = Выборка.ПредставлениеАдреса;
    КонецЕсли;
КонецЦикла;
            
// Шаг 4: Анализируем и выводим результаты
Если ФактическийАдресНайден Тогда
    Сообщить("Фактический адрес контрагента (из запроса): " + ПредставлениеФактическогоАдреса);
Иначе
    Сообщить("Фактический адрес у контрагента не заполнен (из запроса).");
КонецЕсли;
            
Если ЮридическийАдресНайден Тогда
    Сообщить("Юридический адрес контрагента (из запроса): " + ПредставлениеЮридическогоАдреса);
Иначе
    Сообщить("Юридический адрес у контрагента не заполнен (из запроса).");
КонецЕсли;

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

Как обработать отсутствие адреса в цикле перебора?

Автор темы столкнулся с затруднением при обработке ситуации, когда адрес отсутствует. В случае перебора контактной информации, как показано выше, мы используем флаг (например, ФактическийАдресНайден). Если после завершения цикла этот флаг остается в значении Ложь, это означает, что адрес не был найден.

Давайте вернемся к примеру с перебором и посмотрим, как можно обработать отсутствие адреса:


// ... (получение ВидФактическогоАдреса и ВидЮридическогоАдреса, проверка на Неопределено) ...

// Переменные для хранения информации
ФактическийАдресНайден = Ложь;
ПредставлениеФактическогоАдреса = "";

ЮридическийАдресНайден = Ложь;
ПредставлениеЮридическогоАдреса = "";

// Проверяем, есть ли вообще контактная информация
Если Объект.Контрагент.КонтактнаяИнформация.Количество() > 0 Тогда
    Для Каждого ЭлементКонтактнойИнформации Из Объект.Контрагент.КонтактнаяИнформация Цикл
        Если ВидФактическогоАдреса <> Неопределено И ЭлементКонтактнойИнформации.Вид = ВидФактическогоАдреса Тогда
            ФактическийАдресНайден = Истина;
            ПредставлениеФактическогоАдреса = ЭлементКонтактнойИнформации.Представление;
        ИначеЕсли ВидЮридическогоАдреса <> Неопределено И ЭлементКонтактнойИнформации.Вид = ВидЮридическогоАдреса Тогда
            ЮридическийАдресНайден = Истина;
            ПредставлениеЮридическогоАдреса = ЭлементКонтактнойИнформации.Представление;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

// Теперь, после цикла, мы можем проверить состояние флагов
Если НЕ ФактическийАдресНайден Тогда
    Сообщить("Внимание: Фактический адрес контрагента не заполнен!");
Иначе
    Сообщить("Фактический адрес: " + ПредставлениеФактическогоАдреса);
КонецЕсли;

Если НЕ ЮридическийАдресНайден Тогда
    Сообщить("Внимание: Юридический адрес контрагента не заполнен!");
Иначе
    Сообщить("Юридический адрес: " + ПредставлениеЮридическогоАдреса);
КонецЕсли;

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

Ключевые выводы и рекомендации

В ходе решения данной проблемы, мы выделили несколько критически важных моментов, которые помогут вам избежать подобных ошибок в будущем и эффективно работать с данными в 1С:

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

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

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

  4. Выбирайте подходящий метод получения данных:

    • Для простой проверки одного-двух адресов для конкретного контрагента, особенно если это происходит в модуле формы или объекта, достаточно перебора табличной части КонтактнаяИнформация.
    • Для более сложных сценариев, массовой обработки данных, получения информации по нескольким контрагентам или для оптимизации производительности на сервере, всегда предпочтительнее использовать Запрос к базе данных.
  5. Конфигурация "Комплексная автоматизация 2": В этой конфигурации (и аналогичных, построенных на управляемом приложении) поведение стандартно для платформы 1С:Предприятие 8.3, и описанные методы будут работать корректно.

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

← На главную