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

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

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

Проанализируем основную концепцию: формы действительно изолированы. Прямая "параллельная" работа с одним и тем же объектом данных в памяти из двух разных форм невозможна. Поэтому наша задача — реализовать механизм обмена данными между ними. Рассмотрим самый надежный и распространенный способ.

Метод 1: Обмен данными через параметры и оповещения

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

  1. Передача данных при открытии дополнительной формы.

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

    Важно использовать два ключевых параметра этого метода:

    • ПараметрыФормы — сюда мы поместим наши данные. Рекомендуется передавать параметры в виде структуры.
    • ОписаниеОповещенияОЗакрытии — этот параметр "подписывает" основную форму на событие закрытия дополнительной. Когда дополнительная форма закроется, система вызовет указанную нами процедуру-обработчик в основной форме.

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

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

    Теперь в дополнительной (второй) форме нужно принять переданные данные. Это делается в событии ПриСозданииНаСервере. Мы проверяем, были ли переданы параметры, и если да — загружаем их в табличную часть этой формы.

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

    После выполнения этого кода дополнительная форма откроется с данными, которые были в основной форме на момент ее вызова.

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

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

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

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

    Этот шаг — завершающий. После того как дополнительная форма закрылась, сработает оповещение, которое мы создали на первом шаге. Система вызовет процедуру-обработчик ПослеРедактированияДетально в основной форме.

    Эта процедура должна быть экспортной и находиться на клиенте. Она принимает два параметра: РезультатЗакрытия и ДополнительныеПараметры. В РезультатЗакрытия как раз и будет наша измененная таблица значений.

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

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

Оптимизация для больших объемов данных: Временное хранилище

Если ваша табличная часть содержит тысячи строк, передавать ее целиком между клиентом и сервером, а также между формами, может быть накладно с точки зрения производительности. В этом случае лучше использовать временное хранилище.

Схема работы остается той же, но вместо самой таблицы значений мы передаем ее адрес во временном хранилище:

  1. В основной форме: перед открытием дополнительной формы помещаем таблицу значений во временное хранилище с помощью ПоместитьВоВременноеХранилище(). В параметры формы передаем полученный адрес (строку).
  2. В дополнительной форме: в ПриСозданииНаСервере получаем адрес из параметров и извлекаем данные с помощью ПолучитьИзВременногоХранилища().
  3. При закрытии дополнительной формы: снова помещаем измененную таблицу во временное хранилище и возвращаем ее новый адрес через метод Закрыть().
  4. В основной форме: в обработчике оповещения получаем адрес, извлекаем данные и загружаем их в свою ТЧ.

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

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

Прежде чем реализовывать сложный механизм обмена между формами, стоит задать себе вопрос: а действительно ли нужны две разные формы? Часто ту же задачу можно решить проще и элегантнее в рамках одной формы.

Рассмотрим вариант с использованием страниц (вкладок):

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

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

← На главную