Регистры 1С:Предприятия 8.3 изнутри: от метаданных до запроса

· 11 мин

Содержание

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

Частое заблуждение новичков: «остаток товара можно посчитать, пробежав по документам». Можно, но на базе с сотней тысяч накладных такой отчёт будет строиться минутами. Регистры для того и придуманы: документ один раз пишет свои движения, а платформа хранит готовые итоги и отдаёт остаток на любую дату за доли секунды.

Какие бывают регистры и зачем они платформе

Регистр — это таблица, где каждая строка описывает факт: «на склад Основной пришло 10 штук товара А» или «с 01.03 цена товара А — 500 руб.». Строки регистра называют записями или движениями.

В 1С:Предприятии 8.3 четыре вида регистров:

ВидЧто хранитПример в типовыхЧем читают
Регистр сведенийЗначения параметров, часто с историейКурсы валют, цены номенклатурыСрезПоследних, СрезПервых, ПолучитьПоследнее()
Регистр накопленияКоличественные и суммовые показатели: приход и расходОстатки товаров, взаиморасчётыОстатки, Обороты, ОстаткиИОбороты
Регистр бухгалтерииПроводки по плану счетов с субконтоХозрасчётный в БП 3.0Остатки, Обороты, ОборотыДтКт, ДвиженияССубконто
Регистр расчётаНачисления с периодами действия и базойНачисления в ЗУП 3.1БазаНачисления, ДанныеГрафика

Состав полей у регистров похож:

  • 📐 Измерения — разрезы учёта: склад, номенклатура, контрагент. По ним группируются итоги.
  • 🔢 Ресурсы — то, что накапливается или хранится. У регистра накопления ресурсы только числовые.
  • 🏷️ Реквизиты — дополнительная информация о записи (комментарий, строка документа). Итогов по ним нет.
  • 🔗 Стандартные реквизиты — Период, Регистратор, НомерСтроки, Активность, у накопления остатков ещё ВидДвижения.

Правило выбора простое. Нужно знать «сколько есть сейчас и сколько ушло за период» — регистр накопления. Нужно знать «какое значение действует на дату» — регистр сведений . Учёт по счетам с корреспонденцией — регистр бухгалтерии , он строится только вместе с планом счетов. Сложная зарплата с перерасчётами — регистр расчёта, он опирается на план видов расчёта.

Регистр накопления: создание и настройка

Создаётся он в конфигураторе: дерево метаданных → Регистры накопления → правая кнопка → Добавить. Дальше по вкладкам.

Вид регистра: остатки или обороты

Первое решение — свойство Вид регистра:

  • 📦 Остатки — у каждой записи есть вид движения (Приход или Расход), платформа хранит итог на конец каждого периода. Подходит для товаров на складах, денег, долгов.
  • 📈 Обороты — вида движения нет, хранятся только суммы за период. Подходит для продаж, закупок, выручки: «остаток продаж» не имеет смысла.

Вид регистра после того, как в нём появились данные, лучше не менять — придётся перепроводить документы, а при смене на «Обороты» исчезнут виртуальные таблицы Остатки и ОстаткиИОбороты, и сломаются все запросы к ним.

Измерения, ресурсы и регистраторы

На вкладке Данные заведите поля. Пример для учёта товаров:

  1. Измерения: Склад (СправочникСсылка.Склады), Номенклатура (СправочникСсылка.Номенклатура).
  2. Ресурсы: Количество (Число 15.3), Сумма (Число 15.2).
  3. Реквизит, если нужен: Комментарий (Строка 100).

На вкладке Регистраторы отметьте документы, которые пишут движения: «Поступление товаров», «Реализация товаров». Регистр накопления без регистратора не живёт — у каждой записи он обязателен.

Не плодите измерения «на всякий случай». Каждое лишнее измерение множит число строк в таблице итогов. Если поле нужно только для отбора в отчёте и не участвует в итогах — сделайте его реквизитом.

У измерения есть свойство Индексировать. Включайте его для измерения, по которому часто фильтруют запросом, но которое стоит не первым в списке.

Регистр сведений: периодичность и режим записи

Регистр сведений хранит значения, которые меняются во времени или просто привязаны к набору ключей. Две настройки определяют, как с ним работать.

Периодичность

Свойство Периодичность задаёт, есть ли у записей дата и с какой точностью:

  • ⏸️ Непериодический — даты нет. Пример: соответствие «товар → штрихкод».
  • 🕐 В пределах секунды, дня, месяца, квартала, года — значение действует с указанной даты до следующей записи. Пример: цены, курсы, ставки.
  • 📄 В пределах регистратора — период совпадает с моментом документа-регистратора. Доступно только при подчинении регистратору.

Уникальность записи определяется набором «период + все измерения». Две записи с одинаковыми ключами система не примет.

Независимый режим или подчинение регистратору

Свойство Режим записи:

РежимКто пишетКогда выбирать
НезависимыйПользователь вручную, обработка, кодСправочная информация: курсы, контакты, настройки
Подчинение регистраторуТолько документ при проведенииДанные, которые должны исчезать при отмене проведения

