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

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

При разработке интерфейсов на управляемых формах 1С часто возникает задача отфильтровать строки табличной части документа или справочника по определенному условию. Если требуется отобрать строки по равенству конкретному значению, разработчики обычно используют стандартное свойство элемента формы ОтборСтрок. Однако при необходимости отфильтровать строки по интервалу дат (например, показать транспортные расходы за определенный период) разработчики сталкиваются с серьезным ограничением платформы.

Разберем детально, почему стандартный механизм не поддерживает интервалы, а также рассмотрим рабочие способы реализации отбора строк табличной части по диапазону дат.

Ограничения свойства ОтборСтрок управляемой формы

Выясним причину, по которой привычный подход не работает для диапазона. Свойство таблицы управляемой формы ОтборСтрок принимает значение типа ФиксированнаяСтруктура. Ключами этой структуры выступают имена реквизитов (колонок) табличной части, а значениями — фильтрующие данные.

Посмотрим на базовый синтаксис установки такого отбора:


Элементы.ТранспортныеРасходы.ОтборСтрок = Новый ФиксированнаяСтруктура("Дата", ВыбДата);

В качестве значения для ключа структуры платформа 1С допускает передачу не только единичного значения, но и объекта типа Массив (или ФиксированныйМассив). В этом случае отбор отрабатывает по условию В списке (логическое ИЛИ для каждого элемента массива):


Элементы.ТранспортныеРасходы.ОтборСтрок = Новый ФиксированнаяСтруктура("Дата", МассивДат);

Главное ограничение: механизм ОтборСтрок не поддерживает сложные виды сравнения, такие как «Интервал», «ИнтервалВключаяГраницы», «Больше или равно», «Меньше или равно» или «Содержит». Кроме того, в управляемых формах у строк таблицы формы отсутствует свойство Видимость, а через механизм Условное оформление скрыть строки целиком нельзя (доступно только изменение цвета, шрифта, текста или доступности ячеек).

Проанализируем практические способы обхода этого ограничения в зависимости от специфики задачи.

Способ 1. Формирование массива дат диапазона (для дат без времени)

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

Разберем по шагам реализацию этого варианта на клиенте:

  1. Очищаем предыдущий отбор или инициализируем новый массив.
  2. В цикле обходим все календарные дни от даты начала до даты окончания интервала, добавляя каждый день в массив.
  3. Устанавливаем свойство ОтборСтрок через ФиксированнаяСтруктура.

Посмотрим на пример кода процедуры фильтрации:


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

Важное ограничение способа: данный вариант неприменим, если реквизит содержит дату и точное время (состав даты: «Дата и время»), так как платформа выполняет строгое сравнение значений даты с точностью до секунды.

Способ 2. Использование служебного реквизита-флага

Более универсальный способ фильтрации — добавление в табличную часть дополнительного служебного реквизита (например, ПодходитПодПериод с типом Булево).

Рассмотрим алгоритм работы:

  1. При изменении диапазона дат на форме вызывается серверная процедура.
  2. На сервере строки табличной части Объект.ТранспортныеРасходы обходятся в цикле, и для каждой строки проверяется условие попадания даты в интервал. Флагу присваивается Истина или Ложь.
  3. На клиенте устанавливается отбор по равенству служебному флагу: ОтборСтрок = Новый ФиксированнаяСтруктура("ПодходитПодПериод", Истина).

Посмотрим на программную реализацию:


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

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

Такой подход корректно обрабатывает даты со временем, но требует вызова сервера для пересчета флагов при каждой смене границ диапазона.

Способ 3. Отображение данных через реквизит формы типа «ТаблицаЗначений»

Если табличная часть используется преимущественно для просмотра, расчета или специфического редактирования, таблицу формы можно привязать не к реквизиту Объект.ТранспортныеРасходы, а к отдельному реквизиту формы с типом ТаблицаЗначений.

Разберем логику работы этого метода:

  1. Полный набор данных хранится в табличной части Объект.ТранспортныеРасходы.
  2. При открытии формы или смене периода выполняется выгрузка табличной части в промежуточную таблицу или выборка запросом.
  3. Отфильтрованные строки загружаются в реквизит формы ОтображаемыеРасходы методом Загрузить().
  4. Если пользователь редактирует строки в таблице формы, перед сохранением объекта изменения синхронизируются с основной табличной частью в процедуре ПередЗаписьюНаСервере.

Посмотрим на пример выборки данных запросом:


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

Способ 4. Вынос данных в подчиненный регистр сведений

Когда объем данных в табличной части становится большим, а пользователям требуется богатый интерфейс фильтрации (по периодам, суммам, статьям расходов), оптимальным решением с точки зрения архитектуры 1С является отказ от табличной части в пользу подчиненного регистра сведений.

Рассмотрим преимущества такого перехода:

  1. Использование динамического списка: на форму элемента выводится таблица с источником данных ДинамическийСписок, связанным с регистром сведений.
  2. Полноценные отборы: для динамического списка доступен стандартный механизм Отбор системы компоновки данных. В нем штатно поддерживаются любые виды сравнения, включая ВидСравненияКомпоновкиДанных.ИнтервалВключаяГраницы, БольшеИлиРавно и МеньшеИлиРавно.
  3. Производительность: считываются только те записи, которые реально отображаются на экране, что исключает избыточную нагрузку на память при открытии формы объекта.

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


&НаСервере
Процедура УстановитьОтборПериодаВДисписке(ДатаНачала, ДатаОкончания)
    
    ЭлементОтбора = Неопределено;
    Для Каждого Элемент Из СписокТранспортныхРасходов.Отбор.Элементы Цикл
        Если Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Период") Тогда
            ЭлементОтбора = Элемент;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ЭлементОтбора = Неопределено Тогда
        ЭлементОтбора = СписокТранспортныхРасходов.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Период");
    КонецЕсли;
    
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ИнтервалВключаяГраницы;
    ЭлементОтбора.ПравоеЗначение = Новый СтандартныйПериод(ДатаНачала, ДатаОкончания);
    ЭлементОтбора.Использование = ЗначениеЗаполнено(ДатаНачала) И ЗначениеЗаполнено(ДатаОкончания);
    
КонецПроцедуры

Резюме

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

← На главную