Почему не заполняется табличная часть при открытии новой формы обработки и как это исправить

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

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

В этой статье мы подробно разберем, почему данные «теряются», как устроена работа с объектами в памяти сервера и какие существуют надежные способы передачи данных табличных частей между формами.

Причина возникновения проблемы: архитектура управляемых форм

Проанализируем ситуацию. В обычном приложении (толстый клиент) объект обработки существовал в памяти как единое целое. В управляемом приложении всё иначе. Когда мы открываем форму, система создает не сам объект, а его «проекцию» — специальный тип данных ДанныеФормыСтруктура, который отображается в реквизите Объект.

Важно понимать: для каждого нового экземпляра формы (даже если это формы одной и той же обработки) создается свой собственный экземпляр данных. Они никак не связаны между собой автоматически. Если вы добавили строки в таблицу в Форме №1, Форма №2 об этом ничего не узнает, так как она работает со своей копией данных в памяти сервера. Рассмотрим основные способы решения этой проблемы.

Способ 1. Использование механизма владельца формы и копирование данных

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

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


ПараметрыОткрытия = Новый Структура;
// Если нужно передать дополнительные параметры, добавляем их сюда
ОткрытьФорму("Обработка.МояОбработка.Форма.ФормаНастроек", ПараметрыОткрытия, ЭтаФорма);

Теперь во второй форме (в данном примере это «ФормаНастроек») нам нужно принять эти данные. Наилучшим местом для этого является серверное событие ПриСозданииНаСервере. Мы можем использовать метод КопироватьДанныеФормы, который эффективно переносит данные из одного объекта ДанныеФормыСтруктура в другой.

Проанализируем код во второй форме:


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

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

Способ 2. Передача данных через параметры и Временное хранилище

Если таблица данных большая или форм действительно много (как упоминалось в обсуждении — до 15 штук), постоянное копирование всего объекта может быть избыточным. В таких случаях рекомендуется использовать Временное хранилище. Это «золотой стандарт» разработки в 1С для передачи тяжелых данных между контекстами.

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

  1. В основной форме выгружаем табличную часть в обычную ТаблицаЗначений.
  2. Помещаем эту таблицу во временное хранилище и получаем уникальный адрес.
  3. Передаем этот адрес как параметр при открытии второй формы.
  4. Во второй форме получаем таблицу по адресу и загружаем её в свою табличную часть.

Посмотрим на пример кода в первой форме:


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

&НаКлиенте
Процедура ОткрытьВторуюФорму()
    АдресДанных = ПоместитьТаблицуВХранилище();
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("АдресДанных", АдресДанных);
    
    ОткрытьФорму("Обработка.МояОбработка.Форма.ВтораяФорма", ПараметрыФормы);
КонецПроцедуры

Теперь рассмотрим обработку во второй форме. Нам нужно в свойстве формы «Параметры» заранее создать параметр АдресДанных (или просто обращаться к нему в коде):


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

Способ 3. Синхронизация изменений через оповещения

Часто вторая форма открывается не просто для просмотра, а для редактирования настроек, которые должны вернуться обратно в первую форму. В этом случае мы используем механизм Оповестить. Это позволяет избежать «хаоса», когда у вас открыто множество форм, и каждая должна знать об изменениях данных.

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


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

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


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

Рекомендации по выбору метода

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

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

Таким образом, «исчезновение» данных — это не ошибка программы, а следствие работы системы оптимизации 1С, которая не перекачивает лишние данные между формами без явного указания разработчика. Выбирайте наиболее подходящий под ваши задачи метод синхронизации, и ваши табличные части всегда будут заполнены корректно.

← На главную