Разработка и Конфигурация · 10 мин
Как в 1С выбрать все документы
Как выбрать все документы в 1С: запрос без условий, выборка через Выбрать(), отбор по периоду и виду документа. Примеры кода, типичные ошибки и проверка результата.
Задача «выбрать все документы» в 1С встречается в двух типовых ситуациях: при написании запроса в консоли или в модуле и при программном обходе документов через метод Выбрать() менеджера документа. В обоих случаях «все» почти всегда означает «все документы конкретного вида», а не буквально все документы базы — выборка по всем типам сразу потребует перебора метаданных и на больших базах выполняется долго.
Простейший вариант — запрос без секции ГДЕ: конструкция ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг вернёт все существующие в базе документы этого вида, включая непроведённые и помеченные на удаление. Это важно понимать сразу: без дополнительных условий в выборку попадёт всё, что физически хранится в таблице.
Ниже разобраны оба подхода — через запрос и через метод Выбрать(), варианты отбора по периоду и статусу проведения, способ выбрать документы всех видов разом, а также типичные ошибки, из-за которых выборка возвращается пустой или неполной.
Выбор всех документов запросом
Запрос — основной инструмент выборки. Минимальный текст запроса, возвращающего все документы одного вида, выглядит так:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка КАК Ссылка,
| Док.Номер КАК Номер,
| Док.Дата КАК Дата
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
|УПОРЯДОЧИТЬ ПО
| Док.Дата";
Результат = Запрос.Выполнить().Выбрать();
Отсутствие секции ГДЕ и есть условие «выбрать всё». В выборку попадут проведённые, непроведённые и помеченные на удаление документы. Если нужны только «живые» документы, добавьте отбор:
"ГДЕ
| Док.Проведен = ИСТИНА
| И НЕ Док.ПометкаУдаления"
Обход результата выполняется циклом Пока Результат.Следующий() Цикл. Внутри цикла доступны поля, перечисленные в секции ВЫБРАТЬ. Если нужно работать с документом как с объектом (менять реквизиты, перепроводить), получите объект через Результат.Ссылка.ПолучитьОбъект() — но учитывайте, что это дорогая операция, и делать её для каждой строки большой выборки следует только при реальной необходимости.
ВЫБРАТЬ Ссылка, Номер, Дата ИЗ Документ.ПоступлениеТоваровУслуг ГДЕ Проведен УПОРЯДОЧИТЬ ПО ДатаВыборка через метод Выбрать()
Второй способ — метод Выбрать() менеджера документов. Он удобен, когда не нужен сложный запрос, а требуется просто перебрать документы, например в регламентном задании или обработке:
Выборка = Документы.РеализацияТоваровУслуг.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Номер);
КонецЦикла;
Вызов без параметров возвращает все документы вида. Метод принимает необязательные параметры: начало и конец интервала дат, отбор по реквизитам (структура) и порядок. Например, выборка за период:
Выборка = Документы.РеализацияТоваровУслуг.Выбрать(
НачалоМесяца(ТекущаяДатаСеанса()),
КонецМесяца(ТекущаяДатаСеанса()));
Отбор по реквизиту передаётся структурой: Новый Структура("Организация", ОрганизацияСсылка). Ограничение метода — отбор возможен только по равенству и только по реквизитам, для которых в конфигураторе включено индексирование или которые входят в критерий отбора. Для сложных условий (по сумме больше заданной, по виду операции из списка) используйте запрос.
Запрос или метод Выбрать()
Подходит для сложных условий, соединений с другими таблицами, группировок и итогов. Требует написания текста запроса.
Подходит для простого перебора по периоду или одному реквизиту. Не поддерживает сложные условия и соединения.
Подходит для отображения документов пользователю в форме списка с произвольным отбором, а не для пакетной обработки.
Отбор по периоду, проведению и реквизитам
На практике «все документы» почти всегда уточняется условиями. Самые частые из них:
- По периоду:
ГДЕ Док.Дата МЕЖДУ &НачалоПериода И &КонецПериода. Параметры передаются черезЗапрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала)). Помните, что дата в 1С хранится с точностью до секунды — конец периода задавайте как конец дня. - Только проведённые:
ГДЕ Док.Проведен. - Без пометки удаления:
ГДЕ НЕ Док.ПометкаУдаления. - По реквизиту:
ГДЕ Док.Контрагент = &КонтрагентилиДок.Организация В (&СписокОрганизаций).
Для отбора по периоду существует также виртуальная таблица границ, но в большинстве случаев достаточно условия МЕЖДУ. Если запрос используется в отчёте на СКД, период лучше передавать через параметры НачалоПериода и КонецПериода — они автоматически появятся в настройках отчёта.
Как выбрать документы всех видов сразу
Запрос не может обратиться сразу ко всем видам документов одной таблицей — у каждого вида своя таблица. Если нужно собрать документы всех видов (например, для поиска по номеру или аудита), переберите метаданные и выполните запрос по каждому виду:
Для Каждого МетаДок Из Метаданные.Документы Цикл
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ." + МетаДок.Имя;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// обработка
КонецЦикла;
КонецЦикла;
Альтернатива — объединение через ОБЪЕДИНИТЬ ВСЕ для ограниченного списка видов, когда их немного и они известны заранее. Ещё один вариант — журналы документов: если нужные виды входят в общий журнал, можно выбрать записи из таблицы журнала одним запросом.
Проверка результата выборки
После выполнения запроса проверьте, что выборка не пустая и содержит ожидаемое количество строк. Метод РезультатЗапроса.Пустой() быстро покажет, есть ли данные, а Выбрать().Количество() — сколько строк вернулось (учтите: вызов Количество() на больших выборках может быть ресурсоёмким в некоторых СУБД).
Быстрый способ проверить запрос без написания кода — консоль запросов (в типовых конфигурациях на управляемых формах доступна как внешняя обработка, в инструментах разработчика — встроена). Вставьте текст запроса, задайте параметры и сравните количество строк с количеством документов в списке формы при тех же отборах.
Как проверить результат
Совпадает с количеством документов в списке при тех же отборах
Выборка пустая или строк заметно меньше — проверьте условия и границы периода
Есть проведённые и непроведённые документы, если отбор по статусу не задан
Пропали помеченные на удаление или документы на границах периода
Запрос по индексированным полям выполняется быстро
Запрос «подвисает» — вероятно, условие по неиндексированному реквизиту на большой таблице
Типичные ошибки и ограничения
Чаще всего проблемы возникают не из-за синтаксиса, а из-за неверных предположений о данных:
- Выборка «пустая», потому что в условии сравнивается составной тип или ссылка другого вида документа.
- Использование
ПолучитьОбъект()в цикле по десяткам тысяч документов — обработка работает часами и блокирует записи. - Перебор через
Выбрать()с обходом поСледующий()без транзакции при параллельной записи — возможны блокировки и конфликты. - Попытка выбрать «все документы» через обращение к несуществующей общей таблице — такой таблицы нет, нужен перебор метаданных или журнал.
Что важно запомнить
Все документы вида выбираются запросом без секции ГДЕ или методом Выбрать() без параметров. Уточняйте выборку периодом с корректными границами дат, статусом проведения и пометкой удаления. Для всех видов сразу перебирайте метаданные или используйте журнал документов, а массовые обработки сначала тестируйте на копии базы.
Частые вопросы
Как выбрать только проведённые документы?
Добавьте в запрос условие ГДЕ Проведен = ИСТИНА (достаточно ГДЕ Проведен). Учтите, что не все виды документов поддерживают проведение — для документов с отключённым проведением поле Проведен всегда ложно, и такое условие вернёт пустую выборку.
Как выбрать документы за текущий месяц?
Передайте в запрос параметры: НачалоМесяца(ТекущаяДатаСеанса()) и КонецМесяца(ТекущаяДатаСеанса()), а в тексте используйте условие ГДЕ Дата МЕЖДУ &Начало И &Конец. Функции НачалоМесяца и КонецМесяца доступны во встроенном языке.
Почему запрос без условий не возвращает все документы?
Наиболее вероятные причины: у текущего пользователя действует ограничение доступа к данным (RLS) на уровне записей, документы находятся в другой базе или вы смотрите не тот вид документа. Проверьте выборку под пользователем с полными правами.
Можно ли выбрать документы по подстроке в номере?
Да, через оператор ПОДОБНО: ГДЕ Номер ПОДОБНО "%00123%". Учтите, что номер документа — строка с лидирующими нулями, поэтому шаблон должен учитывать формат номера, а поиск по ПОДОБНО не использует индекс и на больших таблицах работает медленно.
Чем отличается Выгрузить() от Выбрать() у результата запроса?
Выгрузить() возвращает таблицу значений целиком в память — удобно для дальнейшей обработки и свёртки, но требует памяти под все строки. Выбрать() возвращает выборку для последовательного обхода — экономнее по памяти на больших результатах.
Как выбрать документы, у которых есть движения по конкретному регистру?
Используйте соединение с таблицей регистра или условие ГДЕ Ссылка В (ВЫБРАТЬ Регистратор ИЗ РегистрНакопления.ИмяРегистра). Второй вариант проще: подзапрос вернёт всех регистраторов, у которых есть записи в регистре.