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

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

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

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

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

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

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

Решение 1. Точечное добавление нужного поля в группировку

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

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


&НаСервере
Функция ПолучитьТаблицуИзСписка()

    // 1. Получаем исполняемую схему и настройки из элемента формы (таблицы)
    Схема = Элементы.Список.ПолучитьИсполняемоюСхемуКомпоновкиДанных();
    Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();

    // 2. Добавляем программные отборы при необходимости
    ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ПометкаУдаления");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = Ложь;
    ЭлементОтбора.Использование = Истина;

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

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

    // 5. Выполняем компоновку и выводим результат в таблицу значений
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

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

    Возврат ТаблицаРезультат;

КонецФункции

Решение 2. Выгрузка всех доступных полей схемы

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

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


// Очищаем состав выбранных полей группировки
Настройки.Структура[0].Выбор.Элементы.Очистить();

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

Важные ограничения и нюансы механизма

При использовании выгрузки динамического списка через СКД важно учитывать следующие особенности платформы:

  1. Контекст выполнения: Методы ПолучитьИсполняемуюСхемуКомпоновкиДанных() и ПолучитьИсполняемыеНастройкиКомпоновкиДанных() вызываются только у элемента формы (таблицы формы), а не у самого реквизита. Соответственно, код должен исполняться строго в серверном контексте формы (директива &НаСервере). Вне контекста формы эти методы недоступны.
  2. Доступность поля в наборе данных: Добавляемое поле обязательно должно присутствовать в тексте запроса списка или в полях основной таблицы. Если поля нет в наборе данных исходной схемы, его предварительно нужно добавить в Схема.НаборыДанных[0].Поля.
  3. Пропуск данных из обработчиков: Данные, которые рассчитываются динамически на клиенте или формируются в событии ПриПолученииДанныхНаСервере, в таблицу значений не попадут. Процессор компоновки делает прямой запрос к СУБД, минуя интерфейсные механизмы постобработки строк.
  4. Нагрузка на сервер и СУБД: Динамический список отображает данные порционно. Метод ПроцессорВывода.Вывести() выгружает всю выборку целиком. Если в списке отсутствуют жесткие отборы, выполнение такого кода на таблицах с миллионами записей приведет к долгому зависанию и высокому потреблению оперативной памяти.

Альтернативные варианты

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

  1. Обработка выделенных строк: Если пользователю требуется обработать не весь список, а лишь строки, выбранные вручную, лучше получить массив через Элементы.Список.ВыделенныеСтроки и передать его параметром в отдельный запрос. Это работает в разы быстрее и безопаснее для производительности.
  2. Получение сгенерированного текста запроса: Если требуется применить конструкцию ВЫБРАТЬ ПЕРВЫЕ или перенаправить результат во временную таблицу, после шага КомпоновщикМакета.Выполнить(...) можно получить готовый текст запроса со всеми фильтрами списка через свойство МакетКомпоновки.НаборыДанных[0].Запрос и выполнить его через обычный объект Запрос.
← На главную