В практической работе разработчика 1С часто возникает задача реализации удобного пользовательского интерфейса для фильтрации данных. Типичный пример — выбор дней недели (понедельник, вторник и т.д.) для планирования или анализа графиков доставки торговых точек. Стандартно пользователи хотят видеть наглядный список дней с флажками (типа Булево), где можно отметить несколько произвольных дней, и отчет выведет только соответствующие им записи.
Разберем детально, как решить эту задачу в Системе Компоновки Данных (СКД) различными способами. Мы проанализируем ситуацию с точки зрения архитектуры базы данных, настроим параметры для управляемых форм, а также найдем обходной путь для ограничений обычных форм (толстого клиента).
Прежде чем переходить к настройке интерфейса, проанализируем техническую сторону хранения данных. Зачастую в конфигурациях можно встретить денормализованное хранение графика доставки в виде строки в реквизите справочника (например, строка "124" означает доставку по понедельникам, вторникам и четвергам). Из-за этого разработчикам приходится писать тяжелые запросы с использованием оператора ПОДОБНО (LIKE):
ВЫБОР КОГДА ТорговыеТочки.ГрафикДоставки ПОДОБНО "%1%" ТОГДА "Понедельник " ИНАЧЕ "" КОНЕЦ
Использование оператора ПОДОБНО с ведущим процентом (%1%) делает невозможным использование индексов СУБД. Это приводит к полному сканированию таблицы (Table Scan), что на больших базах данных вызывает серьезные проблемы с производительностью.
Правильное архитектурное решение:
ДниНедели со значениями: Понедельник, Вторник, Среда и т.д.ГрафикДоставкиТорговыхТочек.ТорговаяТочка (тип: СправочникСсылка.ТорговыеТочки)ДеньНедели (тип: ПеречислениеСсылка.ДниНедели)В этом случае в СКД достаточно связать таблицу торговых точек с регистром сведений левым соединением. В настройках отбора СКД поле ДеньНедели выводится стандартным образом. Платформа 1С автоматически предложит пользователю удобный выбор элементов перечисления флажками при использовании вида сравнения «В списке». Никакого дополнительного кодирования не потребуется.
Если же архитектуру базы данных менять нельзя, и дни доставки продолжают храниться в виде строки в реквизите, рассмотрим программные и настроечные обходные пути.
Выясним, как настроить удобный выбор дней недели через параметры СКД в управляемом приложении, сохранив строковый реквизит в базе данных. Поскольку прямое условие ГрафикДоставки В (&ДниНедели) не сработает (в базе лежит строка типа "14", а в параметре будет список значений ["1", "4"]), применим специальную логику в запросе.
Разберем настройку по шагам:
ДниНедели:
Строка (или Число, в зависимости от формата хранения)."1", Представление: Понедельник"2", Представление: Вторник"3", Представление: Среда"4", Представление: Четверг"5", Представление: Пятница"6", Представление: Суббота"7", Представление: ВоскресеньеДниНеделиПустые. В колонке «Выражение» пропишем формулу:
&ДниНедели.Количество() = 0. Этот параметр позволит выводить все записи, если пользователь не выбрал ни одного дня.
ДниНедели в состав быстрых настроек отчета, чтобы он отображался прямо на форме.Теперь скорректируем текст запроса СКД. Мы используем логический прием проверки вхождения элементов списка в строковое поле:
ВЫБРАТЬ
ТорговыеТочки.Ссылка КАК ТорговаяТочка,
ТорговыеТочки.Представление КАК Представление
ИЗ
Справочник.ТорговыеТочки КАК ТорговыеТочки
ГДЕ
&ДниНеделиПустые
ИЛИ ("1" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%1%")
ИЛИ ("2" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%2%")
ИЛИ ("3" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%3%")
ИЛИ ("4" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%4%")
ИЛИ ("5" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%5%")
ИЛИ ("6" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%6%")
ИЛИ ("7" В (&ДниНедели) И ТорговыеТочки.ГрафикДоставки ПОДОБНО "%7%")
При такой настройке в режиме «1С:Предприятие» пользователь увидит параметр Дни недели. При нажатии на него откроется стандартное окно списка значений, где можно проставить галочки напротив нужных дней. Запрос корректно отфильтрует данные, проверив наличие каждого выбранного символа в строке графика доставки.
В обычных формах интерфейс настройки параметров СКД не обладает гибкостью управляемого приложения. Стандартно вывести на форму удобный список с флажками непосредственно из параметров компоновщика не получится. Решим эту задачу программным путем, создав собственную панель выбора на форме отчета.
Рассмотрим пошагово алгоритм реализации:
ТЗ_ДниНедели).ТЗ_ДниНедели три колонки:
Пометка (тип: Булево) — для отображения флажка.День (тип: Строка) — скрытый идентификатор дня ("1", "2" и т.д.).Представление (тип: Строка) — понятный текст для пользователя ("Понедельник", "Вторник").ПриОткрытии программно заполним таблицу дней недели:
Процедура ПриОткрытии()
// Заполняем таблицу выбора дней
ТЗ_ДниНедели.Очистить();
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "1";
НоваяСтрока.Представление = "Понедельник";
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "2";
НоваяСтрока.Представление = "Вторник";
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "3";
НоваяСтрока.Представление = "Среда";
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "4";
НоваяСтрока.Представление = "Четверг";
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "5";
НоваяСтрока.Представление = "Пятница";
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "6";
НоваяСтрока.Представление = "Суббота";
НоваяСтрока = ТЗ_ДниНедели.Добавить();
НоваяСтрока.Пометка = Ложь;
НоваяСтрока.День = "7";
НоваяСтрока.Представление = "Воскресенье";
КонецПроцедуры
Теперь перейдем к обработке события формирования отчета. Нам необходимо перехватить построение схемы и передать отмеченные пользователем элементы в параметры СКД. Реализуем это в процедуре кнопки ДействиеСформировать на форме отчета или в модуле объекта в событии ПриКомпоновкеРезультата:
Процедура СформироватьОтчет()
// Сформируем список отмеченных дней
СписокВыбранныхДней = Новый СписокЗначений;
Для Каждого СтрокаДня Из ТЗ_ДниНедели Цикл
Если СтрокаДня.Пометка Тогда
СписокВыбранныхДней.Добавить(СтрокаДня.День);
КонецЕсли;
КонецЦикла;
// Получаем параметры СКД
ПараметрыДанных = КомпоновщикНастроек.Настройки.ПараметрыДанных;
// Передаем список в СКД
ПараметрДниНедели = ПараметрыДанных.Элементы.Найти("ДниНедели");
Если ПараметрДниНедели <> Неопределено Тогда
ПараметрДниНедели.Значение = СписокВыбранныхДней;
ПараметрДниНедели.Использование = Истина;
КонецЕсли;
// Заполняем признак пустого списка для корректной работы условия запроса
ПараметрПустые = ПараметрыДанных.Элементы.Найти("ДниНеделиПустые");
Если ПараметрПустые <> Неопределено Тогда
ПараметрПустые.Значение = (СписокВыбранныхДней.Количество() = 0);
ПараметрПустые.Использование = Истина;
КонецЕсли;
// Дальнейший стандартный вывод отчета...
КонецПроцедуры
Такой подход обеспечивает максимальное удобство: пользователь работает на обычной форме с привычными чекбоксами (флажками) прямо на рабочей панели отчета, не заходя во вложенные настройки компоновщика, а отчет генерируется быстро и корректно.