При работе с программной загрузкой или изменением данных в 1С:Бухгалтерия 3.0, особенно когда речь идет о такой сложной структуре, как контактная информация контрагентов, мы часто сталкиваемся с тем, что прямая запись в табличные части объектов не приносит желаемого результата. В данной статье мы подробно разберем, почему так происходит, и как правильно работать с контактной информацией, используя рекомендованные механизмы БСП (Библиотеки стандартных подсистем) в 1С.
Когда мы пытаемся напрямую записать значения в табличную часть КонтактнаяИнформация элемента справочника, например, контрагента, мы можем обнаружить, что изменения не сохраняются или отображаются некорректно. Автор изначального вопроса столкнулся с этой проблемой, пытаясь "прямой записью" заполнить колонки "Вид", "Тип", "Представление" и другие.
Причина такой неэффективности заключается в том, что 1С хранит контактную информацию не просто как набор строк, а в более сложной, структурированной форме. Эти данные могут быть представлены в виде XML-строк, XDTO-объектов или других внутренних структур, особенно для таких сложных типов, как адреса, которые интегрированы с Федеральной информационной адресной системой (ФИАС).
Таким образом, для корректной работы с контактной информацией требуется использование специализированных функций и методов, предоставляемых БСП, которые умеют преобразовывать наши данные в необходимый внутренний формат и правильно записывать их в базу. В качестве альтернативы ручному написанию кода можно использовать готовую обработку для переноса данных между похожими конфигурациями 1С.
Давайте разберем, как 1С хранит контактную информацию. Каждый объект, который может иметь контактные данные (например, контрагент, физическое лицо, организация), имеет табличную часть с именем КонтактнаяИнформация. Эта табличная часть содержит несколько ключевых колонок:
Вид: Ссылка на элемент справочника ВидыКонтактнойИнформации. Это определяет, что именно мы записываем (например, "Юр. адрес контрагента", "Email", "Телефон").Тип: Ссылка на перечисление ТипыКонтактнойИнформации. Определяет общий тип контактной информации (например, "Адрес", "Телефон", "АдресЭлектроннойПочты").Представление: Строковое представление контактной информации, которое мы видим в интерфейсе пользователя (например, "г. Москва, ул. Ленина, д. 1", "test@example.com", "+7 (495) 123-45-67").ЗначенияПолей: Это наиболее важная и сложная колонка. Она хранит детализированные данные о контактной информации в структурированном виде. Для простых типов, таких как электронная почта или телефон, это может быть XML-строка, содержащая значение. Для адресов эта колонка содержит сложный XDTO-объект или XML-структуру, описывающую адрес по компонентам (город, улица, дом и т.д.) в соответствии с классификатором ФИАС. Именно из-за этой колонки прямая запись значений часто не работает, так как требуется не просто строка, а корректно сформированная структура.Когда мы работаем с контактной информацией программно, нам необходимо не только правильно определить Вид и Тип, но и корректно сформировать содержимое колонки ЗначенияПолей. Для этого и предназначены функции БСП.
Для программной работы с контактной информацией в 1С:Бухгалтерия 3.0 (и других конфигурациях на БСП) мы будем использовать два основных модуля:
УправлениеКонтактнойИнформациейЭтот модуль является основным и рекомендованным для использования. Он предоставляет унифицированный и стабильный интерфейс для получения, добавления, изменения и удаления контактной информации для любых объектов конфигурации. Функции этого модуля заботятся о внутренней логике, форматировании данных и взаимодействии с системой. Мы будем использовать следующие его функции:
КонтактнаяИнформацияОбъекта(): Позволяет получить текущую контактную информацию для указанного объекта. Возвращает табличную часть с данными.ЗаписатьКонтактнуюИнформацию(): Используется для записи новой контактной информации. Она принимает объект, сформированные ЗначенияПолей, Вид и Тип.УстановитьКонтактнуюИнформациюОбъекта(): Используется для сохранения изменений в уже полученной табличной части контактной информации объекта.УправлениеКонтактнойИнформациейСлужебныйМодули с суффиксом "Служебный" (например, УправлениеКонтактнойИнформациейСлужебный) в 1С содержат внутренние, вспомогательные функции, которые не предназначены для прямого вызова из внешнего прикладного кода. Они являются частью "внутренней кухни" конфигурации и могут меняться разработчиками 1С в новых версиях платформы или конфигурации без предварительного уведомления. Это означает, что код, использующий такие "служебные" модули, может перестать работать после очередного обновления.
Критически важное предупреждение: Несмотря на то, что в приведенном примере кода используются функции из модуля УправлениеКонтактнойИнформациейСлужебный, мы настоятельно не рекомендуем их прямое использование в ваших разработках, предназначенных для длительной эксплуатации. Вместо этого, по возможности, следует искать аналогичные функции в "неслужебных" модулях БСП или создавать обертки для этих функций, чтобы минимизировать риски при обновлениях.
Тем не менее, для демонстрации рабочего примера, как это было сделано автором, мы рассмотрим его код. Он использует следующие функции из этого служебного модуля:
КонтактнаяИнформацияXDTOПоПредставлению(): Формирует XDTO-объект контактной информации из ее строкового представления и типа.КонтактнаяИнформацияXDTOВXML(): Преобразует XDTO-объект контактной информации в XML-строку, которая затем записывается в поле ЗначенияПолей.Давайте подробно рассмотрим процесс добавления новой контактной информации на примере адреса электронной почты для существующего контрагента. Мы будем использовать подход, предложенный автором, с использованием функций БСП.
Получение объекта контрагента: Прежде всего, нам нужна ссылка на объект контрагента, которому мы хотим добавить контактную информацию. Мы можем получить его по наименованию, коду или любым другим доступным методом.
// Предположим, у нас есть наименование контрагента
НаименованиеКонтрагента = "НаименованиеМоегоКонтрагента";
МойКонтрагент = Справочники.Контрагенты.НайтиПоНаименованию(НаименованиеКонтрагента);
// Если контрагент не найден, необходимо обработать эту ситуацию
Если МойКонтрагент = Неопределено Тогда
Сообщить("Контрагент с наименованием '" + НаименованиеКонтрагента + "' не найден!");
Возврат;
КонецЕсли;
// Если мы работаем с объектом, а не ссылкой
МойКонтрагентОбъект = МойКонтрагент.ПолучитьОбъект();
Определение типа и вида контактной информации: Для корректной записи нам необходимо указать, какой тип и вид контактной информации мы добавляем. Эти значения выбираются из системных перечислений и справочников.
ТипКИ = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтрагенты; // Может отличаться в вашей базе
АдресЭлектроннойПочты = "new_email@example.com";
Важно убедиться, что выбранные ВидКИ и ТипКИ соответствуют тому, что вы хотите сохранить. ВидКИ обычно создается в конфигурации для каждого объекта и может иметь различные значения для одного ТипаКИ (например, "Рабочий Email", "Личный Email").
Формирование XDTO-объекта и XML-строки для ЗначенияПолей: Это самый сложный шаг, который требует использования "служебных" функций. Мы сначала формируем внутренний XDTO-объект из строкового представления электронной почты, а затем преобразуем его в XML-строку.
// Создаем XDTO-объект контактной информации из представления и типа
ОбъектXDTOКИ = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(АдресЭлектроннойПочты, ТипКИ);
// Преобразуем XDTO-объект в XML-строку, которая будет храниться в "ЗначенияПолей"
ЗначенияПолейXML = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTOКИ);
Здесь УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению() берет обычную строку (адрес электронной почты) и "упаковывает" её в специальный XDTO-формат, понятный 1С. Затем УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML() конвертирует этот XDTO-объект в текстовое XML-представление, которое и будет сохранено в поле ЗначенияПолей табличной части.
Запись контактной информации в объект: Теперь, когда у нас есть все необходимые данные в правильном формате, мы используем основную функцию БСП для записи контактной информации.
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(МойКонтрагентОбъект, ЗначенияПолейXML, ВидКИ, ТипКИ);
Эта функция самостоятельно добавляет новую строку в табличную часть КонтактнаяИнформация объекта МойКонтрагентОбъект, заполняя все необходимые поля, включая наше сформированное ЗначенияПолейXML.
Финальная запись объекта контрагента: После всех манипуляций с контактной информацией, не забудьте записать сам объект контрагента, чтобы изменения были сохранены в базе данных.
МойКонтрагентОбъект.Записать();
Сообщить("Контактная информация (Email) успешно добавлена для контрагента " + НаименованиеКонтрагента);
Полный пример кода для добавления контактной информации (Email):
// ******** Начало кода для добавления контактной информации (Email) ********
// 1. Получаем объект контрагента
// Предположим, у нас есть переменная с адресом электронной почты для добавления
АдресЭлектроннойПочтыДляДобавления = "example_new@domain.com";
// Пример получения первого попавшегося контрагента для демонстрации
// В реальной задаче вы, скорее всего, будете перебирать контрагентов или искать конкретного
Спр = Справочники.Контрагенты.Выбрать();
Если Спр.Следующий() Тогда
МойКонтрагентОбъект = Спр.ПолучитьОбъект(); // Получаем объект для изменения
Иначе
Сообщить("Не найдено ни одного контрагента для добавления информации.");
Возврат;
КонецЕсли;
// 2. Определяем тип и вид контактной информации
ТипКИ = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтрагенты;
// Проверяем существование вида контактной информации
Если ВидКИ.Пустая() Тогда
Сообщить("Не найден вид контактной информации 'EmailКонтрагенты'. Проверьте справочник 'ВидыКонтактнойИнформации'.");
Возврат;
КонецЕсли;
// 3. Формируем XDTO-объект и XML-строку для "ЗначенияПолей"
// Важно: Использование "Служебный" модулей не рекомендуется 1С
ОбъектXDTOКИ = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(АдресЭлектроннойПочтыДляДобавления, ТипКИ);
ЗначенияПолейXML = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTOКИ);
// 4. Записываем контактную информацию в объект
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(МойКонтрагентОбъект, ЗначенияПолейXML, ВидКИ, ТипКИ);
// 5. Финальная запись объекта контрагента
МойКонтрагентОбъект.Записать();
Сообщить("Контактная информация (Email: " + АдресЭлектроннойПочтыДляДобавления + ") успешно добавлена для контрагента: " + МойКонтрагентОбъект.Наименование);
// ******** Конец кода для добавления контактной информации (Email) ********
Если нам необходимо не добавить новую запись, а изменить существующую контактную информацию (например, обновить адрес электронной почты), процесс будет несколько иным. Мы сначала получаем текущие данные, находим нужную запись, модифицируем ее и затем сохраняем.
Получение объекта контрагента: Аналогично предыдущему случаю, нам нужен объект контрагента.
// Предположим, у нас есть наименование контрагента
НаименованиеКонтрагента = "НаименованиеМоегоКонтрагента";
МойКонтрагент = Справочники.Контрагенты.НайтиПоНаименованию(НаименованиеКонтрагента);
Если МойКонтрагент = Неопределено Тогда
Сообщить("Контрагент с наименованием '" + НаименованиеКонтрагента + "' не найден!");
Возврат;
КонецЕсли;
МойКонтрагентОбъект = МойКонтрагент.ПолучитьОбъект();
Получение текущей контактной информации объекта: Используем функцию КонтактнаяИнформацияОбъекта() для загрузки всех текущих контактных данных. Эта функция возвращает табличную часть, которую мы можем изменять.
// Получаем текущую контактную информацию объекта
КонтИнформация = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(МойКонтрагентОбъект,,ТекущаяДата(),Ложь);
Параметры функции КонтактнаяИнформацияОбъекта():
Объект: Ссылка или объект, для которого запрашивается контактная информация.ДатаАктуальности (необязательный): Дата, на которую требуется получить контактную информацию (для версионируемых данных).ТолькоАктуальные (необязательный): Если Истина, будут возвращены только актуальные записи.Определение типа и вида для новой информации: Определяем тип и вид контактной информации, которую мы хотим установить.
ТипКИ = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтрагенты; // Должен совпадать с тем, что ищем
НовыйАдресЭлектроннойПочты = "updated_email@example.com";
Формирование нового XDTO-объекта и XML-строки: Аналогично добавлению, создаем новые структурированные данные для поля ЗначенияПолей.
ОбъектXDTOКИ = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(НовыйАдресЭлектроннойПочты, ТипКИ);
ЗначенияПолейXML = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTOКИ);
Поиск и обновление существующей записи: Теперь мы перебираем полученную табличную часть КонтИнформация, находим нужную строку по ее Виду и обновляем ее поля.
НайденаЗапись = Ложь;
Для каждого ТекСтрока ИЗ КонтИнформация Цикл
Если Строка(ТекСтрока.Вид) = Строка(ВидКИ) Тогда // Сравниваем по строковому представлению
ТекСтрока.Представление = НовыйАдресЭлектроннойПочты;
ТекСтрока.ЗначенияПолей = ЗначенияПолейXML;
НайденаЗапись = Истина;
Прервать; // Обновляем только первую найденную запись
КонецЕсли;
КонецЦикла;
Если Не НайденаЗапись Тогда
Сообщить("Контактная информация типа Email не найдена для обновления. Возможно, следует добавить новую запись.");
Возврат;
КонецЕсли;
Установка обновленной контактной информации в объект: После модификации табличной части, мы используем функцию УстановитьКонтактнуюИнформациюОбъекта(), чтобы применить эти изменения к объекту контрагента.
УправлениеКонтактнойИнформацией.УстановитьКонтактнуюИнформациюОбъекта(МойКонтрагентОбъект, КонтИнформация);
Финальная запись объекта контрагента: Как и при добавлении, завершаем процесс записью самого объекта контрагента.
МойКонтрагентОбъект.Записать();
Сообщить("Контактная информация (Email) успешно обновлена для контрагента: " + МойКонтрагентОбъект.Наименование);
Полный пример кода для замены контактной информации (Email):
// ******** Начало кода для замены контактной информации (Email) ********
// 1. Получаем объект контрагента
// Предположим, у нас есть переменная с адресом электронной почты для обновления
НовыйАдресЭлектроннойПочтыДляЗамены = "updated_contact@newdomain.com";
// Пример получения первого попавшегося контрагента для демонстрации
// В реальной задаче вы, скорее всего, будете перебирать контрагентов или искать конкретного
Спр = Справочники.Контрагенты.Выбрать();
Если Спр.Следующий() Тогда
МойКонтрагентОбъект = Спр.ПолучитьОбъект(); // Получаем объект для изменения
Иначе
Сообщить("Не найдено ни одного контрагента для замены информации.");
Возврат;
КонецЕсли;
// 2. Получаем текущую контактную информацию объекта
КонтИнформация = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(МойКонтрагентОбъект,,ТекущаяДата(),Ложь);
// 3. Определяем тип и вид контактной информации, которую будем менять
ТипКИ = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтрагенты;
// Проверяем существование вида контактной информации
Если ВидКИ.Пустая() Тогда
Сообщить("Не найден вид контактной информации 'EmailКонтрагенты'. Проверьте справочник 'ВидыКонтактнойИнформации'.");
Возврат;
КонецЕсли;
// 4. Формируем новый XDTO-объект и XML-строку для "ЗначенияПолей"
// Важно: Использование "Служебный" модулей не рекомендуется 1С
ОбъектXDTOКИ = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(НовыйАдресЭлектроннойПочтыДляЗамены, ТипКИ);
ЗначенияПолейXML = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTOКИ);
// 5. Перебираем существующую контактную информацию и обновляем нужную строку
НайденаЗаписьДляЗамены = Ложь;
Для каждого ТекСтрока ИЗ КонтИнформация Цикл
// Сравниваем вид, чтобы найти нужную запись для обновления
Если Строка(ТекСтрока.Вид) = Строка(ВидКИ) Тогда
ТекСтрока.Представление = НовыйАдресЭлектроннойПочтыДляЗамены; // Обновляем отображаемое представление
ТекСтрока.ЗначенияПолей = ЗначенияПолейXML; // Обновляем внутреннюю структурированную запись
НайденаЗаписьДляЗамены = Истина;
Прервать; // Если нужно обновить только первую найденную запись
КонецЕсли;
КонецЦикла;
Если Не НайденаЗаписьДляЗамены Тогда
Сообщить("Контактная информация типа Email для вида '" + Строка(ВидКИ) + "' не найдена у контрагента: " + МойКонтрагентОбъект.Наименование + ". Добавление новой записи.");
// Если запись не найдена, можно принять решение о ее добавлении
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(МойКонтрагентОбъект, ЗначенияПолейXML, ВидКИ, ТипКИ);
Иначе
// 6. Устанавливаем обновленную контактную информацию в объект
УправлениеКонтактнойИнформацией.УстановитьКонтактнуюИнформациюОбъекта(МойКонтрагентОбъект, КонтИнформация);
КонецЕсли;
// 7. Финальная запись объекта контрагента
МойКонтрагентОбъект.Записать();
Сообщить("Контактная информация (Email: " + НовыйАдресЭлектроннойПочтыДляЗамены + ") успешно заменена/добавлена для контрагента: " + МойКонтрагентОбъект.Наименование);
// ******** Конец кода для замены контактной информации (Email) ********
Работа с адресами (юридическими, фактическими, почтовыми) является наиболее сложной частью управления контактной информацией в 1С. Это связано с глубокой интеграцией системы с Федеральной информационной адресной системой (ФИАС).
Почему адреса сложнее?
УправлениеКонтактнойИнформацией.ДобавитьКонтактнуюИнформацию(), которую пытался использовать автор в самом начале, действительно может быть применена для адресов, но ее параметры для адресов требуют не просто строки, а специальной структуры, сформированной на основе данных ФИАС.Рекомендации для работы с адресами:
Мы настоятельно рекомендуем не пытаться напрямую формировать XML-строки для адресов, как это было сделано для электронной почты, используя "служебные" функции. Вместо этого:
При программной работе с контактной информацией в 1С:Бухгалтерия 3.0 мы рекомендуем придерживаться следующих принципов:
ВидыКонтактнойИнформации и ТипыКонтактнойИнформации, которые вы используете в коде, существуют в вашей базе данных и правильно настроены.Работа с контактной информацией в 1С, особенно в современных управляемых приложениях, требует понимания внутренних механизмов хранения данных и использования соответствующих функций БСП. Прямая запись в табличные части редко приводит к успеху из-за сложной структурированной природы данных, таких как XML и XDTO. Используя модули УправлениеКонтактнойИнформацией, мы можем эффективно добавлять и изменять контактную информацию, обеспечивая корректность и устойчивость нашего решения к изменениям конфигурации. Особое внимание следует уделять работе с адресами, где необходима интеграция с ФИАС и использование специализированных функций для обработки адресных данных.