При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с задачей обработки данных, которые пользователь видит на экране в данный момент. Особенность объекта ДинамическийСписок заключается в том, что он не хранит все данные в оперативной памяти (в отличие от таблицы значений), а подгружает их порциями из базы данных. Если пользователь воспользовался поиском (Ctrl+F), установил отбор через «Найти» или настроил сложный фильтр в окне настроек списка, нам может потребоваться программно получить именно этот «отфильтрованный» набор строк — например, чтобы подсчитать их количество или выполнить над ними групповое действие.
В этой статье мы подробно разберем, как извлечь данные из динамического списка, учитывая все активные настройки, включая поиск и программные отборы.
Для решения нашей задачи в платформе 1С предусмотрены специальные методы, которые позволяют «снять слепок» текущего состояния запроса динамического списка. Нам не нужно вручную перебирать коллекцию Отбор или пытаться анализировать строку поиска. Система сама предоставляет готовую схему и настройки, которые она использует для вывода данных на экран.
Рассмотрим основные методы, которые нам понадобятся:
ПолучитьИсполняемуюСхемуКомпоновкиДанных() — возвращает объект СхемаКомпоновкиДанных, содержащую текст запроса и описание полей.ПолучитьИсполняемыеНастройкиКомпоновкиДанных() — возвращает текущие НастройкиКомпоновкиДанных, в которых объединены пользовательские фильтры, фиксированные отборы и параметры поиска.Важно: Эти методы доступны только на стороне сервера. Поэтому любая процедура обработки данных должна начинаться с вызова серверного контекста.
Проанализируем наиболее универсальный подход. Он позволяет получить результат в виде таблицы значений, полностью повторяющей структуру и данные списка с учетом всех фильтров. Это удобно, если строк немного (например, до нескольких тысяч) и вам нужно обработать каждое значение.
Рассмотрим программный код реализации этого метода:
&НаСервере
Процедура ПолучитьДанныеСпискаНаСервере()
// 1. Получаем схему и настройки из элемента формы (динамического списка)
// Предположим, что основной реквизит списка на форме называется "Список"
Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
// 2. Подготавливаем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// Указываем тип генератора для выгрузки в коллекцию (таблицу значений)
ТипГенератора = Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений");
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , ТипГенератора);
// 3. Инициализируем процессор компоновки данными макета
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// 4. Выводим результат в таблицу значений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
РезультатТаблица = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(РезультатТаблица);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Теперь переменная РезультатТаблица содержит все строки, которые видел пользователь
КоличествоСтрок = РезультатТаблица.Количество();
Сообщить("Выбрано строк: " + КоличествоСтрок);
КонецПроцедуры
Этот метод хорош тем, что он автоматически учитывает права доступа (RLS), функциональные опции и параметры запроса. Однако помните о производительности: если в отбор попадет 100 000 записей, выгрузка их всех в таблицу значений может привести к переполнению памяти сервера.
Разберем ситуацию, когда нам не нужна вся таблица значений, а нужно лишь быстро получить количество строк или выполнить свой специфический запрос на основе настроек пользователя. В этом случае мы можем извлечь текст запроса из макета компоновки и выполнить его через объект Запрос.
Посмотрим на пример кода, который позволяет выполнить запрос напрямую:
&НаСервере
Функция ПолучитьКоличествоЗаписейСписка()
Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);
// Получаем текст запроса, который сформировала система компоновки
ТекстЗапроса = МакетКомпоновки.НаборыДанных[0].Запрос;
// Если нам нужно только количество, мы можем обернуть этот запрос
ТекстЗапросаКоличество = "ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ (" + ТекстЗапроса + ") КАК Подзапрос";
Запрос = Новый Запрос(ТекстЗапросаКоличество);
// Важно передать все параметры, которые СКД сформировала для отборов и поиска
Для Каждого Параметр Из МакетКомпоновки.ЗначенияПараметров Цикл
Запрос.УстановитьПараметр(Параметр.Имя, Параметр.Значение);
КонецЦикла;
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка[0];
КонецЕсли;
Возврат 0;
КонецФункции
Выясним причину, по которой этот способ может быть предпочтительнее: он работает быстрее при больших объемах данных, так как серверу базы данных проще вернуть одно число, чем передавать тысячи строк данных приложению.
Проанализируем несколько критических моментов, о которых стоит помнить при работе с этими методами:
ПОДОБНО для всех видимых текстовых полей. Метод ПолучитьИсполняемыеНастройки корректно собирает эти условия. Однако в старых версиях платформы поиск через Ctrl+F мог не всегда попадать в настройки. В современных релизах (8.3.10+) эта проблема решена.П1, Поле1). Будьте внимательны при обращении к полям в результирующей таблице.ПолучитьИсполняемуюСхемуКомпоновкиДанных является то, что она учитывает права доступа пользователя «на уровне записей». Если вы просто напишете свой запрос к той же таблице, вы можете получить больше данных, чем видит пользователь, что приведет к ошибкам в логике программы.ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений) используйте ПроцессорКомпоновкиДанных.ОткрытьРезультат(). Это позволит обходить записи по одной с помощью метода Следующий(), не загружая их все одновременно в память.Мы рассмотрели эффективные способы программного доступа к данным динамического списка. Использование исполняемой схемы компоновки — это единственный надежный способ узнать, что именно видит пользователь в данный момент с учетом всех фильтров, поиска и ограничений прав. Выбор между использованием процессора вывода и прямым выполнением запроса зависит от вашей конкретной задачи: нужен ли вам полный набор данных или достаточно агрегатных значений (количество, сумма).
Применяйте эти методы на сервере, учитывайте параметры запроса и всегда следите за объемом данных, которые выгружаются в коллекции значений, чтобы обеспечить стабильную работу системы.