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

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

В практике разработки на платформе 1С 8.3 программисты часто сталкиваются с необходимостью обработать данные, которые пользователь ввел в таблицу на форме, с помощью механизма запросов — для этой задачи есть расширение для автоматизации написания кода 1С. Однако при переходе с обычных форм на управляемые возникают нюансы, связанные с разделением кода на клиентский и серверный, а также с особенностями типов данных управляемой формы. В этой статье мы подробно разберем, как правильно передать таблицу управляемой формы в запрос, избежать типичных ошибок и оптимизировать этот процесс.

Причина возникновения ошибки при прямом обращении к таблице

Рассмотрим стандартную ситуацию: у нас есть реквизит формы ТабСум с типом ТаблицаЗначений, который отображается на экране. Попытка передать этот реквизит напрямую в параметр запроса, как это иногда срабатывало в старых версиях платформы, приведет к ошибке: "Содержимое объекта данных может быть выбрано только во временную таблицу". Выясним причину: данные на управляемой форме хранятся в специальном формате ДанныеФормыКоллекция, который не является полноценной таблицей значений с точки зрения SQL-движка 1С. Чтобы запрос «понял» эти данные, их нужно предварительно подготовить.

Шаг 1. Преобразование данных формы в таблицу значений

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


&НаСервере
Функция ПолучитьТаблицуДляЗапроса()
    // Выгружаем данные из реквизита формы в реальную Таблицу Значений
    ТЗ = ТабСум.Выгрузить(); 
    Возврат ТЗ;
КонецФункции

Здесь метод Выгрузить() создает копию данных таблицы в виде объекта ТаблицаЗначений. Также можно использовать метод ДанныеФормыВЗначение(), если требуется преобразовать объект целиком с сохранением всех метаданных, но для простых таблиц Выгрузить() вполне достаточно.

Шаг 2. Использование временных таблиц в запросе

Как только мы получили объект ТаблицаЗначений, мы должны передать его в запрос. Важное правило управляемых форм: внешние таблицы значений в запросе можно использовать только путем помещения их во временные таблицы — для этого подойдёт консоль запросов и кода для тестирования логики. Рассмотрим подробнее код запроса:


&НаСервере
Процедура ВыполнитьЗапросНаСервере()
    // 1. Подготавливаем данные
    ВнешняяТЗ = ТабСум.Выгрузить();

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

    // 3. Устанавливаем параметр
    Запрос.УстановитьПараметр("ВнешнийИсточник", ВнешняяТЗ);

    // 4. Выполняем и получаем результат
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        ТаблицаРезультата = РезультатЗапроса.Выгрузить();
        // Дальнейшая обработка данных на сервере
    КонецЕсли;
КонецПроцедуры

В данном примере мы используем конструкцию ПОМЕСТИТЬ. Это критически важно, так как платформа не позволяет выполнять прямые соединения или выборки из внешних таблиц значений без их предварительной материализации в менеджере временных таблиц БД.

Шаг 3. Решение проблемы передачи данных между клиентом и сервером

Частая ошибка начинающих разработчиков — попытка вернуть результат запроса (объект ТаблицаЗначений) напрямую с сервера на клиент — поможет инструмент пошаговой отладки кода и запросов. Это вызывает ошибку: "Ошибка отображения типов: Отсутствует отображение для типа ValueTable". В управляемом приложении объект ТаблицаЗначений не существует на клиенте. Разберем, как поступить правильно:

  1. Обработка на сервере: Старайтесь выполнять всю логику обработки результата запроса внутри серверной процедуры. Если данные нужны для заполнения другой таблицы на форме, делайте это там же на сервере, обращаясь к реквизитам формы напрямую.
  2. Передача через массив структур: Если данные жизненно необходимы на клиенте, преобразуйте их в массив структур. Массивы и структуры — это «легкие» типы, которые отлично передаются между клиентом и сервером.
  3. Использование временного хранилища: Поместите таблицу во временное хранилище и передайте на клиент только адрес (строку).

Посмотрим на пример правильной организации вызовов:


&НаКлиенте
Процедура КомандаПроверить(Команда)
    // Вызываем серверную процедуру, которая все сделает сама
    ОбработатьДанныеНаСервере();
    // Оповещаем пользователя
    Сообщить("Обработка завершена успешно!");
КонецПроцедуры

&НаСервере
Процедура ОбработатьДанныеНаСервере()
    // Выгружаем данные формы
    ДанныеДляЗапроса = ТабСум.Выгрузить();
    
    // Выполняем запрос (аналогично коду выше)
    // ... запрос помещает данные в ВТ и обрабатывает их ...
    
    // Если нужно обновить данные на форме:
    // ТабРезультатНаФорме.Загрузить(РезультатЗапроса.Выгрузить());
КонецПроцедуры

Дополнительные рекомендации для повышения производительности

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

1. Обязательная типизация колонок. При выгрузке таблицы значений 1С должна точно знать типы данных каждой колонки. Если в исходной таблице на форме колонки не имеют четкого типа (составной тип или «любая ссылка»), запрос может работать медленно или выдавать ошибки типизации. Рекомендуется явно описывать типы при программном создании таблиц с помощью объекта ОписаниеТипов.

2. Индексация временной таблицы. Если вы планируете соединять (ЛЕВОЕ СОЕДИНЕНИЕ) выгруженную таблицу с большими таблицами базы данных (например, с регистрами), обязательно добавьте индексацию по ключевым полям в самом запросе. Это делается так:

"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ ИНДЕКСИРОВАТЬ ПО Номер"

3. Использование Менеджера временных таблиц. Если логика обработки сложная и включает несколько разных запросов, создайте МенеджерВременныхТаблиц. Это позволит «сохранить» вашу таблицу ВТ_Данные между вызовами разных объектов Запрос в рамках одного серверного контекста.

Подводя итог, отметим: работа с таблицами в управляемых формах требует дисциплины в разделении контекстов выполнения. Выгружаем данные на сервере через Выгрузить(), используем ПОМЕСТИТЬ в тексте запроса и обрабатываем результат, не пытаясь передать объект ТаблицаЗначений обратно на клиент.

← На главную