Как проверить, пуст ли динамический список в 1С

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

В разработке на платформе 1С:Предприятие 8.3 часто возникает задача управления интерфейсом в зависимости от наполненности динамического списка. Типичный пример: скрытие таблицы «Аналоги» или «Связанные документы», если для текущего объекта данных нет. Однако стандартная проверка через Элементы.ИмяСписка.ТекущиеДанные часто подводит разработчиков, так как свойство ТекущиеДанные может принимать значение Неопределено не только когда список пуст, но и в моменты обновления параметров, смены фокуса или до завершения отрисовки формы.

В этой статье мы подробно разберем, почему проверка по текущей строке «не канает», и проанализируем надежные программные способы определения пустоты динамического списка.

Почему проверка через ТекущиеДанные ненадежна?

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

Способ 1. Использование метода ПолучитьДанныеДинамическогоСписка

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

Разберем по шагам, как применить этот метод для нашей задачи:

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

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


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

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

Способ 2. Оптимизированный запрос «ВЫБРАТЬ ПЕРВЫЕ 1»

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

Допустим, у нас есть список аналогов, связанный с текущей номенклатурой. Вместо анализа всего ДС, мы выполним быстрый запрос:


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

Этот подход считается наиболее быстрым для СУБД, так как поиск прекращается сразу после нахождения первой подходящей записи (использование оператора ВЫБРАТЬ ПЕРВЫЕ 1).

Способ 3. Получение схемы и выполнение через компоновщик

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

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


Схема = Элементы.СписокАналогов.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.СписокАналогов.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаРезультат = ПроцессорВывода.Вывести(ПроцессорКомпоновки);

СписокПуст = (ТаблицаРезультат.Количество() = 0);

Этот метод универсален, так как он учитывает все пользовательские настройки (фильтры, которые пользователь поставил в меню «Настроить список»), но он довольно ресурсозатратный для простой проверки на пустоту.

Альтернативные подходы к интерфейсу

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

Подводя итог, можно сказать, что выбор метода зависит от сложности запроса динамического списка и требований к производительности. Для простых связей идеально подходит ВЫБРАТЬ ПЕРВЫЕ 1, для сложных списков с пользовательскими фильтрами — ПолучитьДанныеДинамическогоСписка.

← На главную