Часто в процессе разработки на платформе 1С возникает задача: при открытии формы документа или справочника проверить, есть ли записи в динамическом списке, который расположен на этой форме. Если список пуст, мы, возможно, захотим скрыть какие-то элементы управления, вывести предупреждение пользователю или изменить логику работы формы.
Рассмотрим подробнее, почему эта, казалось бы, тривиальная задача вызывает сложности, и разберем по шагам все рабочие способы ее решения.
Главная проблема проверки «при открытии» заключается в самой архитектуре платформы. Динамический список (ДС) считывает данные из базы данных порциями и делает это «лениво» (отложено), чтобы не тормозить отрисовку интерфейса. В событиях ПриСозданииНаСервере и ПриОткрытии физического обращения к базе данных может еще не произойти.
Поэтому сам список на этот момент «не знает», есть в нем данные или нет. В отличие от таблиц значений, у динамического списка нет метода Количество(), который можно было бы просто вызвать и получить результат.
Проанализируем ситуацию: как нам получить данные, полностью идентичные тем, что будут выведены пользователю, со всеми отборами, параметрами и строкой поиска? Самым надежным вариантом является программное использование СКД динамического списка. Этот метод на 100% учитывает все пользовательские настройки и права доступа (RLS).
Посмотрим на пример кода, который необходимо выполнить на сервере:
Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных();
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТЗ = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТЗ);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Если ТЗ.Количество() = 0 Тогда
// Список пуст
КонецЕсли;
Важное уточнение по оптимизации: Выполнение полного запроса через СКД может быть ресурсоемким, если список содержит тысячи строк. Чтобы не «вешать» систему, мы должны ограничить выборку. Достаточно получить всего одну строку. Для этого метод вывода прерывают после получения первой записи (например, пошагово вызывая метод процессора вывода), либо программно модифицируют схему СКД, добавляя инструкцию ПЕРВЫЕ 1. Если хотя бы одна строка получена — список не пуст.
Рассмотрим другой подход. Если отборы динамического списка жестко заданы вами программно (например, отбор по ссылке текущего документа-владельца) и пользователь не может их произвольно менять, проще и быстрее вообще не обращаться к СКД списка.
В этом случае мы пишем простейший запрос напрямую к таблице базы данных:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Таблица.Ссылка КАК Ссылка
|ИЗ
| Документ.НазваниеДокумента КАК Таблица
|ГДЕ
| Таблица.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец", ТекущийВладелец);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
// Записей нет, динамический список тоже будет пустым
КонецЕсли;
Это работает в десятки раз быстрее, чем инициализация компоновщика макета и процессора вывода.
В современных версиях платформы 1С для таблицы формы, связанной с динамическим списком, предусмотрено событие ПриПолученииДанныхНаСервере. Оно срабатывает ровно в тот момент, когда платформа получает реальную порцию данных из базы для их отрисовки.
В обработчик этого события передается параметр Ключи — массив ссылок полученных строк.
Ключи пуст — это означает, что записей для вывода нет.Нюанс: Это событие внеконтекстное и вызывается постоянно при любой прокрутке или обновлении списка. Чтобы выполнить проверку на пустоту только один раз при открытии формы, мы можем завести специальный флаг (например, реквизит формы), проверять его внутри события и менять значение после первой успешной проверки.
Среди разработчиков часто встречается ошибочное мнение, что можно проверить список так: Элементы.Список.ТекущиеДанные = Неопределено. Разберем, почему это плохая практика.
В управляемых формах свойство ТекущиеДанные может возвращать Неопределено просто потому, что фокус интерфейса при открытии формы встал на другой элемент (например, на кнопку командной панели или поле глобального поиска). При этом сами строки в таблице могут присутствовать. Попытки программно активизировать первую строку часто приводят к непредсказуемым результатам из-за асинхронной загрузки данных и вызывают визуальное мерцание интерфейса у пользователя. Этот метод является крайне ненадежным и использовать его не рекомендуется.