БСП в 1С

1С БСП: получить реквизит объекта одним запросом

Коротко

Чтобы в 1С через БСП получить реквизит, вызовите ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Комментарий") — вернётся само значение. Для нескольких реквизитов сразу — ЗначенияРеквизитовОбъекта(Ссылка, "Код, Наименование, Родитель"), результат придёт структурой за один запрос к базе.

Если ссылок много, не гоняйте функцию в цикле: ЗначенияРеквизитовОбъектов(Ссылки, Реквизиты) читает весь массив одним пакетом и возвращает соответствие «ссылка → структура значений». Все четыре функции живут в общем модуле ОбщегоНазначения — он серверный.

В каком модуле БСП лежат функции чтения реквизитов

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

  • с клиента вызвать напрямую нельзя — код помещают в серверную процедуру (&НаСервереБезКонтекста) или в другой серверный модуль;
  • права проверяются от текущего пользователя, поэтому для чтения «в обход» ролей нужен явный УстановитьПривилегированныйРежим(Истина) перед вызовом;
  • в клиент-серверном коде общего назначения парного клиентского аналога у этих функций нет — ОбщегоНазначенияКлиентСервер к базе не обращается.

Полный состав функций чтения (имя — строка в ОбщегоНазначения/Ext/Module.bsl типовой поставки): ЗначенияРеквизитовОбъекта — 141, ЗначениеРеквизитаОбъекта — 413, ЗначенияРеквизитовОбъектов — 459, ЗначениеРеквизитаОбъектов — 682. Номера строк плавают от версии к версии, а вот имена и порядок параметров стабильны много лет.

ЗначениеРеквизитаОбъекта: получить один реквизит

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

// Серверный контекст
ЦенаВключаетНДС = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ДокументСсылка, "ЦенаВключаетНДС");

Если ЦенаВключаетНДС = Истина Тогда
    // ...
КонецЕсли;

// Реквизит через точку тоже допустим
ИННКонтрагента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ДоговорСсылка, "Владелец.ИНН");
ОбщегоНазначения.ЗначениеРеквизитаОбъекта
СсылкаЛюбаяСсылка или Строка — полное имя предопределённого элемента
ИмяРеквизитаимя реквизита; допускается путь через точку
ВыбратьРазрешенныеБулево, по умолчанию Ложь
КодЯзыкадля мультиязычных реквизитов
Произвольный (значение реквизита)

Внутри это обёртка: функция вызывает ЗначенияРеквизитовОбъекта с одним именем и достаёт из полученной структуры единственный ключ. Отсюда два нюанса. Пустое ИмяРеквизита — не «вернуть всё», а исключение категории «ошибка конфигурации» с текстом «Имя реквизита должно быть заполнено». А путь через точку внутри превращается в ключ структуры без точек: "Владелец.ИНН" читается как поле ВладелецИНН, но наружу вы всё равно получаете просто значение.

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

ЗначенияРеквизитовОбъекта: несколько реквизитов одним запросом

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

Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(
    НоменклатураСсылка, "Код, Наименование, БазоваяЕдиницаИзмерения");

Сообщить(Реквизиты.Код + " / " + Реквизиты.Наименование);

// Псевдонимы: ключ — как назвать поле в результате, значение — реальный путь
Поля = Новый Структура;
Поля.Вставить("Номер");                       // значение не задано — имя берётся из ключа
Поля.Вставить("ИННКонтрагента", "Контрагент.ИНН");

Шапка = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ДокументСсылка, Поля);
Сообщить(Шапка.ИННКонтрагента);
ОбщегоНазначения.ЗначенияРеквизитовОбъекта
СсылкаЛюбаяСсылка или Строка — полное имя предопределённого элемента
РеквизитыСтрока через запятую, Массив, Структура или их фиксированные варианты
ВыбратьРазрешенныеБулево, по умолчанию Ложь
КодЯзыкадля мультиязычных реквизитов
Структура (имена реквизитов и их значения)

Формат второго параметра выбирается по задаче:

  • Строка"Код, Наименование"; пробелы обрезаются, ключи структуры совпадают с именами реквизитов. Пустая строка вернёт пустую структуру, а не исключение.
  • Массив (или фиксированный массив) — удобно, когда список полей собирается в коде; для пути через точку ключом станет имя без точек: "Владелец.Код"ВладелецКод.
  • Структура (или фиксированная) — ключ задаёт псевдоним в результате, значение — фактическое имя поля. Если значение не заполнено, имя берётся из ключа. Для полей через точку параметр КодЯзыка не применяется.
В ИИ Консоли кода: попросите агента прочитать нужные реквизиты у конкретной ссылки — он подставит корректные имена полей из метаданных вашей конфигурации и сразу выполнит код на базе. Это быстрее, чем ловить «Поле объекта не существует» из-за реквизита, который в этой конфигурации называется иначе.

ЗначенияРеквизитовОбъектов: пакетное чтение по массиву ссылок

