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

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

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

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

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

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

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

Что нужно знать о регистре перед чтением

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

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

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

Получить значение из непериодического регистра

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

Отбор = Новый Структура;

Отбор.Вставить("Номенклатура", ТекущаяНоменклатура);

Отбор.Вставить("ТипЦен", ТипЦенЗакупка);

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

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

Цена = Значения.Цена;

Иначе

Цена = 0; // записи нет

КонецЕсли;

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

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

Получить актуальное значение из периодического регистра

Периодический регистр хранит историю изменений, поэтому просто «получить запись» недостаточно — нужно указать, на какую дату. Для этого служат методы ПолучитьПоследнее (значение на дату или самое позднее) и ПолучитьПервое (самое раннее значение).

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

// Курс на дату документа:

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

Если Результат.Количество() > 0 Тогда

Курс = Результат.Курс;

КонецЕсли;

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

Обратите внимание на границы периодичности. Если регистр периодичен «в пределах дня», а вы передаете дату со временем 10:00, запись, сделанная в 15:00 того же дня, в срез не попадет — платформа сравнивает моменты точно. При сомнениях передавайте КонецДня(Дата).

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

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

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

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

"ВЫБРАТЬ

| Курсы.Валюта,

| Курсы.Курс

|ИЗ

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

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

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

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

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

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

Чтение набора записей и построение отбора

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

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

Набор.Отбор.Владелец.Установить(ТекущийТовар);

Набор.Прочитать();

Для Каждого Запись Из Набор Цикл

Сообщить(Запись.Штрихкод);

КонецЦикла;

Установка отбора через Набор.Отбор.ИмяИзмерения.Установить(Значение) обязательна перед Прочитать() — без отбора в память загрузится вся таблица регистра, что на больших объемах может привести к нехватке памяти и аварийному завершению сеанса.

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

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

Простейшая проверка — открыть регистр в режиме 1С:Предприятие через меню «Операции» → «Регистры сведений», установить отбор по тем же измерениям и сравнить значения ресурсов с тем, что вернул код. Убедитесь, что смотрите ту же базу и тот же период.

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

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

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

Структура результата
Норма

Количество() > 0, нужное поле присутствует

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

Пустая структура — записи по отбору нет

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

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

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

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

Скорость выполнения
Норма

Один запрос обрабатывает весь список ключей

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

Обращение к базе на каждой итерации цикла

Выбор метода под задачу

Единого «правильного» способа нет — есть подходящий под конкретную ситуацию. Ориентируйтесь на количество читаемых записей, периодичность регистра и контекст исполнения (клиент, сервер, фоновое задание).

СитуацияРекомендуемый способОграничение
Одно значение, непериодический регистрПолучить(Отбор)Только независимые регистры
Одно значение на датуПолучитьПоследнее(Дата, Отбор)Не использовать в цикле
Значения для списка ключейЗапрос к СрезПоследнихТолько периодические регистры
Регистр подчинен регистраторуЗапрос с отбором по РегистраторМетоды менеджера недоступны
Чтение с последующим изменениемНабор записей с отборомОбязательно задать отбор до Прочитать()
Маршрут решения

Как выбрать действие

Нужна одна запись и регистр непериодическийИспользуйте Получить с отбором по всем измерениям
Нужно значение на конкретную датуИспользуйте ПолучитьПоследнее с явной датой и проверкой результата
Нужно обработать много ключей или построить отчетПишите запрос к СрезПоследних с отбором в параметрах виртуальной таблицы
Регистр подчинен регистраторуЧитайте запросом или набором записей с отбором по регистратору

В клиент-серверном варианте все перечисленные методы выполняйте на сервере — в серверных процедурах общих модулей или модулей объектов. Вызов методов регистра с тонкого клиента без серверного контекста невозможен, а передача больших выборок на клиента замедляет работу.

Итог

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

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

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

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

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

Можно ли получить значение из регистра сведений на толстом клиенте обычного приложения?

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

Чем СрезПоследних отличается от обычного запроса с максимумом по периоду?

Виртуальная таблица строится оптимизированным механизмом платформы и корректно обрабатывает все комбинации измерений, включая те, по которым записей нет. Ручная группировка с МАКСИМУМ(Период) требует дополнительного соединения и чаще дает ошибки на граничных случаях, например при нескольких записях с одинаковым периодом.

Как получить значение ресурса, не зная заранее его имени?

Используйте запрос к физической таблице регистра и обход колонок результата через Результат.Колонки — там будут все измерения, ресурсы и реквизиты. Структура, возвращаемая методом Получить, также позволяет перебрать поля циклом, но только для одной записи.

Почему запрос к СрезПоследних работает медленно?

Основные причины: отбор задан в секции ГДЕ вместо параметров виртуальной таблицы, не передан период (срез строится на максимальную дату по всей истории) и отсутствие отбора по измерениям при большом объеме регистра. Перенесите условия в параметры виртуальной таблицы и ограничьте список ключей.

Можно ли читать регистр сведений через COM-соединение из другой базы?

Да, через COM-объект V83.COMConnector доступны те же методы менеджера регистров и запросы, но типы значений измерений нужно передавать как COM-объекты той базы, а не как ссылки текущей. Для регулярного обмена предпочтительнее HTTP-сервисы или планы обмена — COM-соединение держит сеанс и чувствительно к разрывам.