Разработка и Конфигурация · 11 мин
Как получить период из регистра сведений в 1С
Способы получить период из регистра сведений 1С: запрос к таблице, СрезПоследних и СрезПервых, методы ПолучитьПоследнее и ПолучитьПервое, типовые ошибки и примеры кода.
Регистр сведений с периодичностью «в пределах секунды», «дня», «месяца» и т.д. хранит системное поле Период — дату и время записи значения. Получить его можно несколькими способами: запросом к таблице регистра, виртуальными таблицами СрезПоследних и СрезПервых, а также методами объекта РегистрСведенийМенеджер — ПолучитьПоследнее и ПолучитьПервое. Выбор зависит от того, нужен период одной записи, срез по отбору или полная история изменений.
Важно понимать: период — это не ресурс и не реквизит, а служебное измерение времени, которое платформа заполняет автоматически при записи. Поэтому обращаться к нему нужно именно как к полю Период в запросе или как к свойству записи в объектной модели. Попытка прочитать период через «точку» у выборки без указания поля — частая ошибка новичков.
Ниже разобраны все рабочие способы с примерами кода, условиями выбора между ними, проверкой результата и типичными ошибками. Примеры приведены для управляемого приложения, но синтаксис идентичен и для обычных форм.
Что такое период в регистре сведений и когда он существует
Поле Период появляется только у периодических регистров сведений. Если в конфигураторе у регистра установлена периодичность «Непериодический», поля Период в таблице нет, и любые попытки обратиться к нему в запросе завершатся ошибкой «Поле не найдено». Поэтому первый шаг — открыть свойства регистра в конфигураторе и проверить значение свойства «Периодичность».
Периодичность определяет точность хранения: «в пределах секунды» сохраняет дату со временем, «в пределах дня/месяца/квартала/года» — только начало соответствующего интервала. Это важно при сравнении периодов: две записи с разным временем внутри одного дня при периодичности «в пределах дня» будут иметь одинаковый период, и вторая запись с тем же набором измерений перезапишет первую.
Дополнительно периодические регистры могут быть подчинены регистратору — тогда период записи наследуется из даты документа-регистратора, и получить его можно как из самой записи, так и из реквизита Регистратор.Дата.
Получение периода запросом к таблице регистра
Самый универсальный способ — запрос к физической таблице регистра. Поле называется Период, его можно выбирать, сортировать по нему и использовать в условиях. Пример запроса, возвращающего периоды и значения для конкретного элемента измерения:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Период КАК Период,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
|ГДЕ
| Цены.Номенклатура = &Номенклатура
|УПОРЯДОЧИТЬ ПО
| Период УБЫВ";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Период: " + Выборка.Период + ", цена: " + Выборка.Цена);
КонецЦикла;
Если нужен только последний (максимальный) период по отбору, используйте агрегатную функцию МАКСИМУМ — это быстрее, чем выгружать всю историю и искать максимум в коде:
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(Цены.Период) КАК Период
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
|ГДЕ
| Цены.Номенклатура = &Номенклатура";
Такой запрос вернёт одну строку. Если записей по отбору нет, поле Период будет содержать NULL — это нужно учитывать при обработке результата, иначе сравнение с датой даст неочевидное поведение.
СрезПоследних и СрезПервых — период актуальных значений
Виртуальные таблицы СрезПоследних и СрезПервых возвращают записи, актуальные на заданный момент, и поле Период в них показывает, когда это значение было установлено. Это самый частый сценарий: узнать не только текущее значение ресурса, но и дату, с которой оно действует.
Запрос.Текст =
"ВЫБРАТЬ
| Срез.Период КАК Период,
| Срез.Номенклатура КАК Номенклатура,
| Срез.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&НаДату, ) КАК Срез";
Запрос.УстановитьПараметр("НаДату", ТекущаяДатаСеанса());
Обратите внимание на границу включения: СрезПоследних(&НаДату) включает записи с периодом, равным указанной дате. Если параметр не задать (оставить пустые скобки), срез строится на максимальную дату — по всем существующим записям. Условие отбора передаётся вторым параметром виртуальной таблицы строкой, например "Номенклатура = &Номенклатура".
Методы ПолучитьПоследнее и ПолучитьПервое
Когда нужен период и значение одной записи по известному набору измерений, удобнее объектные методы менеджера регистра. Они не требуют построения запроса и возвращают структуру с ресурсами и реквизитами записи:
Отбор = Новый Структура("Номенклатура", НоменклатураСсылка);
Значения = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(ТекущаяДатаСеанса(), Отбор);
Если Значения.Цена <> Неопределено Тогда
Сообщить("Цена установлена: " + Значения.Цена);
КонецЕсли;
Особенность: ПолучитьПоследнее возвращает структуру, в которой нет поля Период — только ресурсы и реквизиты. Если нужен именно период найденной записи, используйте запрос с МАКСИМУМ(Период) или срез, либо создайте набор записей с отбором и прочитайте его. Первый параметр метода — момент времени, на который ищется значение; если его опустить, поиск идёт на самую позднюю дату.
Метод ПолучитьПервое работает зеркально — возвращает самую раннюю запись начиная с указанного момента. Оба метода при отсутствии записей возвращают структуру с пустыми (неопределёнными) значениями ресурсов, поэтому проверка результата обязательна.
- 1Проверьте в конфигураторе, что регистр периодический
- 2Определите набор измерений для отбора
- 3Сформируйте запрос с МАКСИМУМ(Период) или СрезПоследних с отбором
- 4Выполните запрос и проверьте результат на NULL
- 5Используйте полученный период для чтения полной записи набора записей
Чтение периода через набор записей и менеджер записи
Объектный подход нужен, когда вы уже работаете с записью для изменения. У набора записей и менеджера записи период доступен как свойство Период:
Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(НоменклатураСсылка);
Набор.Отбор.Период.Установить(НужнаяДата);
Набор.Прочитать();
Если Набор.Количество() > 0 Тогда
ПериодЗаписи = Набор[0].Период;
КонецЕсли;
Для независимого регистра можно использовать менеджер записи: создать его через СоздатьМенеджерЗаписи(), заполнить измерения и период, вызвать Прочитать() и затем проверить Менеджер.Выбран(). Если запись не найдена, свойство Выбран вернёт Ложь, а читать Период бессмысленно — там останется ранее присвоенное значение.
Учтите: чтение набора без отбора по всем измерениям загрузит в память все записи регистра. На больших таблицах это грубая ошибка, приводящая к зависанию сеанса. Всегда устанавливайте отбор до вызова Прочитать().
Выбор способа под задачу
Единого «правильного» метода нет — каждый вариант оптимален в своём сценарии. Ориентируйтесь на объём данных и на то, нужен ли сам период или только значение ресурса.
| Задача | Рекомендуемый способ | Ограничение |
|---|---|---|
| Период последней записи по отбору | Запрос с МАКСИМУМ(Период) | Возвращает NULL при пустом результате |
| Значение и дата актуальной цены/курса | СрезПоследних с отбором | Медленно без отбора по измерениям |
| Только значение ресурса, период не нужен | ПолучитьПоследнее | Период в результате отсутствует |
| Запись уже изменяется в коде | Набор записей, свойство Период | Требуется полный отбор по ключу записи |
| Вся история изменений по измерению | Запрос к таблице с сортировкой по Период | Большой объём выборки на длинной истории |
Сравнение вариантов
Гибкий, подходит для истории и агрегации; требует написания текста запроса
Даёт период и значение на дату одной конструкцией; чувствителен к отсутствию отбора
Короткий код для одной записи; не возвращает сам период
Нужен при чтении с последующей записью; требует точного отбора по ключу
Проверка результата и отладка
После получения периода убедитесь, что значение корректно. Для запроса с МАКСИМУМ проверяйте результат на NULL через Выборка.Период = NULL или функцию ЕСТЬNULL в самом запросе. Для среза — что выборка вообще содержит строки, иначе обращение к полю даст ошибку.
Быстрый способ проверить данные визуально — открыть регистр в режиме предприятия через список записей и включить отображение колонки «Период», либо выполнить тот же запрос в консоли запросов. Если период в запросе отличается от ожидаемого, проверьте периодичность регистра и часовой пояс сеанса — дата записи хранится с учётом времени сервера.
Как проверить результат
Дата (или NULL при отсутствии записей)
Неопределено там, где ожидалась дата из запроса
Период округлён до дня/месяца согласно настройке регистра
Время обрезано неожиданно — периодичность не «в пределах секунды»
Выборка содержит строку, менеджер записи Выбран() = Истина
Пустая выборка — отбор не совпал ни с одной записью
FAQ
Как получить период, если регистр сведений непериодический?
Никак — поля Период у такого регистра не существует. Если нужна дата изменения, добавьте в регистр собственный реквизит типа «Дата» и заполняйте его при записи, либо измените периодичность регистра в конфигураторе с переносом данных.
Почему ПолучитьПоследнее не возвращает период записи?
Метод по замыслу платформы возвращает структуру только с ресурсами и реквизитами. Чтобы узнать период найденной записи, выполните запрос с МАКСИМУМ(Период) по тому же отбору или используйте виртуальную таблицу СрезПоследних.
Чем отличается СрезПоследних с параметром даты и без него?
С указанной датой срез строится на этот момент включительно. Без параметра — на максимальную дату среди всех записей, то есть возвращаются самые последние значения по каждой комбинации измерений.
Как получить период записи, подчинённой регистратору?
Так же — через поле Период в запросе, поскольку платформа копирует туда дату документа. Альтернатива — обратиться к реквизиту Регистратор и прочитать его Дату, что удобно, когда нужны ещё и данные самого документа.
Почему запрос возвращает период без времени, хотя записывал с временем?
Периодичность регистра установлена «в пределах дня» или грубее — платформа обрезает время при записи. Чтобы хранить время, в конфигураторе нужно установить периодичность «В пределах секунды», при этом существующие записи сохранят уже усечённые даты.
Что быстрее: запрос с МАКСИМУМ или СрезПоследних?
Для получения только периода по конкретному отбору МАКСИМУМ обычно легче, так как не строит виртуальную таблицу. Срез оправдан, когда кроме периода нужны значения ресурсов на дату по нескольким измерениям сразу.
Что важно запомнить
Период есть только у периодических регистров сведений. Для одной записи используйте ПолучитьПоследнее или запрос с МАКСИМУМ(Период), для значений на дату — СрезПоследних с обязательным отбором. Всегда проверяйте результат на NULL и пустую выборку.