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