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