При работе в обычных формах (на платформе 1С:Предприятие 8.2 или 8.3 в режиме совместимости) программисты часто сталкиваются с задачей: как получить все элементы, которые в данный момент видит пользователь в списке документов или справочников? Это необходимо для массовой печати, групповой обработки или выгрузки данных, учитывая все установленные пользователем фильтры и отборы. В управляемых формах для этого существуют встроенные механизмы динамического списка, но в обычных формах подход несколько иной.
Рассмотрим подробнее основные способы решения этой задачи, проанализируем их плюсы и минусы, а также разберем примеры кода для каждого случая.
Разберем наиболее правильный и надежный метод. В обычных формах объекты типа ДокументСписок, СправочникСписок или РегистрСведенийСписок не являются простыми таблицами значений. Это динамические выборки. Чтобы получить из них данные с учетом всех пользовательских настроек (отборов, сортировок), лучше всего использовать ПостроительЗапроса.
Проанализируем ситуацию: когда пользователь устанавливает отбор через стандартный диалог «Отбор и сортировка», эти настройки сохраняются в свойстве Отбор списка. ПостроительЗапроса умеет принимать объект списка в качестве источника данных и автоматически применять все его настройки к своему внутреннему запросу.
Посмотрим на пример кода:
// Предположим, на форме есть табличное поле ДокументСписок
Построитель = Новый ПостроительЗапроса;
// Указываем источник данных, передавая туда наш список
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок);
// Выполняем запрос для получения данных
Построитель.Выполнить();
// Выгружаем результат в таблицу значений для последующего перебора
ТЗ_Результат = Построитель.Результат.Выгрузить();
// Теперь мы можем перебрать все документы, которые попали в фильтр
Для Каждого Строка Из ТЗ_Результат Цикл
// Допустим, мы хотим распечатать документы
ПечатьДокумента(Строка.Ссылка);
КонецЦикла;
Важный нюанс: при использовании этого метода ПостроительЗапроса выгрузит только те колонки, которые определены в источнике данных. Если вам нужны дополнительные реквизиты, которых нет в списке, вы можете либо добавить их в настройки построителя, либо получить их позже по ссылке в цикле (хотя для производительности лучше доработать запрос построителя).
Если задача заключается в том, чтобы просто получить печатную форму или таблицу со всеми данными «как есть» на экране, можно воспользоваться встроенной функцией платформы. Метод ВывестиСписок табличного поля генерирует ТабличныйДокумент, содержащий все строки, соответствующие текущим отборам.
Разберем по шагам, как это реализовать:
// Создаем пустой табличный документ
ТабДок = Новый ТабличныйДокумент;
// Вызываем метод вывода списка для элемента формы (табличного поля)
// Параметры: ТабличныйДокумент, ПечатьЗаголовка, ИспользоватьОформление
ЭлементыФормы.СправочникСписок.ВывестиСписок(ТабДок, Истина, Истина);
// Теперь ТабДок содержит готовую таблицу, которую можно показать пользователю или распечатать
ТабДок.Показать("Список отобранных элементов");
Этот способ идеален, если пользователю нужно именно визуальное представление отфильтрованных данных. Однако для программной обработки объектов (например, изменения реквизитов документов) он менее удобен, чем использование построителя запроса.
Иногда возникает вопрос: можно ли использовать события ПриВыводеСтроки или ПриПолученииДанных? Выясним причину, почему это не лучший выбор для задачи «перебрать весь список».
Событие ПриПолученииДанных вызывается платформой только для тех строк, которые в данный момент отображаются на экране монитора (визуальная область). Платформа оптимизирует работу и не подгружает все 10 000 строк из базы, если пользователь видит только 20. Поэтому, пытаясь собрать коллекцию ссылок через это событие, вы получите только «верхушку айсберга».
Однако, если вам нужно выполнять действия только с тем, что видит пользователь прямо сейчас (например, для динамического расчета итогов по видимым строкам), этот метод применим. Рассмотрим пример реализации:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
МассивСсылок = Новый Массив;
Для Каждого Оформление Из ОформленияСтрок Цикл
// Проверяем, что в строке есть данные
Если Оформление.ДанныеСтроки <> НеОпределено Тогда
МассивСсылок.Добавить(Оформление.ДанныеСтроки.Ссылка);
КонецЕсли;
КонецЦикла;
// Здесь можно выполнить какую-то логику для видимых строк
// Например, расчет остатков и вывод их в колонку
ЗаполнитьОстаткиВКолонках(МассивСсылок, ОформленияСтрок);
КонецПроцедуры
Помните, что это событие срабатывает часто (при каждом скролле), поэтому код внутри него должен быть максимально оптимизирован.
Если задача — распечатать не всё, что отфильтровано, а только то, что пользователь выбрал (выделил мышкой), мы используем свойство ВыделенныеСтроки. В обычных формах это коллекция ссылок на объекты.
Проанализируем пример работы:
// Проверяем, выбрал ли пользователь хоть что-нибудь
Если ЭлементыФормы.ДокументСписок.ВыделенныеСтроки.Количество() = 0 Тогда
Предупреждение("Пожалуйста, выделите документы для печати!");
Возврат;
КонецЕсли;
// Перебираем коллекцию выделенных строк
Для Каждого СсылкаНаДокумент Из ЭлементыФормы.ДокументСписок.ВыделенныеСтроки Цикл
// Выполняем действие
Сообщить("Обработка документа: " + СсылкаНаДокумент);
КонецЦикла;
Чтобы пользователь мог выбрать несколько строк сразу, убедитесь, что в свойствах табличного поля установлен РежимВыделения в значение Множественный.
Подведем итоги нашего анализа:
ПостроительЗапроса с источником данных ОписаниеИсточникаДанных. Это самый быстрый и корректный способ, учитывающий иерархию, отборы и порядок.ВывестиСписок().ВыделенныеСтроки.ПриПолученииДанных для получения полного списка данных, так как они работают порционно и только для видимых элементов.При использовании ПостроителяЗапроса всегда помните о производительности: если в списке сотни тысяч записей, выгрузка их всех в таблицу значений может потребовать значительного объема оперативной памяти. В таких случаях рассмотрите возможность обработки данных порциями (выборками).