Главная функция для списков. Принимает массив ссылок и возвращает соответствие, где ключ — ссылка, а значение — структура реквизитов этого объекта:

// Ссылки собраны заранее: выборка, таблица значений, результат запроса
ЗначенияРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(
    МассивДокументов, "Дата, Контрагент, СуммаДокумента");

Для Каждого Документ Из МассивДокументов Цикл
    Данные = ЗначенияРеквизитов[Документ];
    Если Данные = Неопределено Тогда
        Продолжить; // объект не найден или отсечён по правам
    КонецЕсли;
    Итог = Итог + Данные.СуммаДокумента;
КонецЦикла;
ОбщегоНазначения.ЗначенияРеквизитовОбъектов
СсылкиМассив или ФиксированныйМассив из ЛюбаяСсылка
РеквизитыСтрока через запятую или массив имён; путь через точку не поддерживается
ВыбратьРазрешенныеБулево, по умолчанию Ложь
КодЯзыкадля мультиязычных реквизитов
Соответствие: ссылка → Структура значений

Что важно знать о поведении:

  • пустой массив ссылок — это пустое соответствие, без обращения к базе и без исключения;
  • пустой параметр Реквизиты — исключение «Поле объекта должно быть указано»;
  • точка в имени реквизита запрещена явной проверкой: «Обращение через точку не поддерживается». Нужен реквизит связанного объекта — читайте его вторым вызовом по массиву уже полученных ссылок;
  • ссылки разных типов допустимы: библиотека группирует их по типу и объединяет запросы через ОБЪЕДИНИТЬ ВСЕ. Но перечисленные реквизиты должны существовать у каждого типа из массива, иначе будет исключение о несуществующем поле;
  • объектов, которых нет в базе (битые ссылки), в результате просто не будет — обращение по ключу вернёт Неопределено.

Если нужен ровно один реквизит по массиву ссылок, есть более короткий вариант — соответствие «ссылка → значение» без промежуточных структур:

Наименования = ОбщегоНазначения.ЗначениеРеквизитаОбъектов(МассивСсылок, "Наименование");

Для Каждого Элемент Из Наименования Цикл
    Сообщить(Строка(Элемент.Ключ) + " = " + Элемент.Значение);
КонецЦикла;

// Одну ссылку в массив удобно завернуть готовым хелпером
Одна = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(СсылкаНаЭлемент);
ОбщегоНазначения.ЗначениеРеквизитаОбъектов
МассивСсылокМассив или ФиксированныйМассив из ЛюбаяСсылка
ИмяРеквизитаодно имя реквизита, например "Код"
ВыбратьРазрешенныеБулево, по умолчанию Ложь
КодЯзыкадля мультиязычных реквизитов
Соответствие: ссылка → значение реквизита

Почему это лучше, чем Ссылка.Реквизит в цикле

Обращение через точку от ссылки — это ленивое чтение: платформа при первом же обращении выполняет отдельный запрос к базе и подтягивает объект. В цикле по 500 ссылкам вы получаете 500 запросов вместо одного — классическая проблема N+1:

// Плохо: запрос к базе на каждой итерации
Для Каждого Документ Из МассивДокументов Цикл
    Итог = Итог + Документ.СуммаДокумента;   // чтение объекта целиком
КонецЦикла;

// Хорошо: один пакет запросов на весь массив
Значения = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(МассивДокументов, "СуммаДокумента");
Для Каждого Документ Из МассивДокументов Цикл
    Данные = Значения[Документ];
    Итог = Итог + ?(Данные = Неопределено, 0, Данные.СуммаДокумента);
КонецЦикла;

Разница не только в числе запросов. Через точку читается весь объект со всеми реквизитами и табличными частями, а функция БСП выбирает ровно перечисленные поля. На тяжёлых документах с большими табличными частями это отличается на порядки по объёму передаваемых данных.

Отдельный неочевидный эффект: обращение через точку от ссылки, у которой нет прав на чтение объекта, даёт ошибку прав доступа прямо в середине цикла. Функции БСП дают явный контроль над этим поведением через ВыбратьРазрешенные.

Параметр ВыбратьРазрешенные и права доступа

Третий параметр у всех четырёх функций — ВыбратьРазрешенные, по умолчанию Ложь. Он управляет ключевым словом РАЗРЕШЕННЫЕ в запросе, которым читаются реквизиты:

  • Ложь — строгий режим. Нет прав на таблицу или на любой из перечисленных реквизитов — будет исключение. Подходит, когда отсутствие прав это ошибка сценария;
  • Истина — мягкий режим. Для одиночной ссылки RLS-ограничение даёт реквизиты со значением Неопределено; для массива ссылок недоступный объект просто исключается из результата. Но при полном отсутствии прав на таблицу исключение возникнет всё равно.

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

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

