Как программно добавить динамические колонки в динамический список для отображения связанных данных?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача отобразить данные в виде "развертки" или матрицы. Например, у нас есть список документов (заказов или задач), и мы хотим видеть в колонках не просто реквизиты самого документа, а наличие в них определенных услуг или сотрудников. Классический пример: в строках — документы, в колонках — фамилии сотрудников, а на пересечении — флажок, указывающий, участвует ли данный сотрудник в этой задаче.

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

Способ 1. Программная модификация текста запроса (Рекомендуемый)

Этот метод считается наиболее правильным и производительным, так как он позволяет пользователю использовать стандартные функции платформы: сортировку, поиск и отбор по созданным колонкам. Суть метода заключается в том, чтобы при создании формы динамически изменить текст запроса динамического списка, добавив в него вычисляемые поля для каждого объекта (например, сотрудника).

Проанализируем алгоритм реализации этого метода в обработчике ПриСозданииНаСервере:

Шаг 1. Получение данных для колонок

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


// Получаем список сотрудников, которые станут нашими колонками
ЗапросСотрудники = Новый Запрос;
ЗапросСотрудники.Текст = 
    "ВЫБРАТЬ
    |	Сотрудники.Ссылка КАК Ссылка,
    |	Сотрудники.Наименование КАК ФИО
    |ИЗ
    |	Справочник.Сотрудники КАК Сотрудники
    |ГДЕ
    |	НЕ Сотрудники.ПометкаУдаления";

РезультатЗапроса = ЗапросСотрудники.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Шаг 2. Добавление реквизитов формы

Чтобы динамический список "понял", куда помещать данные из нового запроса, мы должны добавить новые реквизиты в объект ДинамическийСписок. Для этого используется метод ИзменитьРеквизиты().


НовыеРеквизиты = Новый Массив;
ДобавляемыеКолонки = Новый СписокЗначений;

Пока Выборка.Следующий() Цикл
    ИмяПоля = "Сотрудник_" + СтрЗаменить(Строка(Выборка.Ссылка.УникальныйИдентификатор()), "-", "_");
    НовыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяПоля, Новый ОписаниеТипов("Булево"), "Список"));
    ДобавляемыеКолонки.Добавить(Выборка.Ссылка, ИмяПоля);
КонецЦикла;

ИзменитьРеквизиты(НовыеРеквизиты);

Шаг 3. Модификация текста запроса

Теперь мы должны достроить текст запроса динамического списка. Рассмотрим пример, где мы проверяем вхождение документа в массив ссылок, где этот сотрудник фигурирует. Либо, что более эффективно, используем вложенные ВЫБОР КОГДА.


ТекстЗапроса = Список.Текст; // Берем исходный текст из настроек ДС
Для Каждого ЭлементСписка Из ДобавляемыеКолонки Цикл
    ИмяПоля = ЭлементСписка.Представление;
    ТекстЗапроса = ТекстЗапроса + ", ВЫБОР КОГДА &Список_" + ИмяПоля + " СОДЕРЖИТ Ссылка ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ КАК " + ИмяПоля;
КонецЦикла;

// Важное замечание: Использование конструкции "В (&Параметр)" для каждой колонки
// может потребовать предварительного сбора массивов ссылок документов для каждого сотрудника.

Шаг 4. Создание элементов интерфейса

После того как данные подготовлены в запросе, их нужно вывести на форму. Создаем элементы типа ПолеФормы.


Для Каждого ЭлементСписка Из ДобавляемыеКолонки Цикл
    ИмяПоля = ЭлементСписка.Представление;
    НовыйЭлемент = Элементы.Добавить(ИмяПоля, Тип("ПолеФормы"), Элементы.Список);
    НовыйЭлемент.Вид = ВидПоляФормы.ПолеФлажка;
    НовыйЭлемент.ПутьКДанным = "Список." + ИмяПоля;
    НовыйЭлемент.Заголовок = Строка(ЭлементСписка.Значение);
КонецЦикла;

Способ 2. Использование события "ПриПолученииДанныхНаСервере"

Разберем альтернативный вариант. Если количество колонок невелико, а логика их заполнения слишком сложна для SQL-запроса, можно использовать событие ПриПолученииДанныхНаСервере. Этот метод позволяет "дорисовать" значения в колонки прямо перед отправкой данных на клиент.

Проанализируем особенности этого метода:

  1. Вы точно так же программно добавляете реквизиты и элементы формы (как в шагах 2 и 4 первого способа).
  2. В запросе динамического списка вы создаете "пустые" поля, например: ЛОЖЬ КАК Сотрудник1, ЛОЖЬ КАК Сотрудник2.
  3. В обработчике события ПриПолученииДанныхНаСервере вы обходите коллекцию НастройкиПриПолученииДанных и заполняете нужные колонки.

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

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

Сравнение подходов и технические нюансы

Выясним причину, почему первый способ считается профессиональным стандартом. Платформа 1С при работе с динамическим списком стремится минимизировать объем передаваемых данных. Модификация текста запроса позволяет СУБД (SQL Server, PostgreSQL) самостоятельно рассчитать значения флажков, используя индексы. Это критично, если в списке тысячи документов.

Рассмотрим несколько советов по оптимизации:

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

← На главную