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

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

При разработке управляемых форм в 1С часто возникает задача предоставить пользователю возможность динамической настройки отборов. Однако попытка настроить реквизит типа ОтборКомпоновкиДанных внутри строки таблицы значений или дерева значений напрямую на сервере приводит к характерным ошибкам платформы. Рассмотрим причины этих ошибок и разберем проверенные способы правильной организации отборов для каждой строки таблицы.

Анализ причин возникающих ошибок

Проанализируем базовый пример кода, в котором разработчики сталкиваются с двумя ключевыми проблемами платформы 1С:

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

Кроме того, класс ПостроительОтчета является устаревшим механизмом (legacy). В современных управляемых формах для получения структуры реквизитов следует использовать объектную модель метаданных Метаданные или механизмы Схемы Компоновки Данных (СКД).

Способ 1. Получение состава полей через объектную модель метаданных

Если задача заключается только в получении реквизитов метаданных по имени объекта без использования ПостроительОтчета, разберем, как получить список полей программно на сервере:


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

Способ 2. Инициализация отбора через Компоновщик Настроек СКД

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


&НаСервере
Процедура ИнициализироватьКомпоновщикОтбора(ИмяТаблицыМетаданных)
    // 1. Динамически создаем схему компоновки данных
    Схема = Новый СхемаКомпоновкиДанных;
    
    Источник = Схема.ИсточникиДанных.Добавить();
    Источник.Имя = "ИсточникДанных1";
    Источник.ТипИсточникаДанных = "Local";
    
    НаборДанных = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
    НаборДанных.Имя = "НаборДанных1";
    НаборДанных.ИсточникДанных = Источник.Имя;
    НаборДанных.Запрос = "ВЫБРАТЬ * ИЗ " + ИмяТаблицыМетаданных;
    НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;
    
    // 2. Помещаем схему во временное хранилище
    АдресСхемы = ПоместитьВоВременноеХранилище(Схема, УникальныйИдентификатор);
    
    // 3. Инициализируем компоновщик настроек формы
    КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы));
КонецПроцедуры

Способ 3. Организация индивидуального отбора для каждой строки таблицы

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

Разберем алгоритм реализации этого подхода:

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

Посмотрим на реализацию клиентской части при смене активной строки:


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

И серверная процедура для переключения настроек отбора:


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

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

← На главную