В независимом режиме запись пишут через набор записей с отбором:

Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(НачалоДня(ТекущаяДатаСеанса()));
Набор.Отбор.Номенклатура.Установить(Номенклатура);
Набор.Отбор.ВидЦены.Установить(ВидЦены);

Запись = Набор.Добавить();
Запись.Период = НачалоДня(ТекущаяДатаСеанса());
Запись.Номенклатура = Номенклатура;
Запись.ВидЦены = ВидЦены;
Запись.Цена = 500;

Набор.Записать(); // по умолчанию заменяет записи, попавшие под отбор

Отбор здесь не формальность: Записать() с замещением удалит все существующие записи под этим отбором. Без отбора по Номенклатура вы сотрёте цены всех товаров на эту дату.

У регистра сведений есть ещё свойства Ведущее у измерения и Основной отбор. Ведущее измерение удаляет записи при удалении объекта, на который оно ссылается. Основной отбор нужен, чтобы список записей можно было открыть из формы этого объекта.

Как документ записывает движения в регистры

Движения формируются в модуле объекта документа, в обработчике ОбработкаПроведения. Конструктор движений (кнопка Конструктор движений на вкладке Движения документа) создаёт заготовку, но понимать её нужно.

Минимальный пример

Документ «Поступление товаров» с табличной частью Товары:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

    Движения.ОстаткиТоваров.Записывать = Истина;

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

КонецПроцедуры

Что здесь происходит:

  1. Движения.ОстаткиТоваров — набор записей регистра, уже отобранный по текущему документу. Регистратор подставится сам.
  2. Записывать = Истина говорит платформе: после обработчика запиши этот набор. Без этой строки движения молча не сохранятся.
  3. Перед проведением старые движения документа очищаются, если в свойствах документа Удаление движений стоит автоматический вариант. Так повторное проведение не задваивает записи.

Расход с контролем остатка

С приходом всё просто. Расход сложнее: нельзя продать 15 штук, когда на складе 10, и нельзя, чтобы два пользователя одновременно списали последние единицы. Практик решает это двумя приёмами.

Приём 1 — управляемая блокировка до чтения остатков. Блокируем строки регистра по товарам документа:

Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТоваров");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = Товары;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
Блокировка.Заблокировать();

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

Приём 2 — «новая методика» контроля. Сначала записываем расход, потом одним запросом ищем отрицательные остатки:

