Как программно обновить контактную информацию на форме без записи объекта в 1С?

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

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

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

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

В чем заключается проблема?

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

Если мы пойдем "лобовым" путем и попытаемся изменить данные через табличную часть объекта, используя методы типа УправлениеКонтактнойИнформацией.УстановитьКонтактнуюИнформациюОбъекта, мы столкнемся со следующими проблемами:

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

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

Правильный алгоритм решения

Чтобы обновить поля на форме без записи объекта, нам нужно работать с коллекцией, которая служит источником данных для динамически созданных элементов формы. В конфигурациях на базе БСП (в частности, в версиях, используемых в ДО 2.1) эта коллекция часто называется КонтактнаяИнформацияОписаниеДополнительныхРеквизитов или похожим образом (зависит от версии БСП).

Разберем пошагово, как реализовать перенос данных.

1. Получение исходных данных

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


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

    // ... далее следует код обновления формы
КонецПроцедуры

2. Обход коллекции формы и заполнение данных

Теперь самое важное. Мы не трогаем реквизит Объект. Мы обращаемся к коллекции формы ЭтотОбъект.КонтактнаяИнформацияОписаниеДополнительныхРеквизитов. Нам нужно найти в этой коллекции строку, соответствующую нужному виду контактной информации нашего текущего справочника.

Обратите внимание: Вид контактной информации у Источника (Контрагент) и Приемника (Наш справочник) — это разные элементы справочника ВидыКонтактнойИнформации. Нам нужно сопоставить их логически.


// Перебираем коллекцию данных формы
Для Каждого ЭлементКИ из ЭтотОбъект.КонтактнаяИнформацияОписаниеДополнительныхРеквизитов Цикл
    
    // Проверяем, соответствует ли текущая строка Юридическому адресу НАШЕГО объекта
    Если ЭлементКИ.Вид = Справочники.ВидыКонтактнойИнформации.Анк_ЮридическийАдрес Тогда
        
        // Переносим данные из полученной ранее структуры контрагента
        // Важно переносить не только представление, но и внутреннее значение (XML/JSON структуры адреса)
        ЭлементКИ.Значение      = ЮрАдресИзКонтрагента[0].Значение;
        ЭлементКИ.Представление = ЮрАдресИзКонтрагента[0].Представление;
        ЭлементКИ.Тип           = Перечисления.ТипыКонтактнойИнформации.Адрес;
        
    // Здесь можно добавить условия для других видов КИ (Телефон, Email и т.д.)
    ИначеЕсли ЭлементКИ.Вид = Справочники.ВидыКонтактнойИнформации.Анк_Телефон Тогда
        // Логика для телефона...
    КонецЕсли;
    
КонецЦикла;

Почему важно копировать поле Значение? Для адресов в этом поле хранится сложная структура (обычно XML или JSON), разбивающая адрес на город, улицу, дом и т.д. Если скопировать только Представление (строку), то при попытке открыть форму ввода адреса она окажется пустой или некорректной.

3. Обновление отображения (Перерисовка)

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

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


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

// Вызываем метод БСП
УправлениеКонтактнойИнформацией.ОбновитьКонтактнуюИнформацию(ЭтотОбъект, Объект, ПараметрыОбновления);

Параметр Перечитать со значением Истина является ключевым — он заставляет систему перестроить динамические элементы управления на основе тех данных, которые мы только что поместили в коллекцию КонтактнаяИнформацияОписаниеДополнительныхРеквизитов.

Итоговый код решения

Объединим все шаги в единую процедуру, которая выполняется на сервере в контексте формы:


&НаСервере
Процедура ЗаполнитьКИПоКонтрагенту()
    
    // 1. Получаем данные источника
    ДанныеИсточника = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(
        Объект.Контрагент,
        Справочники.ВидыКонтактнойИнформации.ЮридическийАдресКонтрагента,
        ТекущаяДата(),
        Ложь
    );
    
    Если ДанныеИсточника.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    Источник = ДанныеИсточника[0];

    // 2. Изменяем данные в коллекции формы
    Для Каждого ЭлементКоллекции из ЭтотОбъект.КонтактнаяИнформацияОписаниеДополнительныхРеквизитов Цикл
        
        // Ищем целевой вид КИ
        Если ЭлементКоллекции.Вид = Справочники.ВидыКонтактнойИнформации.Анк_ЮридическийАдрес Тогда
            
            ЭлементКоллекции.Значение      = Источник.Значение;
            ЭлементКоллекции.Представление = Источник.Представление;
            
            // Если тип адреса совпадает, можно взять из источника, либо установить явно
            ЭлементКоллекции.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес;
            
            // Прерываем цикл, если нашли нужное (или продолжаем, если видов несколько)
            Прервать; 
            
        КонецЕсли;
        
    КонецЦикла;

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

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

Важные замечания

← На главную