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