В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает ситуация, когда в динамическом списке (например, в журнале документов «Чеки ККМ» в конфигурации «Розница») накапливается огромное количество данных. Если открывать такой список без предварительной фильтрации, система пытается считать все записи, что приводит к длительному ожиданию. Пользователи часто жалуются на «зависание» формы при открытии.
Рассмотрим, как правильно установить отбор по дате программно в момент создания формы, чтобы данные отсекались на уровне запроса к СУБД, а интерфейс оставался отзывчивым и понятным для пользователя.
Разберем типичную ошибку. Часто разработчики пытаются установить период через свойство формы Элементы.Список.Период уже после того, как форма открыта. Проблема заключается в том, что если данные уже начали считываться, применение фильтра постфактум не отменяет первичную нагрузку на базу данных. Кроме того, установка простого равенства дат ВидСравнения.Равно часто не находит записей, так как в 1С тип Дата всегда содержит время (часы, минуты, секунды), и точное совпадение с «началом дня» случается редко.
Если нам важно, чтобы пользователь видел установленный период в верхней части списка (в панели быстрых отборов) и мог его легко изменить, воспользуемся объектом СтандартныйПериод. Проанализируем пример кода, который эффективно работает в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Формируем новый период (например, за сегодня)
НовыйПериод = Новый СтандартныйПериод;
НовыйПериод.Вариант = ВариантСтандартногоПериода.Сегодня;
// Напрямую заполняем свойства элемента формы
ЗаполнитьЗначенияСвойств(Элементы.Список.Период, НовыйПериод);
// Обновляем список для применения настроек
Элементы.Список.Обновить();
КонецПроцедуры
Этот метод хорош тем, что он «штатный». Он корректно взаимодействует с механизмом динамического списка, если у того в настройках указана основная таблица. Пользователь сразу увидит надпись «Сегодня» в поле периода.
Когда требуется более гибкий подход или нужно установить отбор по полю, которое не является стандартным периодом (например, «Дата оплаты»), мы обращаемся к Компоновщику настроек. Здесь важно понимать разницу между коллекциями. Выясним причину, почему код может не срабатывать: если вы добавляете отбор в Настройки, он может быть перекрыт ПользовательскимиНастройками.
Рассмотрим наиболее надежный вариант добавления отбора через коллекцию Отбор.Элементы. Чтобы избежать проблем со временем в датах, будем использовать вид сравнения БольшеИлиРавно.
&НаСервере
Процедура УстановитьОтборПоДате(ДатаНачала)
// Получаем коллекцию отборов динамического списка
КоллекцияОтборов = Список.Отбор.Элементы;
// Проверяем, нет ли уже установленного отбора по этому полю, чтобы не дублировать
ПолеДата = Новый ПолеКомпоновкиДанных("Дата");
ЭлементОтбора = Неопределено;
Для Каждого Элемент Из КоллекцияОтборов Цикл
Если Элемент.ЛевоеЗначение = ПолеДата Тогда
ЭлементОтбора = Элемент;
Прервать;
КонецЕсли;
КонецЦикла;
// Если не нашли — создаем новый
Если ЭлементОтбора = Неопределено Тогда
ЭлементОтбора = КоллекцияОтборов.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = ПолеДата;
КонецЕсли;
// Устанавливаем параметры отбора
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
ЭлементОтбора.ПравоеЗначение = НачалоДня(ДатаНачала);
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный;
КонецПроцедуры
Обратите внимание на свойство РежимОтображения. Установив значение Обычный, мы позволяем пользователю увидеть этот отбор в окне «Настройка списка» и при необходимости отключить его.
Если ваша задача — жестко ограничить данные (например, запретить видеть документы прошлых периодов в конкретном АРМ), следует использовать ФиксированныеНастройки. Посмотрим на пример, как это реализовать. Такие настройки накладываются поверх всех пользовательских фильтров и не могут быть изменены пользователем в интерфейсе.
&НаСервере
Процедура УстановитьЖесткийФильтр()
ГруппаОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор;
НовыйЭлемент = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Дата");
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
НовыйЭлемент.ПравоеЗначение = НачалоДня(ТекущаяДата());
НовыйЭлемент.Использование = Истина;
КонецПроцедуры
Этот метод гарантирует, что запрос к базе данных будет содержать условие WHERE с самого начала, что критически важно для производительности на больших таблицах.
Проанализируем ситуацию, когда разработка ведется в расширении (как в исходном вопросе). При использовании обработчиков &После("ПриСозданииНаСервере") нужно быть осторожным. Если в основной конфигурации уже прописана логика восстановления настроек пользователя, ваш программный код может выполниться, но затем система «накроет» его сохраненными ранее настройками конкретного пользователя.
Совет: Чтобы ваш отбор гарантированно применился, попробуйте принудительно очистить пользовательские настройки отбора перед установкой своих или используйте именно ФиксированныеНастройки.
Подведем итог. Для быстрой и корректной работы динамического списка по дате мы рекомендуем:
Соблюдение этих правил позволит сделать работу пользователей в системе комфортной, а открытие журналов документов — мгновенным.