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

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

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

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

Штатный метод получения данных через СКД

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

Некоторые программисты совершают критическую ошибку: они получают исполняемую схему, извлекают из нее текст запроса и пытаются выполнить его через обычный объект Запрос. Мы крайне не рекомендуем так делать. При сложном поиске, использовании RLS (разграничения прав на уровне записей) или наложении отборов структура запроса динамически перестраивается платформой. Попытка вручную сопоставить параметры и выполнить такой запрос приведет к нестабильной работе и частым ошибкам времени выполнения.

Правильный и надежный способ — использовать полноценный процессор компоновки данных и вывести результат в коллекцию (таблицу значений). Давайте разберем готовый рабочий шаблон функции:


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

Решение проблемы "скрытых" и невидимых колонок

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

В результате сгенерированная таблица значений не будет содержать скрытую колонку. Если ваша бизнес-логика завязана на обработку ссылок документов или справочников, это приведет к ошибкам в коде. Чтобы этого избежать, мы можем использовать два решения:

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

Различие между "строками по отбору" и "строками на экране"

Проанализируем концептуальную разницу в терминах. Динамический список оптимизирован для работы с большими объемами данных. Он считывает из базы данных ровно столько строк, сколько требуется для заполнения видимой области экрана (например, 20-30 строк) плюс небольшой кэш. Если под условия установленного отбора подпадает 150 000 документов, платформа не загружает их все на клиентский компьютер.

Описанный выше метод с использованием схемы компоновки данных (СКД) выполнит запрос к базе данных и вернет все 150 000 строк, которые удовлетворяют текущему отбору пользователя, а не только те 20 строк, которые физически видны на экране монитора.

Если перед вами стоит задача получить только те строки, которые пользователь выделил курсором в данный момент, используйте свойство элемента формы ВыделенныеСтроки:


&НаКлиенте
Процедура ОбработатьВыделенныеСтроки()
    
    МассивИдентификаторов = Элементы.Список.ВыделенныеСтроки;
    Для Каждого Идентификатор Из МассивИдентификаторов Цикл
        ДанныеСтроки = Элементы.Список.ДанныеСтроки(Идентификатор);
        Если ДанныеСтроки <> Неопределено Тогда
            // Обрабатываем данные конкретной строки, например, ДанныеСтроки.Ссылка
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Важно помнить, что метод ДанныеСтроки() работает на клиенте и возвращает данные только для тех строк, которые уже кэшированы на клиенте. Если выделить все строки в списке сочетанием клавиш CTRL+A, часть данных может не успеть загрузиться, поэтому для надежной обработки больших объемов выделенных строк лучше передавать массив идентификаторов (ссылок) на сервер и выполнять обработку там.

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

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

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

Ограничения на Мобильной платформе 1С

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

Для решения этой задачи на мобильной платформе нам придется действовать "вручную":

  1. Программно обойти коллекцию отборов динамического списка (анализируя Список.Отбор.Элементы).
  2. Вручную построить аналогичный SQL-запрос с наложением секции ГДЕ, соответствующей найденным отборам.
  3. Выполнить запрос и получить результат.

Хотя этот способ требует написания большего объема программного кода и усложняет поддержку при изменении структуры данных, он обеспечивает стабильную работу приложения на мобильных устройствах под управлением Android и iOS.

← На главную