При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда при попытке построить запрос к подчиненному справочнику (например, к справочнику ХарактеристикиНоменклатуры) в списке доступных полей Конструктора запросов отсутствует стандартный реквизит Владелец. Это вызывает недоумение, ведь на уровне логики базы данных у подчиненного справочника этот реквизит обязан присутствовать всегда.
В этой статье мы подробно разберем, почему возникает эта проблема, рассмотрим внутренние механизмы платформы 1С при работе с расширениями конфигурации, а также изучим несколько способов решения — от правильной настройки метаданных до быстрых практических «лайфхаков» для разработчика.
Выясним первопричину такого поведения платформы. Описанная проблема практически всегда связана с использованием расширений конфигурации. Когда мы заимствуем типовой справочник из основной конфигурации в расширение, платформа переносит туда лишь базовое описание объекта метаданных. Это делается для оптимизации и минимизации объема расширения.
По умолчанию связи подчинения между объектами в расширении не активны, пока они явно туда не перенесены. Поскольку в контексте расширения платформа «не видит» связей подчинения справочника (например, связи ХарактеристикиНоменклатуры с его владельцем — справочником Номенклатура), визуальный Конструктор запросов скрывает стандартный реквизит Владелец. На самом деле в базе данных этот реквизит никуда не исчезает, база данных о нем знает, но визуальный интерфейс Конструктора в конфигураторе пытается уберечь разработчика от использования связей, которых «нет» в текущем контексте расширения.
Аналогичным образом платформа ведет себя и с иерархическими справочниками. Если вы заимствуете иерархический справочник в расширение, но не укажете свойства иерархии, Конструктор запросов скроет от вас стандартные реквизиты Родитель и ЭтоГруппа.
Ниже мы разберем по шагам, как решить эту проблему различными путями.
Рассмотрим самый надежный и правильный с точки зрения архитектуры 1С метод исправления проблемы. Нам необходимо явно указать платформе в расширении, что у заимствованного справочника существуют связи подчинения.
Выполним следующие шаги:
ХарактеристикиНоменклатуры) и откройте его свойства (клавиша Alt + Enter).Как только свойство Владельцы будет добавлено в контекст расширения, платформа сразу же обновит внутреннее описание метаданных. Если вы теперь откроете Конструктор запросов внутри расширения, стандартный реквизит Владелец чудесным образом появится в списке доступных полей, и вы сможете визуально настраивать связи, отборы и группировки.
Полезный совет: Точно так же поступайте и с иерархическими справочниками. Чтобы вернуть в Конструктор запросов поля Родитель и ЭтоГруппа, добавьте в расширение свойство справочника «Иерархический» и сделайте его контролируемым.
Проанализируем ситуацию, когда вам не хочется или нельзя менять структуру расширения (например, чтобы не усложнять поддержку и обновление конфигурации лишним контролем свойств). Поскольку ограничение на отображение поля Владелец накладывает исключительно визуальный Конструктор запросов, в коде платформы это поле доступно всегда.
Мы можем просто написать текст условия в запросе вручную. При запуске программы в режиме «1С:Предприятие» этот запрос выполнится абсолютно корректно.
Посмотрим на пример кода:
// Пример ручного написания условия по владельцу в коде 1С
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Характеристики.Ссылка КАК Ссылка,
| Характеристики.Наименование КАК Наименование,
| Характеристики.Владелец КАК Владелец
|ИЗ
| Справочник.ХарактеристикиНоменклатуры КАК Характеристики
|ГДЕ
| Характеристики.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец", ВыбраннаяНоменклатура);
РезультатЗапроса = Запрос.Выполнить();
Если вы попробуете открыть этот запрос через Конструктор запросов, конфигуратор может выдать предупреждение или отобразить поле Владелец серым цветом (или со знаком вопроса), однако компилятор 1С пропустит данный код, и в режиме пользователя все отработает без ошибок.
Еще один удобный практический прием — это написание и отладка сложных запросов в режиме пользователя с помощью внешней обработки «Консоль запросов».
Выясним, почему этот метод работает:
В режиме «1С:Предприятие» база данных работает с полностью объединенной и скомпилированной структурой метаданных (основная конфигурация плюс все примененные и активные расширения). На этом этапе никаких ограничений видимости стандартных реквизитов уже нет.
Вы можете запустить консоль запросов прямо в режиме предприятия, визуально настроить любой сложный запрос со всеми отборами по реквизиту Владелец, отладить его на реальных данных, а затем просто скопировать готовый SQL-подобный текст запроса и вставить его в конфигуратор в код вашего модуля.
Иногда запрос настолько сложен, содержит множество временных таблиц, вложенных запросов и объединений, что писать его вручную или постоянно отлаживать без использования Конструктора запросов становится крайне тяжело. В таких случаях опытные разработчики используют изящный прием динамической автозамены.
Разберем этот метод по шагам:
Владелец выберите любое другое доступное поле ссылочного типа, например, поле Ссылка.СсылкаВместоВладельца.Выполнить() сделайте замену текста запроса с помощью стандартной функции СтрЗаменить().Посмотрим на пример реализации данного лайфхака:
// Создаем запрос с использованием временной заглушки для конструктора
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Характеристики.Ссылка КАК Ссылка,
| Характеристики.Ссылка КАК СсылкаВместоВладельца
|ИЗ
| Справочник.ХарактеристикиНоменклатуры КАК Характеристики
|ГДЕ
| Характеристики.Ссылка = &Владелец";
// Производим автозамену заглушки на реальный реквизит Владелец
Запрос.Текст = СтрЗаменить(Запрос.Текст, "Характеристики.Ссылка КАК СсылкаВместоВладельца", "Характеристики.Владелец КАК Владелец");
Запрос.Текст = СтрЗаменить(Запрос.Текст, "Характеристики.Ссылка = &Владелец", "Характеристики.Владелец = &Владелец");
// Устанавливаем параметры и выполняем запрос
Запрос.УстановитьПараметр("Владелец", ПараметрВладелец);
Результат = Запрос.Выполнить();
Используя этот метод, вы сохраняете возможность в любой момент открыть запрос в Конструкторе, отредактировать сложные связи или группировки, не боясь, что Конструктор «сломает» ваш написанный вручную код отбора.
Мы детально проанализировали проблему отсутствия реквизита Владелец в Конструкторе запросов 1С 8.3 при разработке внутри расширений. Рекомендуемым и наиболее профессиональным решением является добавление свойства «Владельцы» в заимствованный объект расширения с включением контроля свойств (Способ 1). В тех же случаях, когда требуется быстрое решение «здесь и сейчас» без изменения структуры метаданных расширения, отлично подойдут методы ручного редактирования или автозамены текста запроса.