Как реализовать динамический список с произвольным запросом в 1С 8.1 на обычных формах

Программист IT и автоматизация бизнеса
← На главную

Разработчики, переходящие с версии 1С 8.3 на старые конфигурации версии 8.1, часто сталкиваются с отсутствием привычного объекта ДинамическийСписок. В управляемых формах этот объект позволяет легко прописать произвольный SQL-подобный запрос, добавить расчетные поля и сложные соединения. Однако в версии 8.1 объекты типа ДокументСписок или СправочникСписок жестко привязаны к соответствующим таблицам базы данных, и напрямую изменить их текст запроса невозможно.

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

Метод 1. Использование Таблицы Значений (ТЗ) как источника данных

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

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

Недостатки: Отсутствие динамической подгрузки данных. Если в выборке будут десятки тысяч строк, форма будет открываться крайне медленно, а оперативная память клиента — переполняться.

Проанализируем алгоритм реализации:

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

Посмотрим на пример кода для заполнения такой таблицы:


Процедура ОбновитьСписок()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   РеализацияТоваровУслуг.Ссылка КАК Ссылка,
        |   РеализацияТоваровУслуг.Дата КАК Дата,
        |   РеализацияТоваровУслуг.Номер КАК Номер,
        |   РеализацияТоваровУслуг.Контрагент КАК Контрагент,
        |   ВЫБОР КОГДА РеализацияТоваровУслуг.СуммаДокумента > 100000 
        |       ТОГДА ""Крупный"" ИНАЧЕ ""Обычный"" КОНЕЦ КАК Категория
        |ИЗ
        |   Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг";
    
    РезультатЗапроса = Запрос.Выполнить();
    ТаблицаНаФорме = РезультатЗапроса.Выгрузить();
    
    // Передаем данные в элемент управления на форме
    ЭлементыФормы.ТабличноеПолеДанные.Значение = ТаблицаНаФорме;
    ЭлементыФормы.ТабличноеПолеДанные.СоздатьКолонки();
КонецПроцедуры

Чтобы данные были актуальными, вызовем эту процедуру при открытии формы или по обработчику оповещения, если данные в базе изменились.

Метод 2. Расчетные колонки через событие ПриПолученииДанных

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

Важное уточнение: Многие начинающие программисты используют событие ПриВыводеСтроки. Это большая ошибка для производительности, так как это событие вызывается для каждой строки отдельно. Если внутри него делать запрос к базе, вы получите классическую проблему "N+1 запрос", что приведет к "тормозам" при прокрутке списка.

Разберем правильный подход с использованием ПриПолученииДанных. Это событие получает сразу массив строк, которые видны пользователю на экране в данный момент.


Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
    // Собираем все ссылки на документы, которые видны на экране
    МассивСсылок = Новый Массив;
    СоответствиеСтрок = Новый Соответствие;
    
    Для Каждого Оформление Из ОформленияСтрок Цикл
        МассивСсылок.Добавить(Оформление.ДанныеСтроки.Ссылка);
        СоответствиеСтрок.Вставить(Оформление.ДанныеСтроки.Ссылка, Оформление);
    EndЦикла;
    
    // Выполняем ОДИН запрос ко всем видимым объектам
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ДополнительныеСведения.Объект КАК Ссылка,
        |   ДополнительныеСведения.Значение КАК СтатусОплаты
        |ИЗ
        |   РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
        |ГДЕ
        |   ДополнительныеСведения.Объект В(&МассивСсылок)";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    Выборка = Запрос.Выполнить().Выбрать();
    
    // Распределяем полученные данные по ячейкам оформления строк
    Пока Выборка.Следующий() Цикл
        Оформление = СоответствиеСтрок.Получить(Выборка.Ссылка);
        Если Оформление <> Неопределено Тогда
            Оформление.Ячейки.СтатусОплаты.УстановитьТекст(Строка(Выборка.СтатусОплаты));
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Метод 3. Отбор по результатам произвольного запроса

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

Рассмотрим прием «Предварительная выборка». Мы сначала программно выполняем сложный запрос, получаем список ссылок, а затем накладываем фильтр на стандартный ДокументСписок.

Проанализируем шаги:

  1. Выполняем запрос, который возвращает только колонку Ссылка.
  2. Выгружаем эти ссылки в СписокЗначений.
  3. Устанавливаем отбор в элементе управления ДокументСписок по виду сравнения ВСписке.

// Пример установки сложного фильтра
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.ЗаказПокупателя ГДЕ СуммаДокумента > 50000");
СписокСсылок = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

ДокументСписок.Отбор.Ссылка.Использовать = Истина;
ДокументСписок.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВСписке;
ДокументСписок.Отбор.Ссылка.Значение.ЗагрузитьЗначения(СписокСсылок);

Внимание: У этого метода есть ограничение со стороны СУБД (например, MS SQL Server). Если список ссылок будет содержать десятки тысяч элементов, запрос платформы к базе данных может стать слишком длинным и вызвать ошибку переполнения параметров SQL.

Метод 4. Использование Системы Компоновки Данных (СКД) на форме

Мало кто помнит, но в 1С 8.1 уже была СКД. Хотя её чаще использовали для отчетов, мы можем создать схему компоновки, результат которой будет выводиться в ПолеТабличногоДокумента или ТабличноеПоле прямо на форме.

Этот способ максимально приближен к «Динамическому списку» 8.3 по своей идеологии, так как СКД берет на себя построение запроса, отборы и группировки. Однако реализация интерактивности (открытие формы документа по клику) в 8.1 для СКД потребует ручного написания кода в событии Выбор.

Выясним причину выбора конкретного метода

Выбор решения зависит от объема данных и требований к интерфейсу:

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

← На главную