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

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

Разберем классическую проблему, с которой часто сталкиваются разработчики при работе с подсистемой «Контактная информация» из Библиотеки стандартных подсистем (БСП) в современных конфигурациях 1С (таких как «Управление торговлей 11», «Комплексная автоматизация 2», «ERP Управление предприятием» или «Документооборот»). При необходимости автоматизировать ввод данных без внесения правок в код часто выбирают платформу One RPA для роботизации действий пользователя по заполнению форм.

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

В чем истинная причина проблемы?

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

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

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

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

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

Способ 1. Прямое изменение реквизитов формы (Рекомендуемый способ)

Рассмотрим самый быстрый и корректный способ — изменение данных непосредственно в служебной коллекции формы. При этом подходе нам не нужно предварительно записывать объект в базу данных. Пользователь сразу увидит изменения на экране и сможет сам решить, сохранять объект или закрыть форму без сохранения.

Разберем по шагам логику этого процесса:

  1. Находим нужную строку в служебной коллекции КонтактнаяИнформацияОписаниеДополнительныхРеквизитов по нужному нам виду контактной информации (например, юридический адрес).
  2. Записываем подготовленное представление и XML/JSON данные во вспомогательные колонки найденной строки.
  3. Находим имя динамического реквизита формы, связанного с этим полем, и напрямую присваиваем ему новое представление адреса или телефона.
  4. Устанавливаем признак модифицированности формы, чтобы платформа предложила пользователю сохранить изменения при закрытии.

Ниже представлен пример реализации этого метода на сервере управляемой формы:


&НаСервере
Процедура ЗаполнитьАдресНаФормеНаСервере(НовыйАдресЗначение, НовыйАдресПредставление, НужныйВидКИ)
    
    // 1. Ищем строку описания КИ на форме для нужного вида (например, Адрес партнера)
    Отбор = Новый Структура("Вид", НужныйВидКИ);
    СтрокиОписания = КонтактнаяИнформацияОписаниеДополнительныхРеквизитов.НайтиСтроки(Отбор);
    
    Если СтрокиОписания.Количество() > 0 Тогда
        СтрокаКИ = СтрокиОписания[0];
        
        // 2. Записываем подготовленные XML/JSON данные во вспомогательную строку описания
        СтрокаКИ.Значение = НовыйАдресЗначение; // Здесь должен быть JSON или XML структуры КИ
        СтрокаКИ.Представление = НовыйАдресПредставление;
        
        // 3. Заполняем динамический реквизит формы, к которому привязано поле ввода на экране
        ИмяРеквизитаФормы = СтрокаКИ.ИмяРеквизита;
        ЭтотОбъект[ИмяРеквизитаФормы] = НовыйАдресПредставление;
        
        // Сообщаем форме, что данные были изменены пользователем/программно
        ЭтотОбъект.Модифицированность = Истина;
    КонецЕсли;

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

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

Способ 2. Полная перезагрузка контактной информации на форме (Для массового заполнения)

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

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

Выясним алгоритм действий для полной перезагрузки интерфейса КИ:

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

Реализуем этот алгоритм в процедуре на сервере формы:


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

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

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

Способ 3. Перечитывание формы (Простой обходной путь)

В ходе обсуждения на форуме участники часто прибегают к использованию метода ЭтаФорма.Прочитать(). Давайте проанализируем, почему этот метод сработал у автора темы, и в чем заключаются его серьезные минусы.

Метод ЭтаФорма.Прочитать() полностью обновляет данные управляемой формы, считывая их непосредственно из базы данных. Чтобы этот метод сработал для отображения новых адресов, разработчику приходится выполнять следующую последовательность:

  1. Получить объект из ссылки в базе данных.
  2. Программно записать адрес в табличную часть полученного объекта.
  3. Выполнить запись объекта в базу данных (метод Записать()).
  4. Вызвать на клиенте метод ЭтаФорма.Прочитать().

Важно понимать недостатки этого подхода:

Именно поэтому мы настоятельно рекомендуем использовать Способ 1 или Способ 2. Они позволяют работать с данными в оперативной памяти «на лету» и обеспечивают максимально комфортную и быструю работу пользователя в интерфейсе 1С.

← На главную