Как заполнить и обновить таблицу на управляемой форме 1С

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

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

Почему данные не обновляются автоматически

В управляемом приложении контекст формы и экземпляр прикладного объекта разделены:

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

Способ 1. Синхронизация через методы преобразования реквизитов

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

Рассмотрим базовый вариант с полной перезагрузкой объекта:


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

Если модуль объекта возвращает готовую таблицу значений, разберем точечную загрузку данных в коллекцию формы без полного преобразования объекта:


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

Способ 2. Передача данных из фонового задания через временное хранилище

Когда алгоритм выполняется в фоновом режиме, фоновое задание не может напрямую взаимодействовать с формой. Выясним правильный порядок передачи данных:

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

Посмотрим на пример кода серверной процедуры получения результата:


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

Способ 3. Обновление закэшированных представлений ссылок

Иногда при программном изменении связанных данных (например, когда при проведении документа программно изменилось наименование номенклатуры) на форме отображается старое представление. Это связано с тем, что клиентское приложение кэширует строковые представления ссылочных типов.

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


&НаКлиенте
Процедура ПослеПроведенияИлиИзменения(СсылкаНаОбъект)
    // Оповещаем систему об изменении данных конкретной ссылки
    ОповеститьОбИзменении(СсылкаНаОбъект);
КонецПроцедуры

Способ 4. Заполнение реквизита типа ТабличныйДокумент из внешнего файла

Разберем частую задачу загрузки данных из внешнего файла Excel в реквизит формы с типом ТабличныйДокумент. Надежнее всего выполнять чтение файла на стороне сервера во избежание проблем с правами и клиентским окружением.

Проанализируем пошаговый алгоритм загрузки:


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

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

Рекомендации

  1. Для копирования данных между однотипными коллекциями формы (например, из временного реквизита формы в табличную часть) используйте платформенную процедуру КопироватьДанныеФормы(Источник, Приемник).
  2. Не применяйте метод формы Прочитать() для отображения результатов заполнения в несохраненных документах, так как он считывает исходные данные из базы данных и сотрет все введенные пользователем изменения.
  3. При программном заполнении реквизитов формы всегда контролируйте свойство Модифицированность формы, чтобы платформа корректно предупреждала пользователя о несохраненных изменениях при закрытии.
← На главную