К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как сделать выборку документов в 1С

Практические способы выборки документов в 1С: запрос с отбором, Выбрать() в коде, журналы документов и динамические списки. Примеры кода, ошибки и FAQ.

Выборка документов — базовая операция в 1С, которая нужна и разработчику, и пользователю. Разработчик получает набор документов для обработки, отчёта или выгрузки, а пользователь — отфильтрованный список в журнале. Способ выборки зависит от задачи: одно дело — найти документы за период по контрагенту, другое — перебрать тысячи проведённых реализаций и изменить в них реквизит.

Главное правило: не перебирайте все документы без отбора, если нужна только часть. Любая выборка должна быть ограничена периодом и условиями — иначе на большой базе операция займёт минуты и создаст нагрузку на сервер. Ниже разобраны все рабочие способы с примерами кода, типичными ошибками и критериями выбора.

Способы выборки: что выбрать под задачу

В платформе 1С есть четыре практических подхода. Запрос (язык запросов) — основной инструмент для отчётов и массовых выборок: он выполняется на сервере СУБД и возвращает только нужные поля. Метод Выбрать() менеджера документов возвращает выборку ссылок, которую удобно обходить в цикле и изменять. Программный отбор динамического списка применяется в формах, а отбор в журнале документов доступен пользователю без программирования.

Сравнение вариантов

Запрос (ВЫБРАТЬ ... ИЗ Документ.РеализацияТоваровУслуг)

Лучший вариант для отчётов, выгрузок и больших объёмов. Можно соединять с табличными частями и регистрами. Не подходит, если нужно изменять каждый документ в цикле с вызовом бизнес-логики.

Документы.Имя.Выбрать()

Подходит для обхода документов с последующей записью изменений. Медленнее запроса, отбор только по дате и простым реквизитам шапки.

Отбор в журнале документов

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

Динамический список с отбором

Для форм списков в управляемом приложении. Отбор хранится в настройках формы.

Если сомневаетесь — начинайте с запроса. Он покрывает большинство задач, а метод Выбрать() оставьте для случаев, когда каждый документ нужно получить объектом, изменить и записать.

Выборка запросом с отбором

Запрос создаётся объектом Запрос, текст пишется на встроенном языке запросов. Минимальный пример — выбрать проведённые реализации за период по организации:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Реализация.Ссылка КАК Ссылка,

| Реализация.Номер КАК Номер,

| Реализация.Дата КАК Дата,

| Реализация.Контрагент КАК Контрагент,

| Реализация.СуммаДокумента КАК Сумма

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода

| И Реализация.Организация = &Организация

| И Реализация.Проведен

|

|УПОРЯДОЧИТЬ ПО

| Реализация.Дата";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("Организация", Организация);

Результат = Запрос.Выполнить().Выбрать();

Пока Результат.Следующий() Цикл

// обработка строки выборки

КонецЦикла;

Обратите внимание на три приёма. Во-первых, параметры передаются через УстановитьПараметр — никогда не подставляйте значения в текст запроса конкатенацией: это риск ошибок с форматом дат и строк. Во-вторых, отбор по дате лучше задавать через МЕЖДУ или Дата >= &Начало И Дата <= &Конец с параметром КонецДня(). В-третьих, условие Проведен отсекает черновики и помеченные на удаление не проверяется автоматически — добавьте отдельно НЕ Реализация.ПометкаУдаления, если нужны только «живые» документы.

Отбор по табличной части

Если условие лежит в табличной части (например, документы, где есть конкретная номенклатура), соединяйте шапку с табличной частью или фильтруйте по ней:

Запрос.Текст =

"ВЫБРАТЬ РАЗЛИЧНЫЕ

| Товары.Ссылка КАК Документ

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Номенклатура = &Номенклатура

| И Товары.Ссылка.Проведен";

РАЗЛИЧНЫЕ здесь обязательно: одна позиция номенклатуры может встречаться в документе несколько раз, и без неё документ продублируется в выборке.

Обход документов методом Выбрать()

Метод Выбрать() менеджера документа возвращает объектную выборку ссылок. Синтаксис: Документы.РеализацияТоваровУслуг.Выбрать(НачалоПериода, КонецПериода). Параметры необязательные, но без них будет выбран весь журнал — на большой базе это долго.

Выборка = Документы.ПоступлениеТоваровУслуг.Выбрать(НачалоМесяца(Дата), КонецМесяца(Дата));

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

Если Выборка.Проведен Тогда

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

ДокОбъект.Комментарий = "Обработано";

ДокОбъект.Записать();

КонецЕсли;

КонецЦикла;

Ключевой момент: Выборка даёт только ссылку и поля, обращение к которым подгружает данные. Для изменения документа нужен ПолучитьОбъект() — это дорогая операция. Если обрабатываете тысячи документов, сначала отберите нужные запросом, а ПолучитьОбъект() вызывайте только для реально изменяемых.

Отбор в журнале документов без программирования

Пользователю выборка обычно нужна в интерфейсе. В журнале документов (например, «Все документы» или журнал конкретного вида) откройте настройку отбора: в типовых конфигурациях это кнопка «Ещё» → «Настроить список» или поле быстрого отбора над списком. Добавьте условия по организации, контрагенту, дате, сумме — список сразу перестроится.

