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