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