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