Как выгрузить таблицу значений в табличную часть внешней обработки при работе с несколькими формами?

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

В процессе разработки внешних обработок на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с задачей взаимодействия между несколькими формами. Типичный сценарий: во вспомогательной форме (например, форме подбора или настроек) формируется ТаблицаЗначений, данные из которой должны попасть в ТабличнуюЧасть основной формы обработки. Рассмотрим подробно, как правильно реализовать этот механизм, избегая типичных ошибок производительности и архитектурных просчетов.

Анализ проблемы взаимодействия форм

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

Разберем по шагам наиболее эффективные способы решения этой задачи.

Способ 1: Использование временного хранилища и обратного вызова

Это «золотой стандарт» разработки в среде 1С. Суть метода заключается в помещении данных во временное хранилище во вспомогательной форме и их извлечении в основной форме после закрытия вспомогательной. Рассмотрим реализацию этого механизма.

В основной форме:

Для начала нам нужно описать процедуру открытия вспомогательной формы. Мы будем использовать ОписаниеОповещения, чтобы основная форма «знала», какую процедуру вызвать, когда вторая форма закроется.


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

&НаКлиенте
Процедура ПриЗакрытииВспомогательнойФормы(Результат, ДопПараметры) Экспорт
    
    // Проверяем, вернул ли нам сервер адрес во временном хранилище
    Если ЭтоАдресВременногоХранилища(Результат) Тогда
        ЗагрузитьДанныеИзХранилищаНаСервере(Результат);
    КонецЕсли;
    
КонецПроцедуры

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

Во вспомогательной форме:

Здесь мы подготавливаем данные и закрываем форму, передавая адрес хранилища в качестве параметра метода Закрыть().


&НаКлиенте
Процедура ЗавершитьПодбор(Команда)
    
    АдресХранилища = ПоместитьДанныеВХранилищеНаСервере();
    Закрыть(АдресХранилища);
    
КонецПроцедуры

&НаСервере
Функция ПоместитьДанныеВХранилищеНаСервере()
    
    // Предположим, ТЗ_Результат получена через СКД или Запрос
    // Мы копируем только нужные колонки, чтобы не перегружать память
    НужныеКолонки = "Номенклатура, Количество, Цена";
    ТЗ_ДляПередачи = ТЗ_Результат.Скопировать(, НужныеКолонки);
    
    // Помещаем во временное хранилище, привязывая к уникальному идентификатору формы
    Возврат ПоместитьВоВременноеХранилище(ТЗ_ДляПередачи, ЭтаФорма.УникальныйИдентификатор);
    
КонецФункции

Способ 2: Оптимизация выбора колонок (Метод Скопировать)

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

Вместо того чтобы помещать ТЗ в запрос и выбирать поля оттуда, гораздо быстрее использовать встроенный метод Скопировать(). Проанализируем пример:


// Вместо создания запроса к ТЗ:
// ТЗ_ТолькоНоменклатура = ТЗ_Исходная.Скопировать(, "Номенклатура");
// Объект.ТаблицаОтбора.Загрузить(ТЗ_ТолькоНоменклатура);

Важный нюанс: метод Загрузить() работает эффективно только в том случае, если имена колонок в ТаблицеЗначений полностью совпадают с именами реквизитов в ТабличнойЧасти. Если имена различаются, вам придется использовать цикл Для Каждого, что на больших объемах данных может работать медленнее.

Технические рекомендации по работе с объектами 1С

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

  1. Лишние обращения к базе данных: В 1С реквизит типа «СправочникСсылка» уже сам по себе является ссылкой. Обращение к свойству .Ссылка вынуждает платформу выполнять дополнительное (хоть и кэшируемое) обращение к объекту. Правильно писать просто: СтрокаТЧ.Номенклатура = СтрокаТЗ.Номенклатура;.
  2. Чтение через точку: Старайтесь минимизировать обращения через точку (например, Строка.Номенклатура.Артикул) внутри циклов в серверном коде. Каждая такая точка — это потенциальный неявный запрос к БД.
  3. Обновление интерфейса: Если после программного заполнения табличной части данные не отобразились на форме, следует вызвать метод ЭтаФорма.ОбновитьОтображениеДанных();. Это заставит визуальные компоненты перечитать данные из реквизитов формы.

Альтернатива: Использование механизма Оповестить()

Если вам требуется обновлять данные в основной форме «на лету», не закрывая вспомогательное окно, воспользуйтесь методом Оповестить().

В дополнительной форме вызываем:

Оповестить("ОбновитьТаблицу", АдресХранилища, ЭтаФорма);

В основной форме создаем обработчик события ОбработкаОповещения:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ОбновитьТаблицу" Тогда
        ЗагрузитьДанныеИзХранилищаНаСервере(Параметр);
    КонецЕсли;
КонецПроцедуры

Этот метод делает интерфейс более динамичным и отзывчивым для пользователя.

Резюме

Мы рассмотрели основные механизмы взаимодействия между формами во внешних обработках. Главное правило — помнить о разделении контекстов и использовать Временное хранилище для передачи объемных коллекций данных (таких как ТаблицаЗначений). Использование метода Загрузить() вместо построчного перебора в цикле значительно повышает производительность вашего кода, особенно при работе с большими справочниками номенклатуры.

← На главную