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