Как обратиться запросом к таблице значений или реквизиту формы в 1С?

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

При работе с запросами в 1С разработчики часто сталкиваются с необходимости обработать данные, которые уже находятся в оперативной памяти — например, в объекте ТаблицаЗначений или в реквизите управляемой формы. Однако попытка напрямую передать реквизит формы в параметр запроса приводит к ошибке выполнения.

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

Выясним причину ошибки «Неверные параметры»

Разберем типичную ситуацию. Допустим, на форме создан реквизит типа «Таблица значений». В коде управляемой формы этот объект имеет тип ДанныеФормыКоллекция (или ДанныеФормыДерево). Если попытаться передать его напрямую в параметр запроса, платформа выдаст ошибку:

{(7, 2)}: Неверные параметры "Данные"
<<?>>&Данные КАК Данные

Проанализируем ограничение платформы: механизм запросов 1С не умеет работать с объектами данных формы. Для построения источника во временной таблице запрос принимает исключительно объекты типов ТаблицаЗначений или ДеревоЗначений.

Разберем решение: выгрузка данных формы в ТаблицуЗначений

Чтобы запрос успешно принял таблицу, содержащуюся в реквизите формы, ее необходимо предварительно преобразовать в объект ТаблицаЗначений. Сделать это на сервере можно несколькими способами.

  1. Метод Выгрузить(): вызвав этот метод у коллекции формы, мы получаем чистую таблицу значений в оперативной памяти.
  2. Метод ЗначениеВРеквизитФормы() / РеквизитФормыВЗначение(): стандартная функция контекста формы, которая преобразует реквизит формы в прикладной объект.

Рассмотрим подробнее рабочий пример с использованием метода Выгрузить() и пакета запросов.


// Переводим данные формы в ТаблицуЗначений
ТЗДанные = ТаблаНаФорме.Выгрузить();

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВТ_Данные.Реквизит1 КАК Реквизит1,
    |	ВТ_Данные.Реквизит2 КАК Реквизит2
    |ПОМЕСТИТЬ ВТ_ИсходнаяТаблица
    |ИЗ
    |	&ВТ_Данные КАК ВТ_Данные
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	ВТ_ИсходнаяТаблица.Реквизит1 КАК Реквизит1,
    |	ВТ_ИсходнаяТаблица.Реквизит2 КАК Реквизит2
    |ИЗ
    |	ВТ_ИсходнаяТаблица КАК ВТ_ИсходнаяТаблица";

Запрос.УстановитьПараметр("ВТ_Данные", ТЗДанные);
РезультатЗапроса = Запрос.Выполнить();

Важные требования к таблице значений для запроса

Посмотрим на основные условия, которым должна соответствовать передаваемая в запрос ТаблицаЗначений:

  1. Строгая типизация колонок: у каждой колонки таблицы значений должно быть заполнено свойство ТипЗначения (объект ОписаниеТипов). Если колонка не имеет типа (тип Неопределено), запрос сгенерирует ошибку.
  2. Серверный контекст: создание объекта ТаблицаЗначений и выполнение запроса возможны только в серверном контексте (директивы &НаСервере или &НаСервереБезКонтекста).
  3. Правила именования полей: имена колонок таблицы должны соответствовать правилам наименования идентификаторов в 1С (без пробелов, спецсимволов и начинаться с буквы или подчеркивания).

Альтернативный вариант через РеквизитФормыВЗначение

Если мы работаем в модуле управляемой формы, можно использовать встроенную функцию РеквизитФормыВЗначение. Этот способ сохраняет типизацию колонок, заданную в свойствах реквизита формы:


&НаСервере
Процедура ОбработатьТаблицуФормыНаСервере()
    
    // Преобразуем реквизит формы в ТаблицуЗначений
    ТаблицаДляЗапроса = РеквизитФормыВЗначение("ТаблаНаФорме");
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ТЗ.Реквизит1 КАК Реквизит1,
        |	ТЗ.Реквизит2 КАК Реквизит2
        |ПОМЕСТИТЬ ВТ_Данные
        |ИЗ
        |	&ТаблицаИсточника КАК ТЗ
        |;
        |
        |ВЫБРАТЬ
        |	ВТ_Данные.Реквизит1 КАК Реквизит1,
        |	ВТ_Данные.Реквизит2 КАК Реквизит2
        |ИЗ
        |	ВТ_Данные КАК ВТ_Данные";
        
    Запрос.УстановитьПараметр("ТаблицаИсточника", ТаблицаДляЗапроса);
    Результат = Запрос.Выполнить();
    
КонецПроцедуры

Совет по производительности: если создаваемая временная таблица содержит большой объем строк и в дальнейшем соединяется с таблицами базы данных, обязательно используйте индексацию по ключевым полям с помощью инструкции ПОМЕСТИТЬ ВТ_Данные ИНДЕКСИРОВАТЬ ПО Реквизит1.

← На главную