Рассмотрим распространенную задачу: необходимо программно обойти элементы справочника и заполнить или обновить их контактную информацию, например, адрес электронной почты, используя данные из запроса. Часто первая интуитивная попытка сделать это напрямую приводит к ошибкам. Разберемся, почему так происходит и как сделать это правильно в современных конфигурациях 1С.
Исходная задача автора: получить из запроса представление (e-mail) и записать его в реквизит АдресЭП табличной части КонтактнаяИнформация справочника ФизическиеЛица.
Первоначальный код выглядел примерно так и не работал:
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Объект = Справочники.ФизическиеЛица.ТекущиеДанные; // Некорректный метод
Объект.КонтактнаяИнформация.АдресЭП = ВыборкаДетальныеЗаписи.Представление; // Неверное присваивание
КонецЦикла;
Давайте по шагам проанализируем, в чем здесь ошибки и как их исправить, чтобы добиться нужного результата без побочных эффектов.
При попытке напрямую изменить данные в табличной части КонтактнаяИнформация разработчики сталкиваются с рядом проблем, которые не всегда очевидны. Посмотрим на основные причины, по которым такой подход не работает или опасен.
ТЧОбъекта.АдресЭП = Значение неверна синтаксически. Табличная часть — это коллекция строк, и обращаться нужно к конкретной строке и её реквизиту: СтрокаТЧ.АдресЭП = Значение.Вывод: Прямая манипуляция с табличной частью КонтактнаяИнформация — рискованный и нерекомендуемый путь для типовых конфигураций.
Несмотря на все риски, рассмотрим механику прямого добавления строки. Этот способ может сработать в простых, нетиповых конфигурациях или если вы точно знаете, что контактная информация хранится только в табличной части без дополнительных механизмов.
Алгоритм действий следующий:
ПолучитьОбъект().Объект.КонтактнаяИнформация).Добавить().Записать().Посмотрим на пример кода, который реализует этот алгоритм:
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Получаем объект по ссылке из запроса
ФизЛицоОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
// Если нужно обновить информацию, а не добавить дубль,
// сначала нужно найти существующую строку или очистить старые данные.
// Например, можно найти строку с нужным видом и типом и изменить ее.
// В данном примере мы просто добавляем новую запись.
СтрТЧ = ФизЛицоОбъект.КонтактнаяИнформация.Добавить();
// ВАЖНО: Заполняем все ключевые поля, а не только адрес
СтрТЧ.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
// Имя предопределенного элемента может отличаться в вашей конфигурации!
// Проверьте в Конфигураторе: Справочники -> ВидыКонтактнойИнформации -> Предопределенные
СтрТЧ.Вид = Справочники.ВидыКонтактнойИнформации.EmailФизическогоЛица;
// Заполняем само значение и его представление
АдресЭП = ВыборкаДетальныеЗаписи.Представление;
СтрТЧ.АдресЭП = АдресЭП; // Это поле может называться иначе или отсутствовать
СтрТЧ.Представление = АдресЭП;
// Записываем объект, чтобы сохранить изменения в базе данных
ФизЛицоОбъект.Записать();
КонецЦикла;
Важно: Этот код лишь демонстрирует механику. Как мы выяснили, в типовых конфигурациях он скорее всего приведет к проблемам. Используйте его с большой осторожностью.
Самый надежный, безопасный и правильный способ работы с контактной информацией в типовых конфигурациях — использовать специально предназначенный для этого API из Библиотеки стандартных подсистем.
В БСП есть общий модуль УправлениеКонтактнойИнформацией, который содержит процедуры и функции для всех операций с контактами: добавление, изменение, удаление, получение. Использование этого модуля гарантирует, что все данные будут записаны корректно во все необходимые места (и в табличную часть, и в регистры сведений).
Рассмотрим, как решить нашу задачу с его помощью. Алгоритм будет немного другим:
ВидыКонтактнойИнформации, который соответствует электронной почте.УправлениеКонтактнойИнформацией.ДобавитьКонтактнуюИнформацию(), передав в нее все необходимые параметры.Посмотрим на практический пример кода, адаптированный из обсуждения:
&НаСервере
Процедура ОбновитьEmailДляВсехНаСервере()
Запрос = Новый Запрос;
// Текст запроса должен выбирать Ссылку на объект и новое значение для его email
Запрос.Текст =
"ВЫБРАТЬ
| ФизическиеЛица.Ссылка КАК Ссылка,
| ВашиДанные.Email КАК НовыйEmail
|ИЗ
| Справочник.ФизическиеЛица КАК ФизическиеЛица
| // Здесь ваше соединение с источником данных для email
|ГДЕ
| ФизическиеЛица.ЭтоГруппа = ЛОЖЬ";
Результат = Запрос.Выполнить().Выгрузить();
// Получаем нужный Вид контактной информации.
// Имя предопределенного элемента (EMailФизическиеЛица, Email и т.д.)
// лучше уточнить в вашей конфигурации.
ВидEmail = Справочники.ВидыКонтактнойИнформации.EmailФизическогоЛица;
Для Каждого Строка ИЗ Результат Цикл
СсылкаНаОбъект = Строка.Ссылка;
НовыйАдрес = Строка.НовыйEmail;
Если НЕ ЗначениеЗаполнено(НовыйАдрес) Тогда
Продолжить;
КонецЕсли;
// Вызываем стандартную процедуру БСП для добавления/обновления информации
УправлениеКонтактнойИнформацией.ДобавитьКонтактнуюИнформацию(
СсылкаНаОбъект, // Владелец информации
НовыйАдрес, // Значение (сам e-mail)
ВидEmail, // Вид информации
ТекущаяДата(), // Дата актуальности
Истина); // Перезаписывать, если контакт такого вида уже есть
Сообщить("Обновлена информация для: " + СсылкаНаОбъект);
КонецЦикла;
КонецПроцедуры
Преимущества этого подхода:
Таким образом, при работе с типовыми конфигурациями на БСП всегда отдавайте предпочтение использованию программных интерфейсов (API) общих модулей. Это сэкономит ваше время, убережет от ошибок и обеспечит корректную работу системы.