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

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

Как получить ресурс из регистра сведений 1С

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

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

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

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

Как устроен регистр сведений и что влияет на способ чтения

Перед написанием кода откройте регистр в конфигураторе и проверьте три свойства. Первое — периодичность: «Непериодический», «В пределах секунды», «В пределах дня» и так далее. Второе — режим записи: «Независимый» или «Подчинение регистратору». Третье — состав измерений: от него зависит, какие поля нужно передать в отбор, чтобы однозначно адресовать запись.

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

Получение ресурса запросом через срез последних

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

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

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

"ВЫБРАТЬ

| КурсыВалютСрезПоследних.Курс КАК Курс

|ИЗ

| РегистрСведений.КурсыВалют.СрезПоследних(&Период, Валюта = &Валюта) КАК КурсыВалютСрезПоследних";

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

Запрос.УстановитьПараметр("Валюта", ВалютаДокумента);

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

Если Не Результат.Пустой() Тогда

Выборка = Результат.Выбрать();

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

Курс = Выборка.Курс;

Иначе

Курс = 0; // записи нет — обработать ситуацию

КонецЕсли;

Обратите внимание на обработку пустого результата: если по заданному отбору записей нет, запрос вернёт пустую выборку, и обращение к полю даст ошибку. Всегда проверяйте Результат.Пустой() или используйте ЕСТЬNULL при соединении с другими таблицами.

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

Получение ресурса методами менеджера регистра

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

// Периодический регистр

Отбор = Новый Структура("Валюта", ВалютаДокумента);

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

Если Значения.Количество() > 0 Тогда

Курс = Значения.Курс;

КонецЕсли;

// Непериодический регистр

Отбор = Новый Структура("Организация", Организация);

Значения = РегистрыСведений.ОтветственныеЛица.Получить(Отбор);

Руководитель = Значения.Руководитель;

Важная деталь: если запись не найдена, метод возвращает структуру со значениями по умолчанию (пустые ссылки, нули), а не пустую структуру. Поэтому проверять результат надо не на «пустоту структуры», а на осмысленность значения ресурса — например, Курс = 0 означает, что записи нет. Ключи структуры отбора должны точно совпадать с именами измерений, иначе получите ошибку выполнения.

Массовое получение ресурсов для списка ключей

Типовая задача документа: для табличной части из сотни товаров подставить цены. Решать её вызовом ПолучитьПоследнее() в цикле нельзя — это сотни обращений к СУБД. Правильный подход: выгрузить список номенклатуры во временную таблицу или передать массив в параметр и получить все цены одним запросом.

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

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

"ВЫБРАТЬ

| Срез.Номенклатура КАК Номенклатура,

| Срез.Цена КАК Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(

| &Дата,

| Номенклатура В (&СписокНоменклатуры)

| И ТипЦен = &ТипЦен) КАК Срез";

Запрос.УстановитьПараметр("СписокНоменклатуры", МассивТоваров);

Результат удобно выгрузить в таблицу значений и индексировать по колонке измерения, либо сразу обойти выборкой и заполнить соответствие «Номенклатура → Цена». Тогда в цикле по строкам документа останется только взять значение из соответствия — быстро и без повторных обращений к базе.

Порядок действий для массового чтения
  1. 1
    Соберите из табличной части массив значений измерения (товары, валюты)
  2. 2
    Сформируйте запрос к СрезПоследних с условием Измерение В (&Список)
  3. 3
    Передайте дату среза и массив в параметры запроса
  4. 4
    Выгрузите результат и постройте соответствие ключ-значение
  5. 5
    В цикле по строкам берите ресурс из соответствия, обрабатывая отсутствующие ключи

Чтение через набор записей и менеджер записи

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

Запись = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();

Запись.Номенклатура = Товар;

Запись.Прочитать();

Если Запись.Выбран() Тогда

Штрихкод = Запись.Штрихкод;

КонецЕсли;

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

Сравнение способов и выбор под задачу

Единого «лучшего» способа нет — выбор определяется сценарием. Запрос к срезу последних выигрывает при массовом чтении и при необходимости соединить ресурс с другими данными. Методы менеджера короче и читабельнее для одиночных обращений. Менеджер записи нужен, когда за чтением следует изменение той же записи.

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

Запрос к СрезПоследних

Массовое чтение, соединения с другими таблицами, отчёты. Требует аккуратной обработки пустого результата.

ПолучитьПоследнее / Получить

Одиночное чтение одного ресурса. Короткий код, но медленно в циклах; при отсутствии записи возвращает значения по умолчанию.

Менеджер записи

Когда после чтения нужно изменить или удалить конкретную запись. Требует точного заполнения всех измерений ключа.

Набор записей с отбором

Чтение и перезапись группы записей. Опасен при неполном отборе — можно затереть лишнее.

Типичные ошибки и проверка результата

Типичные ошибки
01
Чтение основной таблицы периодического регистра без среза — получаете произвольную историческую запись вместо актуальной
02
Вызов ПолучитьПоследнее в цикле по строкам документа — резкое падение производительности на больших табличных частях
03
Отсутствие проверки на пустой результат — ошибка обращения к полю выборки или незаметный ноль вместо цены
04
Опечатка в имени измерения в структуре отбора — исключение времени выполнения
05
Передача даты без времени, когда в регистре записи в пределах дня — срез берётся на начало дня, а не на нужный момент

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

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

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

Период найденной записи
Норма

Период меньше или равен дате среза и близок к ней

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

Период сильно старше даты среза — возможно, актуальных данных нет

Значение ресурса
Норма

Заполнено и соответствует данным в списке регистра

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

Ноль или пустая ссылка при уверенности, что запись есть — проверьте отбор

Полнота отбора
Норма

В отборе все измерения, влияющие на уникальность

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

Отбор по части измерений — ресурс может быть от чужой записи

Отдельно проверьте поведение на граничных случаях: дата среза раньше первой записи регистра, измерение с пустым значением, регистр без единой записи. Код, корректно отрабатывающий эти ситуации (возвращает значение по умолчанию и пишет понятное сообщение), избавит от сбоев в прикладной логике.

Итог

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

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

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

Чем СрезПоследних отличается от СрезПервых?

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

Почему ПолучитьПоследнее возвращает ноль, хотя запись в регистре есть?

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

Как получить ресурс регистра, подчинённого регистратору?

Читайте основную таблицу регистра с отбором по регистратору или по измерениям обычным запросом. Срез последних для таких регистров технически доступен, но на практике чаще нужны движения конкретного документа: ВЫБРАТЬ ... ИЗ РегистрСведений.ИмяРегистра ГДЕ Регистратор = &Документ.

Можно ли получить ресурс без запроса, напрямую из формы списка регистра?

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

Что быстрее: запрос к срезу последних или ПолучитьПоследнее?

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

Как получить сразу несколько ресурсов одной записи?

Все перечисленные способы возвращают все ресурсы записи сразу: в запросе перечислите нужные поля через запятую, а ПолучитьПоследнее и Получить возвращают структуру со всеми ресурсами и измерениями — обращайтесь к ним по именам, например Значения.Цена и Значения.Валюта.