Рассмотрим частую и весьма интересную задачу, с которой сталкиваются разработчики при динамическом формировании запросов в 1С. Довольно часто возникает потребность передать внешнюю таблицу значений (ТЗ) в качестве параметра в запрос, используя объект СхемаЗапроса. Если в обычном тексте запроса мы просто пишем конструкцию вида ВЫБРАТЬ * ИЗ &тз, то при конструировании схемы программным путем прямолинейные подходы часто приводят к ошибке "не найдена таблица".
Давайте подробно разберем, как правильно реализовать эту задачу, проанализируем частые ошибки и посмотрим на работающие примеры кода. Мы изучим два основных способа: использование шаблона текста запроса и прямое манипулирование объектной моделью схемы.
Это наиболее простой и быстрый способ, если вам нужно быстро инициализировать схему с нужной структурой. Суть заключается в том, чтобы написать базовый "каркас" запроса в виде обычной строки, передать его в схему, а затем уже программно дорабатывать отборы, группировки и связи.
Разберем по шагам, как это работает:
СхемаЗапроса.УстановитьТекстЗапроса(), передавая туда наш шаблон.Посмотрим на практический пример кода:
ТекстШаблон = "ВЫБРАТЬ
| Таб.Поле1 КАК Поле1,
| Таб.Поле2 КАК Поле2
|ПОМЕСТИТЬ ДанныеТаблицы
|ИЗ
| &Таблица КАК Таб";
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(ТекстШаблон);
// Далее можно модифицировать СхемуЗапроса программно
Платформа автоматически распарсит этот текст, создаст нужные источники, колонки и поместит их в коллекции схемы. Это избавляет от необходимости вручную прописывать каждый шаг инициализации.
Если архитектура решения требует полностью программного конструирования схемы без использования текста, мы можем добавить параметр в качестве источника напрямую в объектную модель. Однако здесь кроется главный нюанс, из-за которого разработчики получают ошибки.
Чтобы платформа смогла построить схему и понять, какие поля можно выбирать, группировать или соединять, ей необходимо знать структуру передаваемой таблицы. Для этого в метод Добавить() коллекции Источники нужно передать специальный аргумент — образец структуры данных.
Рассмотрим синтаксис добавления источника:
Оператор.Источники.Добавить("&ИмяПараметра", "Псевдоним", ОбразецСтруктуры);
В качестве образца структуры мы можем передать:
Если мы используем таблицу значений в качестве образца, крайне важно задавать типы её колонок с помощью объекта ОписаниеТипов. Если передать нетипизированную ТЗ, платформа не сможет определить типы полей, что в дальнейшем приведет к ошибкам при попытке соединить эту таблицу с другими сущностями базы данных.
Проанализируем правильный пример кода для этого способа:
Схема = Новый СхемаЗапроса;
Пакет = Схема.ПакетЗапросов[0];
Оператор = Пакет.Операторы[0];
// 1. Создаем образец таблицы и строго типизируем колонки
ОбразецТЗ = Новый ТаблицаЗначений;
ОбразецТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ОбразецТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
// 2. Добавляем параметр-таблицу в источники с передачей образца
Источник = Оператор.Источники.Добавить("&тз", "Таб", ОбразецТЗ);
// 3. Выбираем все поля из переданной таблицы
Оператор.ВыбираемыеПоля.Добавить("Таб.*");
Среди разработчиков иногда бытует мнение, что перед использованием таблицы её нужно принудительно добавить в коллекцию ДоступныеТаблицы. Развеем этот миф.
Коллекция ДоступныеТаблицы пакета схемы заполняется платформой автоматически. Как только вы программно добавили источник (например, через метод Источники.Добавить() с корректным образцом структуры), платформа сама анализирует метаданные и сразу же делает эти поля доступными для конструирования. Вручную добавлять элементы в ДоступныеТаблицы не требуется.
Также стоит отметить удобство выборки полей. Если в запрос передается образец структуры, нет необходимости циклом перебирать колонки и добавлять каждое поле по отдельности. Как видно из примера выше, достаточно добавить в ВыбираемыеПоля конструкцию с символом звездочки ("Таб.*"), и платформа автоматически развернет её в полный список колонок источника.