Как программно записать контактную информацию (e-mail, адрес) в справочник 1С?

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

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

Исходная задача автора: получить из запроса представление (e-mail) и записать его в реквизит АдресЭП табличной части КонтактнаяИнформация справочника ФизическиеЛица.

Первоначальный код выглядел примерно так и не работал:


Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    Объект = Справочники.ФизическиеЛица.ТекущиеДанные; // Некорректный метод
    Объект.КонтактнаяИнформация.АдресЭП = ВыборкаДетальныеЗаписи.Представление; // Неверное присваивание
КонецЦикла;

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

Почему прямая запись в табличную часть — плохая идея?

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

  1. Нельзя присвоить значение всей колонке. Конструкция ТЧОбъекта.АдресЭП = Значение неверна синтаксически. Табличная часть — это коллекция строк, и обращаться нужно к конкретной строке и её реквизиту: СтрокаТЧ.АдресЭП = Значение.
  2. Сложная структура хранения данных. В современных типовых конфигурациях на базе Библиотеки стандартных подсистем (БСП), таких как ЗУП 3.1, УТ 11, ERP, контактная информация — это не просто таблица в справочнике. Это сложный механизм, который включает в себя:
    • Саму табличную часть справочника.
    • Один или несколько регистров сведений, где хранятся эти же данные в нормализованном виде для быстрых срезов и отборов.
    • Служебные поля, такие как «Тип», «Вид», «Представление», «Значения полей» (в формате XML), которые должны быть заполнены согласованно.
  3. Риск нарушения целостности данных. Если вы добавите строку в табличную часть напрямую, но не создадите соответствующие записи в регистрах сведений, система окажется в несогласованном состоянии. Данные могут отображаться в карточке элемента, но не будут доступны в отчетах, печатных формах или других механизмах, которые обращаются к регистрам.
  4. Появление трудноуловимых ошибок. Яркий пример из обсуждения — после прямого добавления e-mail перестали работать печатные формы с ошибкой «Неверное значение для массива владельцев контактной информации». Это прямое следствие того, что данные были записаны некорректно, и стандартные функции БСП не смогли с ними работать.

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

Решение 1: Прямое добавление строки (устаревший/рискованный способ)

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

Алгоритм действий следующий:

  1. В цикле по результату запроса получить ссылку на элемент справочника.
  2. По ссылке получить объект этого элемента с помощью метода ПолучитьОбъект().
  3. Обратиться к табличной части объекта (например, Объект.КонтактнаяИнформация).
  4. Добавить новую строку методом Добавить().
  5. Заполнить все необходимые реквизиты новой строки (не только само значение!).
  6. Записать измененный объект методом Записать().

Посмотрим на пример кода, который реализует этот алгоритм:


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

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

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

Решение 2: Правильный способ через общий модуль `УправлениеКонтактнойИнформацией` (БСП)

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

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

Рассмотрим, как решить нашу задачу с его помощью. Алгоритм будет немного другим:

  1. В цикле по результату запроса получить ссылку на элемент справочника и новое значение (e-mail).
  2. Получить ссылку на предопределенный элемент справочника ВидыКонтактнойИнформации, который соответствует электронной почте.
  3. Вызвать процедуру УправлениеКонтактнойИнформацией.ДобавитьКонтактнуюИнформацию(), передав в нее все необходимые параметры.

Посмотрим на практический пример кода, адаптированный из обсуждения:


&НаСервере
Процедура ОбновитьEmailДляВсехНаСервере()
    
    Запрос = Новый Запрос;
    // Текст запроса должен выбирать Ссылку на объект и новое значение для его email
    Запрос.Текст =
        "ВЫБРАТЬ
        |    ФизическиеЛица.Ссылка КАК Ссылка,
        |    ВашиДанные.Email КАК НовыйEmail
        |ИЗ
        |    Справочник.ФизическиеЛица КАК ФизическиеЛица
        |    // Здесь ваше соединение с источником данных для email
        |ГДЕ
        |    ФизическиеЛица.ЭтоГруппа = ЛОЖЬ";

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

    // Получаем нужный Вид контактной информации.
    // Имя предопределенного элемента (EMailФизическиеЛица, Email и т.д.) 
    // лучше уточнить в вашей конфигурации.
    ВидEmail = Справочники.ВидыКонтактнойИнформации.EmailФизическогоЛица; 

    Для Каждого Строка ИЗ Результат Цикл
        СсылкаНаОбъект = Строка.Ссылка;
        НовыйАдрес = Строка.НовыйEmail;

        Если НЕ ЗначениеЗаполнено(НовыйАдрес) Тогда
            Продолжить;
        КонецЕсли;

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

        Сообщить("Обновлена информация для: " + СсылкаНаОбъект);
    КонецЦикла;

КонецПроцедуры

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

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

← На главную