Почему не работает функция ЗНАЧЕНИЕ() в СКД внутри расширения и как это исправить

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

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

В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем механизмы работы расширений и рассмотрим несколько надежных способов решения проблемы, которые позволят вам успешно модифицировать типовые отчеты и печатные формы, такие как Т-6 в 1С:ЗУП.

Выясним причину проблемы

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

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

Существует мнение, что проблема была полностью исправлена в релизах платформы, начиная с 8.3.14, но практика показывает, что в определенных сценариях (особенно при сложных левых соединениях) ошибка продолжает проявляться даже на самых современных версиях 8.3.23 и выше.

Способ 1. Использование параметров СКД (Рекомендуемый метод)

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

Разберем по шагам, как это реализовать:

  1. Откроем наш запрос в конструкторе или текстовом редакторе СКД.
  2. Заменим проблемный участок кода. Вместо ЗНАЧЕНИЕ(Справочник.ВидыОтпусков.Основной) напишем &ПараметрВидОтпуска.
  3. Перейдем на закладку «Параметры» в схеме компоновки данных.
  4. Найдем наш новый параметр ПараметрВидОтпуска.
  5. В колонке «Тип» укажем конкретный тип ссылки, например, СправочникСсылка.ВидыОтпусков.
  6. В колонке «Выражение» пропишем вызов функции: ЗНАЧЕНИЕ(Справочник.ВидыОтпусков.Основной).

Важное примечание: Как ни странно, функция ЗНАЧЕНИЕ(), написанная в колонке «Выражение» на закладке параметров, работает гораздо стабильнее, чем внутри самого текста запроса. Это происходит потому, что вычисление выражения параметра происходит в другом контексте, где платформа лучше справляется с поиском предопределенных данных.

Пример обновленного запроса:


ВЫБРАТЬ
    ВидыОтпусков.Ссылка КАК Ссылка,
    ВидыОтпусков.Наименование КАК Наименование
ИЗ
    Справочник.ВидыОтпусков КАК ВидыОтпусков
ГДЕ
    ВидыОтпусков.Ссылка = &ПараметрВидОтпуска

Способ 2. Явное заимствование предопределенных элементов

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

Посмотрим на структуру дерева объектов в расширении. Если вы раскрываете ветку «Предопределенные» у заимствованного справочника и видите там пустоту, значит, платформа просто не знает, что такое "Основной" в контексте расширения.

Чтобы это исправить:

  1. В дереве основной конфигурации найдите нужный справочник.
  2. Раскройте список его предопределенных элементов.
  3. Нажмите правой кнопкой мыши на конкретный элемент (например, Основной) и выберите команду «Добавить в расширение».
  4. Убедитесь, что элемент появился в дереве расширения с тем же именем.

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

Способ 3. Программная установка параметров

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

Проанализируем ситуацию: печатная форма Т-6 вызывается из кода. Нам нужно найти место, где инициализируется компоновщик настроек СКД. Рассмотрим пример кода, который можно вставить в модуль объекта или модуль менеджера (в зависимости от того, где формируются данные):


// Получаем настройки компоновщика
Настройки = ЭтотОбъект.КомпоновщикНастроек.Настройки;

// Ищем нужный параметр по имени
ПараметрДанных = Настройки.ПараметрыДанных.Элементы.Найти("ВидОтпуска");

Если ПараметрДанных <> Неопределено Тогда
    ПараметрДанных.Значение = Справочники.ВидыОтпусков.Основной;
    ПараметрДанных.Использование = Истина;
КонецЕсли;

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

Способ 4. Работа с перечислениями и пустыми ссылками

Ситуация с перечислениями (Перечисление.Имя.Значение) в расширениях обычно обстоит проще, так как это статические данные. Однако, если вы столкнулись с ошибкой и здесь, убедитесь, что в расширение добавлены конкретные значения перечисления, а не только само перечисление как объект.

Что касается пустых ссылок, то вместо использования ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка), попробуйте более универсальный подход через параметры, как мы разбирали в первом способе. Это избавит вас от потенциальных ошибок при обновлении платформы или изменении структуры расширения.

Дополнительные рекомендации

Выясним еще несколько нюансов, которые могут влиять на работу СКД в расширении:

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

← На главную