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