Как перехватить изменение периода в обычной форме списка 1С?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

При разработке на обычных формах в 1С часто возникает задача: перехватить событие изменения периода в форме списка документов (например, в списке «Реализация товаров и услуг»). Цель — проверить условия и, при необходимости, отказаться от применения выбранного отбора, чтобы не допустить формирования слишком тяжелых запросов. Рассмотрим, с какими ограничениями платформы мы сталкиваемся и как правильно решить эту задачу.

Ограничения платформы в обычных формах

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

Если для отбора используется вид сравнения «В списке» с передачей массива из тысяч ссылок на документы (например, полученных отдельным запросом по сложным условиям), это считается жестким антипаттерном. Выясним причину: на уровне системы управления базами данных (СУБД) такой отбор преобразуется в конструкцию IN (...) с огромным количеством параметров. Это вызывает сильную деградацию производительности, длительный поиск, блокировки, а при превышении внутренних лимитов SQL-сервера на количество параметров в запросе форма может аварийно завершить работу.

Надежный способ перехвата периода: собственная кнопка

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

  1. Откройте форму списка в конфигураторе. В свойствах командной панели списка снимите флажок Автозаполнение. Если автозаполнение необходимо оставить, вручную удалите или скройте стандартную кнопку «Установить интервал дат».
  2. Добавьте на командную панель свою собственную кнопку и назначьте ей стандартную пиктограмму выбора периода, чтобы для пользователя интерфейс остался привычным.
  3. Создайте обработчик нажатия для этой кнопки. Внутри обработчика используйте глобальный метод ВвестиПериод() для вызова диалога выбора дат.
  4. После того как пользователь введет даты, проанализируем выбранный интервал. Если он удовлетворяет вашим условиям (например, не превышает один месяц), применим период к списку программно с помощью ДокументСписок.Отбор.Дата.Установить(). Если интервал слишком большой, выведем предупреждение и прервем выполнение.

Посмотрим на пример реализации обработчика нажатия нашей кнопки:


Процедура ДействиеУстановитьПериод(Кнопка)
    
    НачалоПериода = ДокументСписок.Отбор.Дата.ЗначениеС;
    КонецПериода = ДокументСписок.Отбор.Дата.ЗначениеПо;
    
    Если ВвестиПериод(НачалоПериода, КонецПериода, "Выберите период") Тогда
        // Проверяем, что период не больше 31 дня
        Если (КонецПериода - НачалоПериода) > 31 * 24 * 60 * 60 Тогда
            Предупреждение("Выбран слишком большой период! Пожалуйста, выберите интервал не более месяца.");
            Возврат;
        КонецЕсли;
        
        // Устанавливаем отбор
        ДокументСписок.Отбор.Дата.Использование = Истина;
        ДокументСписок.Отбор.Дата.ВидСравнения = ВидСравнения.ИнтервалВключаяГраницы;
        ДокументСписок.Отбор.Дата.ЗначениеС = НачалоПериода;
        ДокументСписок.Отбор.Дата.ЗначениеПо = КонецПериода;
    КонецЕсли;

КонецПроцедуры

Альтернативные варианты сложных отборов в обычных формах

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

1. Использование Критериев отбора

Если дополнительное свойство можно типизировать и привязать к реквизитам документов, создайте объект метаданных «Критерий отбора». Формы списков в 1С умеют штатно и быстро фильтроваться по критериям отбора. Платформа сама сгенерирует оптимальный запрос без необходимости программно собирать массивы.

2. Использование Построителя отчета

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

3. Денормализация данных

Если по определенному реквизиту или свойству отбор требуется постоянно и для всех пользователей, добавьте этот реквизит непосредственно в шапку документа и установите для него признак «Индексировать». Это потребует изменения метаданных и создания подписки на событие (или обработки при записи) для синхронизации значения. Однако это позволит использовать стандартный, очень быстрый отбор по реквизиту без жестких ограничений по периоду, так как СУБД будет использовать индекс.

4. Использование Таблицы значений

Если период всегда жестко ограничен (например, пользователи никогда не смотрят документы более чем за текущий месяц), список можно получать собственным сложным запросом с нужными соединениями и выгружать в Таблицу Значений, которая будет источником данных для табличного поля на форме. Для имитации стандартного поведения платформы, в обработчики ПриВыводеСтроки или ПриПолученииДанных добавляется код для отображения стандартных пиктограмм (статус проведения, пометка удаления и т.д.).

← На главную