Как установить отбор строк в Таблице значений на форме по интервалу дат?

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

В процессе разработки интерфейсов на управляемых формах 1С мы часто сталкиваемся с необходимостью фильтрации данных в таблицах. Если речь идет о Динамическом списке, то там все просто: платформа предоставляет мощные механизмы отборов, включая операторы «Больше», «Меньше», «В Списке» и т.д. Однако, когда мы работаем с ТаблицаЗначений, размещенной на форме, ситуация кардинально меняется.

Разберем проблему, поднятую автором: есть Таблица значений, и нужно наложить отбор по периоду (интервалу дат). Стандартное решение через Элементы.ТЗ.ОтборСтрок в данном случае не срабатывает очевидным образом. Проанализируем, почему так происходит, и рассмотрим проверенные способы решения этой задачи.

Почему не работает стандартный ОтборСтрок?

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

Важно понимать: Структура подразумевает поиск только на полное соответствие (равенство). Мы не можем передать в структуру условие вида «Дата >= 01.01.2024». Мы можем лишь сказать платформе: «Покажи строки, где Дата РАВНА 01.01.2024». Именно поэтому попытка использовать стандартный синтаксис для интервалов обречена на неудачу.

Тем не менее, задача распространенная, и мы рассмотрим три основных подхода к её реализации.

Способ 1. Использование служебной колонки (Метод «Флага»)

Этот метод является одним из самых надежных и простых в реализации. Идея заключается в том, чтобы переложить логику проверки условия (попадает ли дата в интервал) на наш код, а платформе оставить задачу фильтрации по простому равенству (Истина/Ложь).

Алгоритм действий:

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

Рассмотрим пример кода реализации:


&НаКлиенте
Процедура ПриИзмененииПериодаОтбора(Команда)
    // Вызываем серверную процедуру для обработки данных
    УстановитьОтборНаСервере();
КонецПроцедуры

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

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

Этот метод хорош тем, что мы сохраняем все строки в таблице, просто скрываем ненужные. Итоги в подвале (если они есть и настроены стандартно) пересчитаются корректно для видимых строк.

Способ 2. Перезаполнение отображаемой таблицы (Master-Detail)

Если строк в таблице немного, или вам требуется сложная логика фильтрации, которую трудно уложить в один флаг, можно использовать подход с двумя таблицами.

Суть метода:

Посмотрим, как это выглядит в коде:


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

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

Способ 3. Использование Построителя запроса или Временных таблиц

Если таблица значений очень большая, перебирать её циклом Для Каждого может быть медленно. В таких случаях мы можем задействовать мощь языка запросов 1С. Для этой задачи есть консоль запросов и кода для управляемых форм.

Мы можем поместить нашу Таблицу значений во временную таблицу запроса, отфильтровать её с помощью оператора МЕЖДУ и выгрузить результат обратно.

Пример реализации через Менеджер временных таблиц:


&НаСервере
Процедура ФильтрацияЗапросом()
    
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    
    // 1. Помещаем ТЗ во временную таблицу
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ТЗ.ДатаДокумента КАК ДатаДокумента,
        |   ТЗ.Сумма КАК Сумма,
        |   ТЗ.Контрагент КАК Контрагент
        |ПОМЕСТИТЬ ВТ_Данные
        |ИЗ
        |   &ТЗ КАК ТЗ";
        
    Запрос.УстановитьПараметр("ТЗ", ПолнаяТаблицаДанных);
    Запрос.Выполнить();
    
    // 2. Выбираем с фильтром
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ВТ.ДатаДокумента,
        |   ВТ.Сумма,
        |   ВТ.Контрагент
        |ИЗ
        |   ВТ_Данные КАК ВТ
        |ГДЕ
        |   ВТ.ДатаДокумента МЕЖДУ &ДатаНачала И &ДатаОкончания";
        
    Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаНачала));
    Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));
    
    // Выгружаем результат прямо в реквизит формы (если типы совпадают)
    ТаблицаНаФорме.Загрузить(Запрос.Выполнить().Выгрузить());
    
КонецПроцедуры

Способ 4. Условное оформление (Видимость)

В теме также упоминался способ через условное оформление. Вы можете настроить свойство УсловноеОформление формы, задав отбор по дате и установив свойство Видимость = Ложь для неподходящих строк.

Почему мы не рекомендуем этот способ как основной:

  1. Проблема итогов: Если в подвале таблицы считаются суммы, то при скрытии строк через условное оформление суммы не изменятся. Пользователь увидит 2 строки на экране, а сумму в подвале — за 100 строк. Это вводит в заблуждение.
  2. Проблема навигации: Если скрыть 99% строк, полоса прокрутки может вести себя неадекватно, и при прокрутке возможны "тормоза", так как платформе приходится обрабатывать и скрывать элементы на лету.

Этот метод подходит только для небольшой подсветки или скрытия малого количества строк, где итоги не важны.

Резюме

Так как ТаблицаЗначений не поддерживает сложные отборы "из коробки" в интерфейсе:

← На главную