Массовая обработка выбранных элементов

Допустим, вам нужно обработать строки документов или некоторые элементы справочников, отобранные по некоторому условию. Как правильнее написать код по их обработке? Можете воспользоваться моим примером.

Как обычно пишут код начинающие программисты? Просто перебирают все элементы справочника (все документы) и если выполняется условие отбора, то обрабатывают элемент (документ).

Программисты, более продвинутые, строят сначала запрос, где получают список документов и элементов, необходимых для обработки. В случае документов главное для красивого стиля и удобства работы, чтобы условие дважды не проверялось в тексте запроса и в коде.

Поэтому для документов в запросе имеет смысл вернуть не только перечень документов, но и конкретные номера строк, удовлетворяющие условиям отбора. В таком случае вся логика отбора сосредотачивается в запросе и не нужно повторно проверять эти условия в коде.

Итак, рассмотрим по шагам, как правильно написать такую обработку.

Пишем запрос:

ВЫБРАТЬ
  НомерСтроки, Ссылка
ИЗ
  Документ.ТаблицаДляЗагрузки.ТЧЗакачка
ГДЕ //Условие отбора
  МаркаДт В ИЕРАРХИИ (&МаркаБаз) ИЛИ МаркаКт В ИЕРАРХИИ (&МаркаБАЗ))  И Ссылка.Проведен
ИТОГИ ПО Ссылка //Итоги - для группировок, чтобы можно было потом Выбрать использовать!

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

З = Новый Запрос(" ... Текст запроса выше ...");

З.УстановитьПараметр("...", ...); //Установить все параметры запроса

//Первый цикл - по документам

 ВыборкаДок = З.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаДок.Следующий() Цикл

  ТекСсылка = ВыборкаДок.Ссылка;

  ТекОбъект = ТекСсылка.ПолучитьОбъект();

  М = Новый Массив();

  //Второй цикл - по номерам строк

 ВыборкаСтр = ВыборкаДок.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

    Пока ВыборкаСтр.Следующий() Цикл

        М.Добавить(ТекОбъект.ТЧЗакачка[ВыборкаСтр.НомерСтроки-1]);

    КонецЦикла;

    //Обрабатываем выбранные строки

    Сообщить("Документ: " + ТекСсылка + " Нужно обработать строк: " + М.Количество());

    ОбработкаПрерыванияПользователя();

    //Здесь идет код по обработки документа и его массива строк

    ПроизвольнаяОбработкаДокумента(ТекОбъект, М);

    //Записываем, если надо документ

    ТекОбъект.Записать(РежимЗаписиДокумента.Проведение);

КонецЦикла;

У подобного метода есть достоинство - если он прервется на середине, его можно перезапустить и он начнет обрабатывать документы не с начала, а только еще не обработанные документы.

Небольшой совет - если вы собираетесь удалять строки при обработке, то упорядочивайте по убыванию номера строк, чтобы сначала удалять строки с большим номером (тогда при удалении не будут сдвигаться номера строк).