Как передать форму или таблицу формы на сервер для получения настроек динамического списка

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

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

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

Почему нельзя просто получить настройки на клиенте?

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

Отборы = Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы;

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

  1. Потеря пользовательского поиска: Если пользователь ввел поисковый запрос вручную через стандартную строку поиска (комбинация клавиш Alt + F или верхняя панель поиска), этот отбор не попадет в коллекцию ПользовательскиеНастройки. Платформа трансформирует строку поиска во внутренний полнотекстовый фильтр непосредственно перед выполнением запроса к базе данных на сервере.
  2. Динамические и программные условия: Сложные отборы, накладываемые платформой или другими механизмами программно (например, ограничения прав доступа RLS или параметры параметризованных запросов), также не отражаются в базовом компоновщике настроек на клиенте.

Единственный способ получить абсолютно точный, финальный и актуальный отбор списка (включая ручной ввод в поле поиска) — вызвать метод ПолучитьИсполняемыеНастройкиКомпоновкиДанных() на сервере. Рассмотрим подробнее, как это реализовать.

Решение 1. Использование экспортного метода формы через расширение (Рекомендуемый способ)

Вызов серверного метода конкретной формы извне (например, из общей команды) разрешен платформой, если этот метод объявлен с ключевым словом Экспорт. При вызове Форма.ИмяМетодаНаСервере() платформа автоматически производит контекстный переход на сервер. В этот момент вся форма со всеми ее элементами воссоздается в серверной памяти, что открывает доступ к методам динамического списка.

Чтобы не модифицировать каждую типовую форму списка вручную, применим механизм расширений конфигурации. Разберем этот процесс по шагам.

Шаг 1. Добавление экспортного метода в форму списка

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


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

Шаг 2. Вызов метода из общей команды на клиенте

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


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

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

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

Решение 2. Контекстный переход через ВыполнитьКомандуНаСервере()

Если конфигурация разработана с использованием Библиотеки стандартных подсистем (БСП), мы можем использовать еще один красивый платформенный механизм. В БСП-формах стандартно присутствует встроенный метод ВыполнитьКомандуНаСервере(). Посмотрим на пример вызова этого метода из общей команды:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    // Получаем форму-источник, откуда была вызвана команда
    ФормаИсточника = ПараметрыВыполненияКоманды.Источник;
    
    // Выполняем переход на сервер через контекст формы-источника
    ФормаИсточника.ВыполнитьКомандуНаСервере();
    
КонецПроцедуры

Этот метод заставляет платформу выполнить серверный вызов в контексте вызывающей формы. При этом управление передается в обработчик формы &НаСервере, где у нас появляется полный доступ ко всем элементам управления, включая динамический список и его методы получения исполняемых настроек СКД.

Решение 3. Использование механизма подключаемых команд БСП

Для типовых конфигураций (таких как 1С:Бухгалтерия предприятия, 1С:ERP или 1С:Комплексная автоматизация) наиболее правильным с архитектурной точки зрения решением является интеграция с подсистемой "Подключаемые команды" из состава БСП.

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

  1. Команда регистрируется централизованно в общем модуле (например, через переопределяемый модуль БСП ДополнительныеОтчетыИОбработкиОпределяемый).
  2. Подсистема БСП автоматически генерирует кнопку на форме списка всех выбранных объектов.
  3. При нажатии на эту кнопку управление передается в типовой шаблонный обработчик БСП на форме списка.
  4. Поскольку обработчик выполняется внутри контекста формы, БСП имеет полный доступ к Элементы.Список на сервере. Она сама считывает все отборы, упаковывает их и передает в экспортный метод вашего общего модуля.

Использование подключаемых команд БСП полностью исключает необходимость какого-либо изменения кода самих форм списков, что существенно облегчает последующее обновление конфигурации.

Резюме

Мы подробно разобрали ограничения платформы 1С при работе с контекстом форм и нашли способы их обхода. В зависимости от архитектуры вашего решения выберите наиболее подходящий вариант:

← На главную