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