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

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

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

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

Почему стандартный подход «Использовать всегда» не работает с СКД?

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

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

Решение проблемы: программное добавление полей в структуру настроек

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

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


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

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

Завершение процесса: вывод данных в таблицу значений

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

Продолжим наш пример кода:


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

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

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

// Теперь в ТаблицаРезультат (или СтрокиСписка) содержатся все данные, 
// включая скрытое поле "НужноеСкрытоеПоле"

Важные нюансы и ограничения метода

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

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

Альтернативный взгляд: Инициализация через цикл

Интересной особенностью, замеченной практикующими разработчиками, является то, что иногда простого перебора коллекции Настройки.Структура[0].Выбор.Элементы в цикле бывает достаточно для некоей «внутренней инициализации» списка доступных полей. Однако для стабильной работы рекомендуется явно добавлять поле и проверять его наличие, как показано в примере выше.

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

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

← На главную