Как обновить табличную часть во внешней обработке при передаче данных из дополнительной формы в 1С 8.3

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

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

Анализируем причину: почему данные не отображаются?

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

Рассмотрим ситуацию: у нас открыта основная форма (Форма 1). Мы нажимаем кнопку и открываем Форму 2. В этот момент 1С создает второй экземпляр объекта обработки для Формы 2. Если во второй форме мы программно заполняем Объект.ТабличнаяЧасть, мы меняем данные именно во втором экземпляре. Первый экземпляр, связанный с Формой 1, об этих изменениях ничего не знает. Именно поэтому при закрытии второй формы в первой ничего не меняется — таблица остается пустой, так как контекст данных у этих форм абсолютно разный.

Решение 1: Использование Описания Оповещения и метода Закрыть

Рассмотрим наиболее корректный и современный способ передачи данных — использование механизма ОписаниеОповещения. Этот метод позволяет основной форме "ждать" завершения работы второй формы и получить результат её работы в специальную процедуру-обработчик.

Разберем по шагам реализацию в основной форме. Сначала подготовим процедуру открытия вспомогательной формы:


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

Теперь рассмотрим, что должно происходить во второй форме. Когда пользователь нажал кнопку "Перенести данные", нам нужно передать таблицу (или массив структур) обратно и закрыть форму:


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

Завершающий этап — прием данных в Форме 1. Выясним, как правильно обработать полученный массив и обновить интерфейс:


&НаКлиенте
Процедура ПослеЗакрытияФормыЗаполнения(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = Неопределено Тогда
        Возврат; // Пользователь просто закрыл форму без выбора
    КонецЕсли;
    
    // Передаем данные на сервер для заполнения ТЧ объекта
    ЗаполнитьТаблицуНаСервере(Результат);
    
КонецПроцедуры

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

Решение 2: Передача данных через Временное хранилище

Если данных в табличной части очень много (тысячи строк), передавать их через параметры клиента может быть накладно. В этом случае эффективно использовать ВременноеХранилище. Посмотрим, как это работает: во второй форме мы помещаем таблицу в хранилище и передаем только Адрес (строку).

В коде второй формы это будет выглядеть так:


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

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

В первой форме, в процедуре оповещения, мы получим этот адрес и на сервере выполним загрузку:


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

Решение 3: Прямое обращение через Владельца формы

Рассмотрим еще один метод, который часто упоминается на форумах — свойство ВладелецФормы. При открытии второй формы мы указали ЭтаФорма в качестве владельца. Это дает нам возможность из Формы 2 "дотянуться" до реквизитов Формы 1 напрямую.

Важно: При таком подходе нужно обращаться именно к данным формы владельца, а не к его объекту. Проанализируем пример кода для Формы 2:


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

Хотя этот метод кажется простым, мы рекомендуем использовать первый способ (ОписаниеОповещения), так как он обеспечивает более чистую архитектуру и меньше связывает формы между собой, что упрощает отладку.

Особенности обновления интерфейса

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

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

ЭтаФорма.ОбновитьОтображениеДанных();

Резюме для разработчика

Подведем итог нашему разбору. Чтобы успешно обновить табличную часть внешней обработки:

  1. Помните, что каждая форма внешней обработки — это разные объекты в памяти.
  2. Используйте метод ОткрытьФорму с параметром ОписаниеОповещения.
  3. Передавайте данные через результат закрытия формы (Закрыть(Результат)).
  4. Для больших объемов данных используйте ПоместитьВоВременноеХранилище, передавая адрес.
  5. На стороне принимающей формы используйте метод Загрузить() для табличной части на сервере, чтобы обеспечить максимально быструю работу интерфейса.

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

← На главную