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