Как перебрать строки в ДокументСписок и обработать пользовательские флажки в обычных формах 1С

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

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

Почему нельзя обойти ДокументСписок через цикл Для каждого

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

Кроме того, если в табличное поле добавлена колонка «Флажок», не связанная с реквизитом документа в базе данных, эта колонка существует только на уровне визуального отображения текущих видимых строк. Сам ДокументСписок ничего не знает о состоянии таких флажков.

Способ 1. Хранение отметок в отдельной коллекции (Рекомендуемый способ)

Разберем по шагам классический и наиболее производительный подход для работы с флажками выбора в обычных формах. Поскольку динамический список не хранит пользовательские отметки, мы будем запоминать ссылки на выбранные документы в отдельной переменной модуля формы — объекте Соответствие или Массив.

Рассмотрим реализацию механизма:

  1. В модуле формы объявим переменную для хранения отмеченных ссылок: Перем мОтмеченныеДокументы;
  2. В обработчике события формы ПриОткрытии инициализируем коллекцию:
    
    Процедура ПриОткрытии()
        мОтмеченныеДокументы = Новый Соответствие;
    КонецПроцедуры
    
  3. Для отображения флажков в табличном поле используем событие ПриВыводеСтроки (или пакетное событие ПриПолученииДанных):
    
    Процедура ДокументСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
        // Проверяем наличие текущей ссылки в нашей коллекции отметок
        Если мОтмеченныеДокументы[ДанныеСтроки.Ссылка] = Истина Тогда
            ОформлениеСтроки.Ячейки.Флажок.УстановитьФлажок(Истина);
        Иначе
            ОформлениеСтроки.Ячейки.Флажок.УстановитьФлажок(Ложь);
        КонецЕсли;
    КонецПроцедуры
    
  4. При клике пользователя по флажку (событие ПриИзмененииФлажка или Выбор) обновляем наше соответствие:
    
    Процедура ДокументСписокПриИзмененииФлажка(Элемент, Колонка)
        Если Колонка.Имя = "Флажок" Тогда
            ТекущиеДанные = Элемент.ТекущиеДанные;
            Если ТекущиеДанные <> Неопределено Тогда
                СсылкаНаДокумент = ТекущиеДанные.Ссылка;
                Если мОтмеченныеДокументы[СсылкаНаДокумент] = Истина Тогда
                    мОтмеченныеДокументы.Удалить(СсылкаНаДокумент);
                Иначе
                    мОтмеченныеДокументы.Вставить(СсылкаНаДокумент, Истина);
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    
  5. Теперь для обработки выбранных документов нам не нужно обходить табличное поле. Достаточно перебрать ключи накопленной коллекции:
    
    Процедура ВыполнитьОбработкуОтмеченных()
        Для Каждого ЭлементОтбора Из мОтмеченныеДокументы Цикл
            СсылкаНаДокумент = ЭлементОтбора.Ключ;
            
            // Выполняем требуемые действия с документом
            ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
            // ... логика обработки ...
        КонецЦикла;
    КонецПроцедуры
    

Способ 2. Получение строк списка через ПостроительЗапроса

Рассмотрим ситуацию, когда требуется получить все строки списка с учетом пользовательских фильтров и отборов, настроенных в форме (например, для реализации кнопки «Отметить все» или выгрузки отфильтрованных данных).

Для этого используется объект ПостроительЗапроса. Важно помнить, что передать ДокументСписок напрямую в свойство ИсточникДанных нельзя, так как возникнет ошибка несоответствия типов. Необходимо обернуть его в объект ОписаниеИсточникаДанных.

Посмотрим на пример кода:


Процедура ПолучитьВсеСтрокиСписка()
    Построитель = Новый ПостроительЗапроса;
    
    // Передаем ДокументСписок через ОписаниеИсточникаДанных
    Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок);
    
    // Выполняем выборку с учетом всех интерактивных отборов формы
    Результат = Построитель.Результат;
    Выборка = Результат.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Доступ к реквизитам документов из текущего списка
        СсылкаНаДокумент = Выборка.Ссылка;
        
        // Например, отмечаем все документы из текущего отбора:
        мОтмеченныеДокументы.Вставить(СсылкаНаДокумент, Истина);
    КонецЦикла;
    
    // Обновляем визуальное отображение строк в табличном поле
    ЭлементыФормы.ДокументСписок.ОбновитьСтроки();
КонецПроцедуры

Способ 3. Использование стандартного множественного выделения

Если добавление отдельной колонки с флажками не является строгим требованием интерфейса, проанализируем штатную альтернативу — множественное выделение строк мышью и клавиатурой (Shift / Ctrl).

  1. В свойствах табличного поля установим режим выделения:
    
    ЭлементыФормы.ДокументСписок.РежимВыделения = РежимВыделенияТабличногоПоля.Множественный;
    
  2. В обработчике команды обойдем коллекцию ВыделенныеСтроки:
    
    Процедура ОбработатьВыделенныеСтроки()
        Для Каждого СтрокаСписка Из ЭлементыФормы.ДокументСписок.ВыделенныеСтроки Цикл
            СсылкаНаДокумент = СтрокаСписка.Ссылка;
            // Обработка выделенного документа
        КонецЦикла;
    КонецПроцедуры
    

Такой подход не требует хранения дополнительных соответствий и полностью опирается на стандартное поведение платформы 1С:Предприятие.

← На главную