Как правильно получить значение константы в параметре или выражении СКД?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе Системы компоновки данных (СКД) разработчики часто сталкиваются с необходимостью использовать значение какой-либо системной константы. Это может быть дата реорганизации компании, валюта регламентированного учета, признак ведения определенного учета и многое другое. Интуитивно разработчики пытаются получить это значение прямо в схеме компоновки — в поле выражения параметра или вычисляемого поля, используя конструкции вроде ЗНАЧЕНИЕ(Константа.ИмяКонстанты) или Константы.ИмяКонстанты.Получить(). Однако платформа выдает ошибку синтаксиса или неверных параметров еще на этапе компиляции или инициализации макета.

В этой статье мы подробно разберем, почему стандартные подходы вызывают ошибки, и рассмотрим три надежных, проверенных на практике способа получения констант в СКД.

---

Почему не работают простые варианты?

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

1. Ошибка при использовании функции ЗНАЧЕНИЕ()

Оператор ЗНАЧЕНИЕ() — это элемент языка запросов 1С, а не языка выражений СКД. Он предназначен исключительно для обращения к предопределенным элементам конфигурации напрямую в базе данных, минуя обращение к таблицам через параметры. С его помощью можно получить ссылки на предопределенные элементы справочников, планы видов характеристик, значения перечислений или пустые ссылки типов (например, ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)). Константы не являются предопределенными элементами какого-либо типа данных, у них нет уникальных идентификаторов в метаданных в том смысле, в котором они есть у справочников. Именно поэтому синтаксис ЗНАЧЕНИЕ(Константа.ИмяКонстанты) принципиально не поддерживается платформой.

2. Ошибка при использовании конструкции Константы.ИмяКонстанты.Получить() в выражениях СКД

Язык выражений СКД выполняется в изолированном контексте. В целях безопасности, производительности и кроссплатформенности разработчики платформы ограничили прямой доступ из выражений СКД к глобальным контекстным коллекциям сервера (таким как Константы, Справочники, Документы и т.д.). СКД просто «не знает» о существовании менеджера констант во время вычисления выражений параметров. В старых версиях платформы или при работе в режиме толстого клиента иногда происходили утечки контекста (когда некоторые функции встроенного языка случайно срабатывали), но в современных управляемых формах и на тонком/веб-клиенте это гарантированно приведет к ошибке инициализации компоновщика.

Теперь, когда причины понятны, проанализируем рабочие решения этой задачи.

---

Способ 1. Программная установка параметра в модуле отчета (Рекомендуемый метод)

Если ваш отчет имеет собственный модуль объекта (например, это сложный отчет конфигурации или внешняя обработка/отчет), самым гибким и правильным решением будет получить значение константы на стороне встроенного языка 1С и передать его в параметры компоновщика перед выводом отчета.

Для этого мы переопределим стандартное событие компоновки результата в модуле объекта отчета. Шаг за шагом разберем этот процесс.

Откроем модуль объекта отчета и создадим процедуру-обработчик ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем значение нашей константы на сервере
    ЗначениеКонстанты = Константы.ДатаРеорганизации.Получить();
    
    // Устанавливаем значение в основные настройки схемы компоновки
    ПараметрыДанных = КомпоновщикНастроек.Настройки.ПараметрыДанных;
    Параметр = ПараметрыДанных.Элементы.Найти("ДатаРеорганизации");
    
    Если Параметр <> Неопределено Тогда
        Параметр.Значение = ЗначениеКонстанты;
        Параметр.Использование = Истина;
    КонецЕсли;
    
КонецПроцедуры

Важное предупреждение: В управляемом приложении параметры отчета часто выводятся в так называемые «Пользовательские настройки» (чтобы пользователь мог видеть их прямо на форме отчета). Если параметр выведен туда, то платформа при формировании отчета приоритетно возьмет значение именно из пользовательских настроек, проигнорировав код выше. Чтобы избежать этой проблемы, нам необходимо принудительно обойти пользовательские настройки и установить значение константы и туда тоже.

Модернизируем наш код для гарантированной работы в управляемых формах:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    ЗначениеКонстанты = Константы.ДатаРеорганизации.Получить();
    ИмяПараметра = "ДатаРеорганизации";
    
    // 1. Установка в основных настройках компоновщика
    ПараметрыДанных = КомпоновщикНастроек.Настройки.ПараметрыДанных;
    Параметр = ПараметрыДанных.Элементы.Найти(ИмяПараметра);
    Если Параметр <> Неопределено Тогда
        Параметр.Значение = ЗначениеКонстанты;
        Параметр.Использование = Истина;
    КонецЕсли;
    
    // 2. Установка в пользовательских настройках (если параметр выведен на форму)
    Для Каждого Элемент Из КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
        Если ТипЗнч(Элемент) = Тип("ЗначениеПараметраКомпоновкиДанных") 
            И Строка(Элемент.Параметр) = ИмяПараметра Тогда
            Элемент.Значение = ЗначениеКонстанты;
            Элемент.Использование = Истина;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Этот метод абсолютно надежен, работает на любых клиентах и не зависит от обновлений платформы. Для настройки взаимодействия элементов формы с параметрами компоновщика можно использовать решение для стыковки элементов управляемой формы и пользовательских настроек СКД.

---

Способ 2. Добавление таблицы констант в запрос СКД (Без написания кода)

Бывают ситуации, когда отчет должен распространяться в виде чистого XML-файла схемы компоновки данных, либо у нас нет возможности писать программный код в модуле объекта (например, при использовании упрощенных механизмов добавления отчетов в некоторых подсистемах). В таком случае мы можем извлечь константу прямо в запросе СКД.

Давайте посмотрим на два варианта работы с таблицами констант в языке запросов:

  1. Через общую таблицу Константы: Эта виртуальная таблица содержит ровно одну строку, в которой каждая колонка соответствует конкретной константе конфигурации.
  2. Через таблицу конкретной константы Константа.ИмяКонстанты: Эта таблица также содержит одну строку, но только с одной колонкой под названием Значение.

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

Пример запроса в СКД:


ВЫБРАТЬ
    Продажи.Номенклатура КАК Номенклатура,
    Продажи.Количество КАК Количество,
    ТаблицаКонстант.ДатаРеорганизации КАК ДатаРеорганизации
ИЗ
    РегистрНакопления.Продажи КАК Продажи
    // Кросс-соединение с таблицей констант (всегда возвращает 1 строку)
    ЛЕВОЕ СОЕДИНЕНИЕ Константы КАК ТаблицаКонстант ПО ИСТИНА
ГДЕ
    Продажи.Период >= ТаблицаКонстант.ДатаРеорганизации

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

---

Способ 3. Получение через экспортную функцию общего модуля

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

Разберем этот метод по шагам:

Шаг 1. Создание или выбор общего модуля

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

Шаг 2. Написание экспортной функции

Внутри этого модуля напишем простую экспортную функцию, возвращающую значение нужной константы:


Функция ПолучитьДатуРеорганизации() Экспорт
    Возврат Константы.ДатаРеорганизации.Получить();
КонецФункции

Шаг 3. Указание функции в схеме СКД

Перейдем в схему компоновки данных на вкладку Параметры. Для нашего параметра (например, ДатаРеорганизации) в колонке Выражение пропишем вызов нашей функции:

РаботаСКонстантамиВызовСервера.ПолучитьДатуРеорганизации()

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


ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных, , ДанныеРасшифровки, Истина);

---

Резюме и рекомендации

Мы проанализировали три отличных способа решения проблемы. Выбор конкретного метода зависит от архитектуры вашего решения:

← На главную