Регистры 1С:Предприятия 8.3 изнутри: от метаданных до запроса
Содержание
Работа с регистрами в 1С сводится к трём действиям: описать регистр в конфигураторе (измерения, ресурсы, реквизиты), записать в него движения из обработчика ОбработкаПроведения документа и прочитать данные запросом через виртуальные таблицы — Остатки, Обороты, СрезПоследних. Всё остальное — настройки скорости и контроль ошибок.
Частое заблуждение новичков: «остаток товара можно посчитать, пробежав по документам». Можно, но на базе с сотней тысяч накладных такой отчёт будет строиться минутами. Регистры для того и придуманы: документ один раз пишет свои движения, а платформа хранит готовые итоги и отдаёт остаток на любую дату за доли секунды.
Какие бывают регистры и зачем они платформе
Регистр — это таблица, где каждая строка описывает факт: «на склад Основной пришло 10 штук товара А» или «с 01.03 цена товара А — 500 руб.». Строки регистра называют записями или движениями.
В 1С:Предприятии 8.3 четыре вида регистров:
| Вид | Что хранит | Пример в типовых | Чем читают |
|---|---|---|---|
| Регистр сведений | Значения параметров, часто с историей | Курсы валют, цены номенклатуры | СрезПоследних, СрезПервых, ПолучитьПоследнее() |
| Регистр накопления | Количественные и суммовые показатели: приход и расход | Остатки товаров, взаиморасчёты | Остатки, Обороты, ОстаткиИОбороты |
| Регистр бухгалтерии | Проводки по плану счетов с субконто | Хозрасчётный в БП 3.0 | Остатки, Обороты, ОборотыДтКт, ДвиженияССубконто |
| Регистр расчёта | Начисления с периодами действия и базой | Начисления в ЗУП 3.1 | БазаНачисления, ДанныеГрафика |
Состав полей у регистров похож:
- 📐 Измерения — разрезы учёта: склад, номенклатура, контрагент. По ним группируются итоги.
- 🔢 Ресурсы — то, что накапливается или хранится. У регистра накопления ресурсы только числовые.
- 🏷️ Реквизиты — дополнительная информация о записи (комментарий, строка документа). Итогов по ним нет.
- 🔗 Стандартные реквизиты —
Период,Регистратор,НомерСтроки,Активность, у накопления остатков ещёВидДвижения.
Правило выбора простое. Нужно знать «сколько есть сейчас и сколько ушло за период» — регистр накопления. Нужно знать «какое значение действует на дату» — регистр сведений . Учёт по счетам с корреспонденцией — регистр бухгалтерии , он строится только вместе с планом счетов. Сложная зарплата с перерасчётами — регистр расчёта, он опирается на план видов расчёта.
Регистр накопления: создание и настройка
Создаётся он в конфигураторе: дерево метаданных → Регистры накопления → правая кнопка → Добавить. Дальше по вкладкам.
Вид регистра: остатки или обороты
Первое решение — свойство Вид регистра:
- 📦 Остатки — у каждой записи есть вид движения (
ПриходилиРасход), платформа хранит итог на конец каждого периода. Подходит для товаров на складах, денег, долгов. - 📈 Обороты — вида движения нет, хранятся только суммы за период. Подходит для продаж, закупок, выручки: «остаток продаж» не имеет смысла.
Вид регистра после того, как в нём появились данные, лучше не менять — придётся перепроводить документы, а при смене на «Обороты» исчезнут виртуальные таблицы Остатки и ОстаткиИОбороты, и сломаются все запросы к ним.
Измерения, ресурсы и регистраторы
На вкладке Данные заведите поля. Пример для учёта товаров:
- Измерения:
Склад(СправочникСсылка.Склады),Номенклатура(СправочникСсылка.Номенклатура). - Ресурсы:
Количество(Число 15.3),Сумма(Число 15.2). - Реквизит, если нужен:
Комментарий(Строка 100).
На вкладке Регистраторы отметьте документы, которые пишут движения: «Поступление товаров», «Реализация товаров». Регистр накопления без регистратора не живёт — у каждой записи он обязателен.
Не плодите измерения «на всякий случай». Каждое лишнее измерение множит число строк в таблице итогов. Если поле нужно только для отбора в отчёте и не участвует в итогах — сделайте его реквизитом.
У измерения есть свойство Индексировать. Включайте его для измерения, по которому часто фильтруют запросом, но которое стоит не первым в списке.
Регистр сведений: периодичность и режим записи
Регистр сведений хранит значения, которые меняются во времени или просто привязаны к набору ключей. Две настройки определяют, как с ним работать.
Периодичность
Свойство Периодичность задаёт, есть ли у записей дата и с какой точностью:
- ⏸️ Непериодический — даты нет. Пример: соответствие «товар → штрихкод».
- 🕐 В пределах секунды, дня, месяца, квартала, года — значение действует с указанной даты до следующей записи. Пример: цены, курсы, ставки.
- 📄 В пределах регистратора — период совпадает с моментом документа-регистратора. Доступно только при подчинении регистратору.
Уникальность записи определяется набором «период + все измерения». Две записи с одинаковыми ключами система не примет.
Независимый режим или подчинение регистратору
Свойство Режим записи:
| Режим | Кто пишет | Когда выбирать |
|---|---|---|
| Независимый | Пользователь вручную, обработка, код | Справочная информация: курсы, контакты, настройки |
| Подчинение регистратору | Только документ при проведении | Данные, которые должны исчезать при отмене проведения |
В независимом режиме запись пишут через набор записей с отбором:
Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(НачалоДня(ТекущаяДатаСеанса()));
Набор.Отбор.Номенклатура.Установить(Номенклатура);
Набор.Отбор.ВидЦены.Установить(ВидЦены);
Запись = Набор.Добавить();
Запись.Период = НачалоДня(ТекущаяДатаСеанса());
Запись.Номенклатура = Номенклатура;
Запись.ВидЦены = ВидЦены;
Запись.Цена = 500;
Набор.Записать(); // по умолчанию заменяет записи, попавшие под отбор
Отбор здесь не формальность: Записать() с замещением удалит все существующие записи под этим отбором. Без отбора по Номенклатура вы сотрёте цены всех товаров на эту дату.
У регистра сведений есть ещё свойства Ведущее у измерения и Основной отбор. Ведущее измерение удаляет записи при удалении объекта, на который оно ссылается. Основной отбор нужен, чтобы список записей можно было открыть из формы этого объекта.
Как документ записывает движения в регистры
Движения формируются в модуле объекта документа, в обработчике ОбработкаПроведения. Конструктор движений (кнопка Конструктор движений на вкладке Движения документа) создаёт заготовку, но понимать её нужно.
Минимальный пример
Документ «Поступление товаров» с табличной частью Товары:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого СтрокаТЧ Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = СтрокаТЧ.Номенклатура;
Движение.Количество = СтрокаТЧ.Количество;
Движение.Сумма = СтрокаТЧ.Сумма;
КонецЦикла;
КонецПроцедуры
Что здесь происходит:
Движения.ОстаткиТоваров— набор записей регистра, уже отобранный по текущему документу.Регистраторподставится сам.Записывать = Истинаговорит платформе: после обработчика запиши этот набор. Без этой строки движения молча не сохранятся.- Перед проведением старые движения документа очищаются, если в свойствах документа
Удаление движенийстоит автоматический вариант. Так повторное проведение не задваивает записи.
Расход с контролем остатка
С приходом всё просто. Расход сложнее: нельзя продать 15 штук, когда на складе 10, и нельзя, чтобы два пользователя одновременно списали последние единицы. Практик решает это двумя приёмами.
Приём 1 — управляемая блокировка до чтения остатков. Блокируем строки регистра по товарам документа:
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТоваров");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = Товары;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
Блокировка.Заблокировать();
Для этого в свойствах конфигурации должен стоять управляемый режим блокировки (или автоматический и управляемый), а у документа и регистра — Управляемый.
Приём 2 — «новая методика» контроля. Сначала записываем расход, потом одним запросом ищем отрицательные остатки:
Движения.ОстаткиТоваров.Записать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Ост.Номенклатура,
| Ост.КоличествоОстаток
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Остатки(
| &Граница,
| Склад = &Склад
| И Номенклатура В (&СписокТоваров)) КАК Ост
|ГДЕ
| Ост.КоличествоОстаток < 0";
Запрос.УстановитьПараметр("Граница", Новый Граница(МоментВремени(), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("СписокТоваров", Товары.ВыгрузитьКолонку("Номенклатура"));
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = СтрШаблон("Не хватает товара %1: недостача %2",
Выборка.Номенклатура, Формат(-Выборка.КоличествоОстаток, "ЧГ=0"));
Сообщение.Сообщить();
КонецЦикла;
Если Отказ = Истина, транзакция откатится вместе с уже записанными движениями. Плюс подхода: остаток читается один раз и уже с учётом этого документа, без отдельной «таблицы потребности».
Новый Граница(МоментВремени(), ВидГраницы.Включая) включает движения самого документа. Если взять просто МоментВремени(), расход текущего документа в остаток не попадёт и контроль ничего не поймает.
Получение данных: срезы, остатки и запросы
Читать регистры можно двумя путями: методами менеджера и запросом. Для одиночного значения подходит менеджер, для отчётов и проведения — только запрос.
Методы менеджера регистра сведений
Курс валюты на сегодня одной строкой:
Данные = РегистрыСведений.КурсыВалют.ПолучитьПоследнее(
ТекущаяДатаСеанса(), Новый Структура("Валюта", Валюта));
Курс = Данные.Курс;
Метод вернёт структуру ресурсов. Если записи нет — ресурсы будут пустыми (0 для чисел), исключения не будет. Вызывать ПолучитьПоследнее() в цикле по строкам табличной части — плохая идея: каждый вызов идёт отдельным обращением к базе.
Виртуальные таблицы в запросах
У каждого вида регистра свой набор виртуальных таблиц:
- 🗂️
СрезПоследних(Период, Условие)— значение на дату по каждому набору измерений.СрезПервых— первое значение после даты. - 📦
Остатки(Период, Условие)— остатки на момент. - 📈
Обороты(Начало, Конец, Периодичность, Условие)— приход, расход и оборот за интервал. - 🔄
ОстаткиИОбороты(Начало, Конец, Периодичность, МетодДополнения, Условие)— начальный остаток, обороты, конечный остаток в одной таблице. Удобна для ведомостей.
Цены на дату по виду цены:
ВЫБРАТЬ
Цены.Номенклатура,
Цены.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
&Дата,
ВидЦены = &ВидЦены) КАК Цены
Главный приём здесь: условие отбора пишите в параметрах виртуальной таблицы, а не в ГДЕ. В параметре платформа отфильтрует данные до расчёта среза или остатка. В ГДЕ она сначала посчитает итоги по всем товарам и складам, а потом выбросит лишнее. На большой базе разница — секунды против минут.
Остаток на конкретную дату для регистра остатков платформа считает так: берёт ближайший сохранённый итог и досчитывает движения от него до нужной даты. Поэтому запрос остатков на текущую дату работает быстрее, чем на дату три года назад внутри закрытого периода — если итоги настроены правильно.
Физическая таблица
Обращение РегистрНакопления.ОстаткиТоваров без виртуальной таблицы даёт сами записи движений. Её используют для отчёта «что провёл документ» и в отладке: отбор по полю Регистратор покажет все строки, записанные конкретным документом.
Итоги и оптимизация регистров
Для регистров накопления остатков и регистров бухгалтерии платформа хранит итоги по месяцам. Управлять ими можно из режима 1С:Предприятие: в конфигурациях на БСП это Администрирование → Поддержка и обслуживание → Управление итогами и агрегатами. В конфигурациях без такого раздела есть стандартная обработка «Управление итогами» в меню Все функции → Стандартные.
Что там делают:
| Действие | Зачем | Когда |
|---|---|---|
| Установить период рассчитанных итогов | Итоги хранятся только до этой даты, запись движений в прошлое идёт быстрее | Раз в месяц после закрытия периода |
| Пересчитать итоги | Исправить расхождение итогов и движений | После сбоев, подозрения на неверные остатки |
| Отключить и включить использование итогов | Ускорить массовую запись, например при загрузке данных | Перед загрузкой, с обязательным включением после |
| Включить разделение итогов | Убрать конфликты блокировок при параллельной записи | Много пользователей проводят документы одновременно |
Пересчёт итогов на большой базе нагружает сервер и может занимать часы. Запускайте его в нерабочее время: пользователи в это время получат замедление и ожидание блокировок.
Для оборотных регистров накопления вместо итогов есть агрегаты — предрасчитанные обороты по выбранным измерениям и периодичности. Их описывают в конфигураторе, у самого регистра, а включают и перестраивают в той же обработке управления итогами. Агрегаты оправданы, когда регистр продаж разросся до десятков миллионов строк и отчёты по нему тормозят.
Ещё несколько приёмов, которые ускоряют работу с регистрами:
- 🎯 Порядок измерений имеет значение: платформа строит индекс по ним в порядке перечисления. Самое частое в отборах — первым.
- 🚫 Не соединяйте виртуальную таблицу с большой таблицей, если тот же отбор можно передать параметром.
- 📉 Для отчёта за месяц не берите
ОстаткиИОборотыс периодичностьюЗапись— это выборка по каждому движению.
Частые ошибки в работе с регистрами и способы отладки
Большая часть проблем с регистрами видна по одному из трёх симптомов. Выберите свой:
Что ещё ломается чаще, чем хотелось бы:
- ❌ Не заполнен
Период. У движений документа его ставят равнымДатадокумента. Пустой период — запись в начало времён и странные остатки. - ❌ Знак в ресурсе. В регистре остатков расход пишут положительным числом с видом
Расход. Отрицательное количество с видомПриходформально сработает, но сломает обороты: приход станет минусовым. - ❌ Чтение остатков без блокировки. Два кассира одновременно продают последнюю единицу, оба видят «1 шт.», остаток уходит в минус.
- ❌ Запрос в цикле. Срез цены для каждой строки накладной отдельным запросом вместо одного запроса со списком товаров.
Как отладить движения
- В форме документа посмотрите его движения. В БП 3.0 это кнопка
ДтКт(«Показать проводки и другие движения документа»), в конфигурациях на БСП — отчёт «Движения документа» из меню отчётов формы. - В конфигураторе поставьте точку останова в
ОбработкаПроведенияи запустите отладку (F5). В табло вычислитеДвижения.ОстаткиТоваров.Выгрузить()— увидите таблицу записей до сохранения. - Для запросов используйте консоль запросов: выполните тот же текст с теми же параметрами и сравните виртуальную таблицу с физической по полю
Регистратор.