УстановитьПривилегированныйРежим(Истина);
Ответственный = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЗаказСсылка, "Ответственный");
УстановитьПривилегированныйРежим(Ложь);
В ИИ Консоли кода: опишите задачу словами — «посчитай сумму по массиву заказов, читая реквизиты через БСП» — и агент соберёт вариант без запросов в цикле, выполнит его на вашей базе и покажет результат. Заодно видно, какие объекты отсеклись по правам при ВыбратьРазрешенные.

Пустые ссылки, битые ссылки и предопределённые элементы

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

  • Пустая ссылка в ЗначенияРеквизитовОбъекта — вернётся структура с теми же ключами, но все значения будут Неопределено. В ЗначениеРеквизитаОбъекта соответственно Неопределено;
  • Битая ссылка (объект удалён из базы) даёт тот же результат: все реквизиты Неопределено, исключения не будет;
  • Первый параметр строкой трактуется как полное имя предопределённого элемента — "Справочник.ВидыНоменклатуры.Услуга". Библиотека сама вычислит ссылку. Если предопределённый описан в метаданных, но не создан в информационной базе, вернётся структура с Неопределено, а права на таблицу при этом проверяются явно.
Ставка = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(
    "Справочник.СтавкиНДС.НДС20", "Ставка");

// Ссылка может быть незаполненной — проверка не нужна, вернётся Неопределено
Валюта = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ДоговорСсылка, "ВалютаВзаиморасчетов");
Если Не ЗначениеЗаполнено(Валюта) Тогда
    Валюта = ВалютаРегламентированногоУчета;
КонецЕсли;

Частые ошибки при чтении реквизитов через БСП

  • Вызов функции в цикле по ссылкам. ЗначениеРеквизитаОбъекта внутри Для Каждого — это тот же N+1, только с лишним слоем. Для списков есть ЗначенияРеквизитовОбъектов и ЗначениеРеквизитаОбъектов.
  • Точка в реквизитах пакетной функции. ЗначенияРеквизитовОбъектов явно запрещает "Контрагент.ИНН" и выбрасывает исключение. Путь через точку допустим только в функциях для одиночной ссылки.
  • Массив ссылок разных типов с «чужими» реквизитами. Поля объединяются в один запрос, поэтому реквизит должен существовать у каждого типа. Смешанный массив документов безопасно читать только по общим полям вроде Дата и Номер.
  • Результат пакетной функции берут без проверки на Неопределено. Битые ссылки и объекты, отсечённые правами при ВыбратьРазрешенные = Истина, в соответствие не попадают.
  • Попытка вызвать с клиента. Модуль ОбщегоНазначения серверный и без флага «Вызов сервера»: код нужно переносить в &НаСервереБезКонтекста или в свой серверный модуль.
  • Ожидание, что ВыбратьРазрешенные снимет все ошибки прав. Он влияет на записи и RLS, но при отсутствии прав на саму таблицу исключение возникнет в любом режиме. Обход прав — только привилегированный режим.
  • Чтение реквизитов у уже загруженного объекта. Если ДокументОбъект получен через ПолучитьОбъект(), реквизиты берут прямо из него: лишний запрос к базе только замедлит код и вернёт данные, записанные в базе, а не текущие в памяти.

Частые вопросы про получение реквизитов в БСП

В каком модуле БСП лежит функция ЗначениеРеквизитаОбъекта?

В общем модуле ОбщегоНазначения — он серверный, без флага «Вызов сервера» и без привилегированного режима. Вызов возможен только из серверного контекста; там же объявлены ЗначенияРеквизитовОбъекта, ЗначенияРеквизитовОбъектов и ЗначениеРеквизитаОбъектов.

Чем ЗначенияРеквизитовОбъекта отличается от ЗначенияРеквизитовОбъектов?

Первая работает с одной ссылкой и возвращает Структуру значений, допуская путь через точку. Вторая принимает массив ссылок, возвращает Соответствие «ссылка → структура» и читает все объекты одним пакетом запросов, но обращение через точку в ней запрещено.

Что вернёт ЗначениеРеквизитаОбъекта для пустой ссылки?

Неопределено, без исключения. Так же обрабатывается битая ссылка на удалённый объект. Исключение возникнет в другом случае — если не заполнено имя реквизита или такого поля нет в таблице.

Тарифы

ИИ Консоль кода 1С

Лайт

Бесплатно
≈ 1,5 млн токенов

Для ознакомления с возможностями

  • Все функции бесплатно на 2 дня +2 дня за подписку на Telegram или Max
  • Полный набор инструментов без урезаний
  • Без ввода карты
Начать бесплатно

Старт

1990 руб. в месяц
≈ 10 млн токенов

Для индивидуального использования

Выбрать тариф

Продвинутый

Популярный выбор
3990 руб. в месяц
≈ 25 млн токенов

Для интенсивного использования или команд

  • До 15 конфигураций
  • Встроенный агент запросов 1С
  • Свои подписки Codex, Claude и любые OpenAI-совместимые
  • Внешние обработки без Конфигуратора
  • Приоритетная техническая поддержка
Выбрать тариф