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