Как правильно получить контактную информацию в 1С и почему методы Получить() и Выбрать() вызывают ошибки?

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

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

Анализ проблемы: почему методы Получить() и Выбрать() дают сбой?

Рассмотрим ситуацию, когда нам необходимо получить все номера телефонов контрагента или организации, не привязываясь к конкретному виду контактной информации (например, не разделяя их на «Мобильный», «Рабочий» или «Факс»).

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


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

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

Другая частая ошибка возникает при попытке использовать метод Выбрать():


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

В результате выполнения этого кода система генерирует ошибку: «Недопустимое значение параметра (параметр номер '1')». Это происходит по двум причинам:

  1. Регистр сведений КонтактнаяИнформация в типовых конфигурациях является непериодическим. В методе Выбрать() для непериодического регистра структура отбора передается первым параметром. Однако отбор в методе Выбрать() можно устанавливать только по тем измерениям, по которым в конфигураторе взведен признак «Индексировать» или «Ведущее».
  2. Если мы пытаемся построить отбор по неиндексированным полям или нарушаем структуру измерений, метод Выбрать() завершается аварийно.

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

Решение №1: Использование универсальных запросов

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

Рассмотрим подробнее пример кода, который решает задачу получения всех телефонов и адресов электронной почты для конкретного объекта:


Процедура ЗаписатьКонтактыВXML(ЗаписьXML, Объект)
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Контакт");
    
    // Создаем запрос для получения электронной почты
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	КонтактнаяИнформация.Представление КАК Представление
        |ИЗ
        |	РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
        |ГДЕ
        |	КонтактнаяИнформация.Объект = &Объект
        |	И КонтактнаяИнформация.Тип = &Тип";
    
    Запрос.УстановитьПараметр("Объект", Объект);
    Запрос.УстановитьПараметр("Тип", Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Пока Выборка.Следующий() Цикл
            Если СокрЛП(Выборка.Представление) <> "" Тогда
                ЗаписьXML.ЗаписатьАтрибут("ЭлПочта", Выборка.Представление);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    // Переопределяем параметр типа для получения телефонов
    Запрос.УстановитьПараметр("Тип", Перечисления.ТипыКонтактнойИнформации.Телефон);
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Пока Выборка.Следующий() Цикл
            Если СокрЛП(Выборка.Представление) <> "" Тогда
                ЗаписьXML.ЗаписатьАтрибут("Тлф", Выборка.Представление);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Контакт
    
КонецПроцедуры

Преимущества использования запроса в данном случае:

Решение №2: Современный стандарт работы с контактной информацией (БСП)

Если вы работаете в современных конфигурациях (таких как 1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей ред. 11, 1С:Бухгалтерия предприятия ред. 3.0), то прямое обращение к регистру сведений КонтактнаяИнформация считается устаревшим подходом (legacy-кодом). В актуальных версиях Библиотеки Стандартных Подсистем (БСП) хранение контактной информации перенесено в табличные части самих справочников-владельцев.

Для работы с КИ разработчики БСП предоставили готовый программный интерфейс — общий модуль УправлениеКонтактнойИнформацией. Посмотрим на пример использования этого модуля для получения контактных данных:


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

ТаблицаАдресов = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(СсылкаНаОбъект, ПараметрыОтбора);

Для Каждого СтрокаКИ Из ТаблицаАдресов Цикл
    Если ЗначениеЗаполнено(СтрокаКИ.Представление) Тогда
        Сообщить("Электронная почта: " + СтрокаКИ.Представление);
    КонецЕсли;
КонецЦикла;

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


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

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

Развенчание мифа: Работает ли код в одну строку быстрее?

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

Проанализируем, почему этот миф возник и как обстоят дела на самом деле.

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


а=0;ее=текущаядата;Пока а<10000000 Цикл а=а+1;КонецЦикла;Сообщить(текущаядата-ее);

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

Когда к сеансу 1С подключен отладчик, он осуществляет мониторинг выполнения кода построчно. На переход от одной физической строки к другой тратятся дополнительные ресурсы на взаимодействие отладочного модуля с сервером или клиентом. Если весь алгоритм записан в одну строку, отладчик регистрирует его как одно действие, что искусственно занижает показатели времени выполнения на замерах.

В реальной рабочей (продуктовой) базе, где отладка на сервере выключена, ситуация кардинально иная:

  1. Перед исполнением исходный код модулей компилируется платформой 1С в промежуточный машинный код — байт-код.
  2. В процессе компиляции транслятор полностью игнорирует все символы форматирования: пробелы, знаки табуляции, комментарии и символы перевода строки (CRLF).
  3. Полученный байт-код для красиво отформатированного текста программы и для сплошного текста в одну строку будет абсолютно одинаковым. Соответственно, и скорость выполнения кода на рабочем сервере будет идентичной до наносекунды.

Стремление писать код в одну строку ради мнимого ускорения наносит огромный вред проекту. Такой код невозможно читать, анализировать и поддерживать другим разработчикам. Кроме того, системы автоматической проверки качества кода (такие как 1С:АПК или SonarQube) считают длинные строки и отсутствие форматирования критической ошибкой, нарушающей стандарты разработки фирмы «1С».

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

← На главную