Движения.ОстаткиТоваров.Записать();

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Ост.Номенклатура,
|    Ост.КоличествоОстаток
|ИЗ
|    РегистрНакопления.ОстаткиТоваров.Остатки(
|        &Граница,
|        Склад = &Склад
|            И Номенклатура В (&СписокТоваров)) КАК Ост
|ГДЕ
|    Ост.КоличествоОстаток < 0";
Запрос.УстановитьПараметр("Граница", Новый Граница(МоментВремени(), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("СписокТоваров", Товары.ВыгрузитьКолонку("Номенклатура"));

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Отказ = Истина;
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = СтрШаблон("Не хватает товара %1: недостача %2",
        Выборка.Номенклатура, Формат(-Выборка.КоличествоОстаток, "ЧГ=0"));
    Сообщение.Сообщить();
КонецЦикла;

Если Отказ = Истина, транзакция откатится вместе с уже записанными движениями. Плюс подхода: остаток читается один раз и уже с учётом этого документа, без отдельной «таблицы потребности».

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

Получение данных: срезы, остатки и запросы

Читать регистры можно двумя путями: методами менеджера и запросом. Для одиночного значения подходит менеджер, для отчётов и проведения — только запрос.

Методы менеджера регистра сведений

Курс валюты на сегодня одной строкой:

Данные = РегистрыСведений.КурсыВалют.ПолучитьПоследнее(
    ТекущаяДатаСеанса(), Новый Структура("Валюта", Валюта));
Курс = Данные.Курс;

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

Виртуальные таблицы в запросах

У каждого вида регистра свой набор виртуальных таблиц:

  • 🗂️ СрезПоследних(Период, Условие) — значение на дату по каждому набору измерений. СрезПервых — первое значение после даты.
  • 📦 Остатки(Период, Условие) — остатки на момент.
  • 📈 Обороты(Начало, Конец, Периодичность, Условие) — приход, расход и оборот за интервал.
  • 🔄 ОстаткиИОбороты(Начало, Конец, Периодичность, МетодДополнения, Условие) — начальный остаток, обороты, конечный остаток в одной таблице. Удобна для ведомостей.

Цены на дату по виду цены:

ВЫБРАТЬ
    Цены.Номенклатура,
    Цены.Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
        &Дата,
        ВидЦены = &ВидЦены) КАК Цены

Главный приём здесь: условие отбора пишите в параметрах виртуальной таблицы, а не в ГДЕ. В параметре платформа отфильтрует данные до расчёта среза или остатка. В ГДЕ она сначала посчитает итоги по всем товарам и складам, а потом выбросит лишнее. На большой базе разница — секунды против минут.

Остаток на конкретную дату для регистра остатков платформа считает так: берёт ближайший сохранённый итог и досчитывает движения от него до нужной даты. Поэтому запрос остатков на текущую дату работает быстрее, чем на дату три года назад внутри закрытого периода — если итоги настроены правильно.

Физическая таблица

Обращение РегистрНакопления.ОстаткиТоваров без виртуальной таблицы даёт сами записи движений. Её используют для отчёта «что провёл документ» и в отладке: отбор по полю Регистратор покажет все строки, записанные конкретным документом.

Итоги и оптимизация регистров

Для регистров накопления остатков и регистров бухгалтерии платформа хранит итоги по месяцам. Управлять ими можно из режима 1С:Предприятие: в конфигурациях на БСП это Администрирование → Поддержка и обслуживание → Управление итогами и агрегатами. В конфигурациях без такого раздела есть стандартная обработка «Управление итогами» в меню Все функции → Стандартные.

Что там делают:

ДействиеЗачемКогда
Установить период рассчитанных итоговИтоги хранятся только до этой даты, запись движений в прошлое идёт быстрееРаз в месяц после закрытия периода
Пересчитать итогиИсправить расхождение итогов и движенийПосле сбоев, подозрения на неверные остатки
Отключить и включить использование итоговУскорить массовую запись, например при загрузке данныхПеред загрузкой, с обязательным включением после
Включить разделение итоговУбрать конфликты блокировок при параллельной записиМного пользователей проводят документы одновременно

Пересчёт итогов на большой базе нагружает сервер и может занимать часы. Запускайте его в нерабочее время: пользователи в это время получат замедление и ожидание блокировок.

Для оборотных регистров накопления вместо итогов есть агрегаты — предрасчитанные обороты по выбранным измерениям и периодичности. Их описывают в конфигураторе, у самого регистра, а включают и перестраивают в той же обработке управления итогами. Агрегаты оправданы, когда регистр продаж разросся до десятков миллионов строк и отчёты по нему тормозят.

Ещё несколько приёмов, которые ускоряют работу с регистрами:

  • 🎯 Порядок измерений имеет значение: платформа строит индекс по ним в порядке перечисления. Самое частое в отборах — первым.
  • 🚫 Не соединяйте виртуальную таблицу с большой таблицей, если тот же отбор можно передать параметром.
  • 📉 Для отчёта за месяц не берите ОстаткиИОбороты с периодичностью Запись — это выборка по каждому движению.

Частые ошибки в работе с регистрами и способы отладки

Большая часть проблем с регистрами видна по одному из трёх симптомов. Выберите свой:

Диагностика: выберите симптом

Что ещё ломается чаще, чем хотелось бы:

  • ❌ Не заполнен Период. У движений документа его ставят равным Дата документа. Пустой период — запись в начало времён и странные остатки.
  • ❌ Знак в ресурсе. В регистре остатков расход пишут положительным числом с видом Расход. Отрицательное количество с видом Приход формально сработает, но сломает обороты: приход станет минусовым.
  • ❌ Чтение остатков без блокировки. Два кассира одновременно продают последнюю единицу, оба видят «1 шт.», остаток уходит в минус.
  • ❌ Запрос в цикле. Срез цены для каждой строки накладной отдельным запросом вместо одного запроса со списком товаров.

Как отладить движения

  1. В форме документа посмотрите его движения. В БП 3.0 это кнопка ДтКт («Показать проводки и другие движения документа»), в конфигурациях на БСП — отчёт «Движения документа» из меню отчётов формы.
  2. В конфигураторе поставьте точку останова в ОбработкаПроведения и запустите отладку (F5). В табло вычислите Движения.ОстаткиТоваров.Выгрузить() — увидите таблицу записей до сохранения.
  3. Для запросов используйте консоль запросов: выполните тот же текст с теми же параметрами и сравните виртуальную таблицу с физической по полю Регистратор.
Чем регистр сведений отличается от справочника?
У справочника есть ссылка, код и наименование — это объект, на который ссылаются другие данные. Регистр сведений хранит значения по комбинации ключей без собственной ссылки. Цена товара на дату — это регистр, сам товар — справочник.
Можно ли записать движения в регистр накопления без документа?
Нет. У регистра накопления регистратор обязателен. Для ручных корректировок заводят отдельный документ, например «Корректировка остатков» или «Операция».
Сколько измерений можно сделать у регистра?
Ограничение упирается не в платформу, а в скорость: каждое измерение увеличивает таблицу итогов. На практике у рабочих регистров 3–6 измерений, остальное выносят в реквизиты.
Почему ресурс регистра сведений может быть строкой, а у накопления — нет?
Регистр накопления суммирует ресурсы, поэтому они только числовые. Регистр сведений ничего не суммирует, его ресурсы могут быть любого типа: строки, ссылки, даты.
Нужно ли перепроводить документы после добавления нового измерения?
Да, если новое измерение должно заполняться у уже проведённых документов. Иначе у старых записей оно останется пустым, и отчёты в разрезе этого измерения покажут пустую строку.