Полезные приёмы: отбор по периоду удобнее задавать через стандартный период (кнопка выбора периода в панели), а комбинацию условий сохранить как настройку списка, чтобы не настраивать заново. Отбор по значению из открытого документа часто доступен через контекстное меню «Найти в списке» или «Отобрать по значению».

Порядок действий в журнале
  1. 1
    Откройте журнал нужного вида документов
  2. 2
    Задайте период через стандартный выбор периода
  3. 3
    Через «Ещё» → «Настроить список» добавьте условия по реквизитам
  4. 4
    Проверьте, что список содержит только нужные документы
  5. 5
    Сохраните настройку списка для повторного использования

Программный отбор динамического списка

В управляемых формах список документов — это динамический список. Установить отбор программно можно через свойство Отбор реквизита списка или через Список.КомпоновщикНастроек. Простой вариант в модуле формы:

ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = Организация;

ЭлементОтбора.Использование = Истина;

Если список должен всегда показывать ограниченный набор (например, только проведённые документы), отбор лучше задавать в настройках динамического списка в конфигураторе, а не кодом при каждом открытии формы — так настройка централизована и не дублируется.

Производительность и ограничения

Выборка без отбора по дате — главная причина медленных запросов к документам. Таблицы документов в активной базе содержат сотни тысяч записей, и полное сканирование ощутимо даже на сервере. Всегда ограничивайте период и добавляйте условия по индексированным полям (дата, организация, контрагент — обычно индексируются, произвольные строковые реквизиты — нет).

Ещё ограничения: метод Выбрать() с отбором по реквизиту работает только по реквизитам с признаком индексирования; виртуальные таблицы документов не существует — есть только основная таблица и табличные части; в запросе нельзя выбрать движения документа напрямую, только через соединение с регистрами.

Типичные ошибки
01
Подстановка дат и строк прямо в текст запроса конкатенацией — ошибки формата и уязвимость; используйте параметры
02
Выборка без ограничения периода — полное сканирование таблицы и долгое выполнение
03
ПолучитьОбъект() для каждого документа выборки, хотя нужно только прочитать данные — лишняя нагрузка в десятки раз
04
Забытое условие Проведен или ПометкаУдаления — в выборку попадают черновики и удалённые документы
05
Отбор по табличной части без РАЗЛИЧНЫЕ — дубли документов в результате

Проверка результата выборки

После выполнения запроса проверьте, что выборка не пустая и не подозрительно велика. Метод Результат.Пустой() сразу показывает отсутствие данных, а Выборка.Количество() — размер результата. Если количество равно нулю там, где документы точно есть, первым делом проверьте границы периода: частая причина — конец периода без КонецДня(), из-за чего документы последнего дня не попадают в выборку.

Для отладки выводите результат запроса в табличный документ через консоль запросов (в типовых конфигурациях — инструменты разработчика или внешняя консоль). Сверьте несколько документов из выборки с журналом вручную: совпадают ли номер, дата, контрагент.

Контрольные точки

Как проверить результат

Количество строк выборки
Норма

Соответствует ожиданиям по журналу за тот же период

Тревожный признак

Ноль или в разы больше ожидаемого — проверяйте условия ГДЕ и период

Границы периода
Норма

Документы первого и последнего дня присутствуют

Тревожный признак

Пропали документы последнего дня — добавьте КонецДня() к параметру

Статус документов
Норма

Только проведённые (если требуется), без помеченных на удаление

Тревожный признак

В выборке черновики или удалённые — добавьте условия Проведен и НЕ ПометкаУдаления

Частые вопросы

Как выбрать документы только за сегодня?

Используйте параметры НачалоДня(ТекущаяДата()) и КонецДня(ТекущаяДата()) в условии по дате. В запросе: Реализация.Дата МЕЖДУ &Начало И &Конец с этими параметрами.

Чем выборка запросом отличается от Выбрать()?

Запрос выполняется на СУБД, возвращает произвольный набор полей и поддерживает сложные соединения — быстрее и гибче. Выбрать() возвращает ссылки документов для обхода в цикле, отбор ограничен датой и индексированными реквизитами.

Как получить сразу объекты документов, а не ссылки?

Напрямую выбрать объекты нельзя — платформа всегда возвращает ссылки. Объект получают через Ссылка.ПолучитьОбъект() только для тех документов, которые реально нужно изменить, чтобы не тратить память и время.

Почему запрос не находит документы последнего дня периода?

Потому что дата документа содержит время, а параметр конца периода задан как начало дня (00:00:00). Оберните параметр в КонецДня() или используйте условие Дата < &СледующийДень.

Как выбрать документы по нескольким организациям?

Передайте в параметр массив или список значений и используйте условие Организация В (&СписокОрганизаций). Платформа сама развернёт список в условие IN.

Можно ли выбрать документы по движениям в регистре?

Да, через соединение с таблицей регистра по регистратору: ВЫБРАТЬ РАЗЛИЧНЫЕ Регистр.Регистратор ИЗ РегистрНакопления.Продажи ГДЕ ... — так вы получите документы, сделавшие нужные движения.

Итог

Что важно запомнить

Для отчётов и массовых выборок используйте запрос с параметрами и отбором ГДЕ, для изменения документов в цикле — Выбрать() с ПолучитьОбъект() только у нужных, пользователю достаточно отбора в журнале. Всегда ограничивайте период, проверяйте Проведен и ПометкаУдаления, а массовую запись сначала тестируйте на копии базы.