Как в 1С 7.7 выбрать документы определенного вида по списку значений реквизита?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке обработок в среде 1С:Предприятие 7.7 часто возникает задача отобрать документы строго определенного вида (например, ПриходнаяНакладная), у которых реквизит (например, Фирма) принимает одно из значений из заданного списка. Разберем типичные ошибки при решении этой задачи и рассмотрим наиболее эффективные способы выборки данных.

Почему возникает ошибка при использовании метода ВыбратьПоЗначению

Рассмотрим распространенную попытку применить метод ВыбратьПоЗначению напрямую к типизированному объекту документа:


Доки = СоздатьОбъект("Документ.ПриходнаяНакладная");
Доки.ВыбратьПоЗначению(Дата1, Дата2, "Фирма", ВыбФирма);

При выполнении этого кода платформа выдает ошибку: «Объект — документ определенного вида!». Проанализируем причину такого поведения платформы 1С 7.7:

  1. Метод ВыбратьПоЗначению реализован исключительно для нетипизированного объекта СоздатьОбъект("Документ"). Это связано с тем, что отбор по значению реквизита или графы отбора работает на уровне системных таблиц общего журнала документов.
  2. Метод ВыбратьПоЗначению принимает в качестве параметра отбора только одно конкретное значение. Передать в него объект СписокЗначений штатно невозможно.
  3. Для реквизита шапки документа в конфигураторе обязательно должен быть включен признак «Отбор по реквизиту» или реквизит должен входить в состав используемой графы отбора общего журнала.

Способ 1. Использование встроенного объекта «Запрос» (рекомендуемый вариант)

Использование штатного механизма запросов платформы 1С 7.7 позволяет сразу отфильтровать документы нужного вида по условию вхождения реквизита в список значений СписокЗначений.

Посмотрим на пример правильного построения и обхода запроса:


Запрос = СоздатьОбъект("Запрос");
ТекстЗ = "
|Период с Дата1 по Дата2;
|Без Итогов;
|ПН = Документ.ПриходнаяНакладная.ТекущийДокумент;
|Фирма = Документ.ПриходнаяНакладная.Фирма;
|Группировка ПН;
|Условие(Фирма В спФирмы);
|";

Если Запрос.Выполнить(ТекстЗ) = 0 Тогда
    Сообщить("Ошибка выполнения запроса!", "!");
    Возврат;
КонецЕсли;

ТекДок = СоздатьОбъект("Документ.ПриходнаяНакладная");
Пока Запрос.Группировка("ПН") = 1 Цикл
    ТекДок.НайтиДокумент(Запрос.ПН);
    // Обработка найденного документа
    СформироватьЦены();
КонецЦикла;

Разберем важные тонкости настройки текста запроса и его обхода:

  1. Директива «Без Итогов;»: Если не указать Без Итогов;, при вызове метода Запрос.Группировка() без указания конкретного имени группировки первым шагом выборки будет верхнеуровневая итоговая строка, в которой поле Запрос.ПН окажется пустым. Использование Без Итогов; и передача имени группировки в метод Запрос.Группировка("ПН") гарантируют корректный последовательный обход документов.
  2. Состав выборки документов: По умолчанию механизм запросов 1С 7.7 отбирает только проведенные документы. Если требуется обрабатывать также непроведенные или помеченные на удаление документы, необходимо явно добавить строку |Обрабатывать Все; или |Обрабатывать НеПроведенные;.
  3. Упорядочивание: Конструкция Группировка ПН; автоматически сортирует документы в хронологическом порядке (по дате и времени позиции документа), поэтому дополнительно указывать сортировку не требуется.

Способ 2. Прямой перебор документов с проверкой по списку значений

Если документов нужного вида за выбранный период относительно немного, можно воспользоваться методом ВыбратьДокументы у типизированного объекта документа с последующей проверкой вхождения в список.

Рассмотрим реализацию этого варианта:


Доки = СоздатьОбъект("Документ.ПриходнаяНакладная");
Доки.ВыбратьДокументы(Дата1, Дата2);

Пока Доки.ПолучитьДокумент() = 1 Цикл
    // Проверяем вхождение реквизита Фирма в список
    Если спФирмы.Принадлежит(Доки.Фирма) = 1 Тогда
        // Обработка документа
        СформироватьЦены();
    КонецЕсли;
КонецЦикла;

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

Способ 3. Использование нетипизированного объекта «Документ» и метода «ВыбратьПоЗначению»

Если список организаций содержит всего 1–2 значения, а документов нужного вида в базе огромное количество, можно использовать цикл по списку организаций в комбинации с нетипизированной выборкой:


Доки = СоздатьОбъект("Документ");

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

Для работы этого варианта убедимся, что для реквизита Фирма в свойствах метаданных включен флаг «Отбор по реквизиту».

← На главную