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