Почему в динамическом списке 1С не работает отбор по значению "Ложь" и как это исправить?

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

Каждый разработчик «1С» рано или поздно сталкивается с классическим поведением динамических списков: при установке отбора по значению Истина система послушно показывает нужные строки, но стоит выбрать значение Ложь, как список мгновенно пустеет. При этом на экране визуально могут отображаться десятки строк с пустыми флажками, которые пользователь логично ассоциирует со значением Ложь.

В этой статье мы подробно разберем природу этого явления, выясним, почему так происходит на уровне СУБД и платформы «1С:Предприятие», и рассмотрим эффективные способы решения этой проблемы.

В чем суть проблемы и почему она возникает?

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

Рассмотрим фрагмент исходного запроса, который вызывает подобное поведение:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    РеализацияТоваровУслуг.Ссылка,
    РегистрПараметрыОбъекта.НаличиеДокументаОригинала
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РегистрПараметрыОбъекта КАК РегистрПараметрыОбъекта
        ПО РеализацияТоваровУслуг.Ссылка = РегистрПараметрыОбъекта.СсылкаНаДокумент.Ссылка

Поле НаличиеДокументаОригинала имеет тип Булево. Однако из-за использования левого соединения для тех документов РеализацияТоваровУслуг, по которым еще нет записей в регистре сведений РегистрПараметрыОбъекта, СУБД возвращает специальное пустое значение — NULL.

В результате в колонке динамического списка образуется так называемый составной тип данных: Булево и NULL. Платформа «1С:Предприятие» обрабатывает его следующим образом:

  1. На уровне интерфейса поле отображается в виде стандартного флажка (галочки).
  2. Если значение в базе данных равно Истина, флажок устанавливается.
  3. Если значения в базе данных нет (оно равно NULL) или оно равно физической Ложь, флажок отображается как пустой. Для пользователя оба эти состояния выглядят абсолютно одинаково.

Однако при попытке установить стандартный отбор по значению Ложь происходит сбой логики:

---

Способ 1. Использование функции ЕСТЬNULL в запросе (Основное решение)

Самый правильный и надежный способ решить эту проблему — избавиться от значений NULL еще на этапе выполнения запроса на сервере СУБД. Для этого применяется стандартная функция языка запросов «1С» ЕСТЬNULL.

Давайте преобразуем наше поле в запросе динамического списка. Вместо прямого выбора поля пропишем конструкцию, которая принудительно заменяет все пустые значения NULL на логическое значение ЛОЖЬ:


ЕСТЬNULL(РегистрПараметрыОбъекта.НаличиеДокументаОригинала, ЛОЖЬ) КАК НаличиеДокументаОригинала

Посмотрим, как будет выглядеть исправленный и готовый к работе запрос динамического списка целиком:


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

Что это нам дает?

  1. Поле в динамическом списке приобретает строго один тип данных — Булево (вместо составного типа с NULL).
  2. При установке отбора по значению "Ложь" система будет искать строки со значением Ложь. Поскольку все пустые связи на уровне базы данных теперь возвращают Ложь, отбор сработает корректно и вернет пользователю все нужные документы.

---

Способ 2. Настройка отбора пользователем без изменения конфигурации

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

Разберем, как обойти ограничение по шагам через пользовательский интерфейс:

  1. В форме списка нажмите кнопку Еще и выберите пункт Настроить список....
  2. Перейдите на вкладку Отбор.
  3. Добавьте поле Наличие документа оригинала в список отборов.
  4. В колонке Вид сравнения вместо стандартного значения "Равно" установите значение Не заполнено.

С точки зрения СКД вид сравнения Не заполнено транслируется в SQL-условие ЕСТЬ NULL. Таким образом, система выберет все документы, по которым в регистре сведений физически отсутствуют записи. Визуально это как раз те документы, у которых флажок снят.

---

Важное дополнение: Оптимизация неявного соединения в запросе

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


ПО РеализацияТоваровУслуг.Ссылка = РегистрПараметрыОбъекта.СсылкаНаДокумент.Ссылка

Обратите внимание на конструкцию РегистрПараметрыОбъекта.СсылкаНаДокумент.Ссылка. Использование обращения "через точку" к реквизиту ссылочного типа в условии соединения является грубой ошибкой проектирования запросов в среде «1С».

Поле СсылкаНаДокумент в регистре сведений уже хранит ссылку на документ РеализацияТоваровУслуг. Обращаясь к свойству .Ссылка этого поля, мы заставляем СУБД выполнять дополнительное неявное соединение с таблицей документов для получения значения ссылки, которое у нас уже и так есть.

Это приводит к существенному снижению производительности при формировании списка, генерации лишней нагрузки на сервер СУБД и замедлению работы интерфейса у пользователей при росте объема данных.

Для оптимизации запроса необходимо избавиться от обращения к свойству ссылки:


// Неправильно:
ПО РеализацияТоваровУслуг.Ссылка = РегистрПараметрыОбъекта.СсылкаНаДокумент.Ссылка

// Правильно:
ПО РеализацияТоваровУслуг.Ссылка = РегистрПараметрыОбъекта.СсылкаНаДокумент

Исправление этого условия уберет лишнее неявное соединение таблиц на уровне СУБД и ускорит открытие и прокрутку динамического списка.

← На главную