Как полностью скрыть записи в списке журнала документов, если основной фильтр не выбран?

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

При разработке интерфейсов на обычных формах 1С 8.x часто возникает классическая задача: связать два табличных поля. Например, в верхнем списке отображаются контрагенты, а в нижнем — документы, относящиеся исключительно к выбранному контрагенту. Однако разработчики сталкиваются с проблемой: если пользователь накладывает фильтр на верхний список и он становится пустым, нижний список (журнал документов) может продолжать отображать записи или показывать документы с незаполненным полем связи. В этой статье мы подробно разберем, как сделать так, чтобы при отсутствии активной строки в основном списке подчиненный журнал гарантированно оставался пустым.

Анализ проблемы: почему стандартный отбор не всегда работает

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

Многие начинающие программисты пытаются установить отбор по пустой ссылке или значению Неопределено. Разберем, почему это не совсем корректно:

  1. Отбор по пустой ссылке: Если мы установим Отбор.Контрагент.Значение = Справочники.Контрагенты.ПустаяСсылка(), система покажет все документы, в которых контрагент действительно не указан. Это не то же самое, что "пустой список", так как такие документы могут существовать в базе.
  2. Отбор по Неопределено: Результат часто аналогичен первому пункту или вовсе игнорируется системой, оставляя список документов полным.

Проанализируем ситуацию: нам нужно условие, которое заведомо не может быть выполнено ни одной записью в базе данных. Выясним причину, почему лучшим решением здесь выступает использование системного поля Ссылка.

Способ 1: Использование отбора по полю Ссылка

Как было отмечено в обсуждении, поле Ссылка является уникальным идентификатором объекта. Если мы установим отбор по этому полю, передав туда значение, которого нет среди документов данного типа, список гарантированно будет пустым. Рассмотрим, как это реализовать программно в обработчике ПриАктивизацииСтроки.

Посмотрим на пример кода:


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

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

Способ 2: Вид сравнения «В списке» с пустым списком значений

Это еще более надежный и универсальный метод. Мы можем установить вид сравнения ВидСравнения.ВСписке и передать в качестве значения абсолютно пустой СписокЗначений. Логика проста: система пытается найти записи, идентификаторы которых входят в предоставленный перечень. Если перечень пуст, ни одна запись не попадет в выборку.

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

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

// Создаем пустой список для блокировки данных
ПустойСписок = Новый СписокЗначений;

// Обращаемся к отбору журнала
ОтборПоСсылке = ЭлементыФормы.ЖурналДокументовСписок.Значение.Отбор.Ссылка;
ОтборПоСсылке.ВидСравнения = ВидСравнения.ВСписке;
ОтборПоСсылке.Значение = ПустойСписок;
ОтборПоСсылке.Использование = Истина;

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

Способ 3: Проверка количества строк и программная оптимизация

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

Также следует проверять не только ТекущаяСтрока, но и общее количество строк в источнике данных верхнего поля. Рассмотрим улучшенный алгоритм:


Процедура СписокВерхнийПриАктивизацииСтроки(Элемент)
    
    // Получаем доступ к отбору нижнего списка
    ТекущийОтбор = ЭлементыФормы.ЖурналНижний.Значение.Отбор;
    
    // Если в верхнем списке нет записей (результат фильтрации пользователем)
    Если Элемент.Значение.Количество() = 0 Тогда
        
        // Если блокировка еще не установлена, устанавливаем её
        Если Не ТекущийОтбор.Ссылка.Использование Тогда
            ТекущийОтбор.Ссылка.ВидСравнения = ВидСравнения.Равно;
            ТекущийОтбор.Ссылка.Установить(Документы.РеализацияТоваровУслуг.ПустаяСсылка());
            // Отключаем другие отборы, чтобы не конфликтовали
            ТекущийОтбор.Контрагент.Использование = Ложь;
        КонецЕсли;
        
    Иначе
        // Есть данные — работаем в обычном режиме
        ТекущаяСтрока = Элемент.ТекущаяСтрока;
        Если ТекущаяСтрока <> Неопределено Тогда
            ТекущийОтбор.Ссылка.Использование = Ложь;
            ТекущийОтбор.Контрагент.Установить(ТекущаяСтрока.Контрагент);
            ТекущийОтбор.Контрагент.Использование = Истина;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Дополнительные рекомендации по юзабилити

Проанализируем визуальную составляющую. Когда нижний список пуст, пользователь может не сразу понять, почему документов нет — то ли их действительно не существует для данного контрагента, то ли фильтр работает некорректно. Рассмотрим дополнительные приемы:

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

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

← На главную