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

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

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

Почему возникает ошибка при работе с таблицей формы?

Давайте проанализируем ситуацию. Когда мы работаем с таблицей, которая добавлена в реквизиты управляемой формы, её тип — ДанныеФормыКоллекция. Несмотря на внешнее сходство с объектом ТаблицаЗначений, это совершенно разные типы данных.

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

Решение 1: Использование метода Выгрузить()

Самый простой и быстрый способ получить настоящую таблицу значений из коллекции данных формы — использовать встроенный метод Выгрузить(). Этот метод доступен для типа ДанныеФормыКоллекция на стороне сервера. Он создает копию данных в виде полноценного объекта ТаблицаЗначений.

Рассмотрим пример кода, который решает задачу наиболее эффективно:


// Предположим, у нас есть реквизит формы "Реализации" (тип ДанныеФормыКоллекция)
// Нам нужно передать колонку "Ссылка" в параметр запроса

// 1. Выгружаем данные формы в таблицу значений
ТаблицаРеализаций = Реализации.Выгрузить();

// 2. Теперь у нас есть объект ТаблицаЗначений, и мы можем использовать метод ВыгрузитьКолонку()
МассивСсылок = ТаблицаРеализаций.ВыгрузитьКолонку("Ссылка");

// 3. Устанавливаем параметр в запросе
Запрос.УстановитьПараметр("МассивРеализаций", МассивСсылок);

Этот способ хорош тем, что он лаконичен и не требует обращения к метаданным объекта. Однако помните, что метод Выгрузить() работает только в серверном контексте.

Решение 2: Преобразование через РеквизитФормыВЗначение

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

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


// Преобразуем реквизит формы непосредственно в вызове
Запрос.УстановитьПараметр("МассивРеализаций", РеквизитФормыВЗначение("Реализации").ВыгрузитьКолонку("Ссылка"));

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

Оптимизация: Подготовка данных перед запросом

Просто выгрузить колонку — это только половина дела. Чтобы запрос работал быстро и корректно, мы рекомендуем выполнить дополнительную обработку массива. Проанализируем типичные проблемы:

  1. Дубликаты данных. Если в вашей таблице на форме одна и та же ссылка встречается несколько раз, в массив попадут дубли. SQL-серверу придется обрабатывать лишний объем данных в условии В (&Параметр).
  2. Пустые ссылки. Пустые значения в фильтре запроса часто не несут смысла и могут замедлить выполнение, особенно в больших базах.

Разберем правильный алгоритм подготовки данных:


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

// Удаляем дубликаты по нужной колонке
ТЗ.Свернуть("Ссылка");

// Получаем массив уникальных ссылок
МассивСсылок = ТЗ.ВыгрузитьКолонку("Ссылка");

// Желательно также удалить пустые ссылки, если это допустимо логикой
ПозицияПустой = МассивСсылок.Найти(Документы.РеализацияТоваровУслуг.ПустаяСсылка());
Пока ПозицияПустой <> Неопределено Цикл
    МассивСсылок.Удалить(ПозицияПустой);
    ПозицияПустой = МассивСсылок.Найти(Документы.РеализацияТоваровУслуг.ПустаяСсылка());
КонецЦикла;

Запрос.УстановитьПараметр("МассивРеализаций", МассивСсылок);

Когда массив в параметре — это плохо?

Нужно учитывать ограничения платформы и СУБД. Если в колонке вашей таблицы на форме содержатся тысячи строк (например, более 1000–5000), передача их через массив в оператор В (...) может привести к серьезному снижению производительности или даже к ошибке SQL-сервера.

В таких ситуациях мы рекомендуем рассмотреть альтернативный вариант — использование временных таблиц:

  1. Выгрузите данные в ТаблицаЗначений.
  2. Создайте МенеджерВременныхТаблиц.
  3. Поместите таблицу значений целиком во временную таблицу запроса.
  4. В основном запросе выполните СОЕДИНЕНИЕ с этой временной таблицей вместо использования условия ГДЕ ... В (&Массив).

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

Резюме

Мы выяснили, что основной причиной ошибки является различие между типами ДанныеФормыКоллекция и ТаблицаЗначений. Для успешного решения задачи придерживайтесь следующих правил:

← На главную