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

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

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

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

Разбираем проблему: разница между табличным полем и таблицей значений

Выясним причину основной ошибки, с которой столкнулся автор темы на форуме. Попытка вызвать метод напрямую у элемента формы:

ЭлементыФормы.ТЗ.Загрузить(Запрос.Выполнить().Выгрузить());

приводит к ошибке работы платформы. Почему так происходит? Дело в том, что необходимо четко разделять два понятия:

  1. Элемент управления (визуальный объект): В обычных формах это ТабличноеПоле. Оно отвечает исключительно за отображение данных на экране, отрисовку строк, колонок и обработку событий мыши и клавиатуры. У этого объекта нет и не может быть метода Загрузить(), так как он сам по себе не хранит данные.
  2. Объект данных (прикладной объект): В данном случае это ТаблицаЗначений. Именно этот объект физически содержит строки и колонки с данными в оперативной памяти компьютера. И именно у него есть метод Загрузить().

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

Решение для Обычных форм (1С 8.0 - 8.2)

Рассмотрим подробнее, как решить эту задачу на обычных формах. У нас есть два основных корректных пути реализации.

Вариант 1. Использование свойства "Значение" элемента формы

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


РезультатЗапроса = Запрос.Выполнить();
ЭлементыФормы.ТЗ.Значение = РезультатЗапроса.Выгрузить();
ЭлементыФормы.ТЗ.СоздатьКолонки();

Разберем по шагам, что происходит в данном коде:

  1. Мы выполняем запрос и выгружаем его результат. Метод Выгрузить() возвращает нам полноценный новый объект типа ТаблицаЗначений.
  2. Мы присваиваем этот новый объект свойству ЭлементыФормы.ТЗ.Значение. В этот момент старая таблица значений в памяти уничтожается, а на её место встает новая, содержащая структуру и данные из нашего запроса.
  3. Важный шаг: Мы вызываем метод ЭлементыФормы.ТЗ.СоздатьКолонки(). Так как мы заменили таблицу значений на абсолютно новую, у нее изменился состав колонок. Визуальный элемент управления на форме еще не знает об этом. Метод СоздатьКолонки() принудительно обновляет сетку табличного поля на форме, создавая визуальные столбцы в соответствии с новой структурой данных.

Вариант 2. Использование прямого обращения к реквизиту формы

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


ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
ТЗ.Очистить();
ТЗ = ТаблицаРезультата;
ЭлементыФормы.ТЗ.СоздатьКолонки();

Или, если мы хотим сохранить структуру существующих колонок (например, если они уже настроены на форме с определенной шириной, заголовками и типами данных), мы используем метод Загрузить():


ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
ТЗ.Загрузить(ТаблицаРезультата);

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

Решение для Управляемых форм (1С 8.3)

В современных конфигурациях 1С на управляемых формах архитектура работы с интерфейсом кардинально изменилась. Понятие ЭлементыФормы ушло в прошлое, а данные четко разделены на клиентские структуры (данные формы) и объекты базы данных.

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

Вариант А. Структура колонок известна заранее (типовой случай)

Если вы заранее добавили на форму реквизит с типом Таблица значений, создали у него необходимые колонки и перетащили этот реквизит на элемент формы (создав элемент декорации таблицы), то заполнение на сервере будет выглядеть следующим образом:


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

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

Вариант Б. Динамическое создание колонок (структура неизвестна заранее)

Если ваш запрос динамический (например, отчет с плавающим числом колонок), то на управляемой форме нам придется программно перестраивать структуру реквизитов и элементов формы. Посмотрим на пример реализации:


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

Этот метод более трудоемок, но он позволяет полностью сымитировать поведение метода СоздатьКолонки() на управляемых формах.

Рекомендации по производительности и лучшие практики

В завершение разберем несколько важных архитектурных правил при работе с таблицами и запросами в 1С:

← На главную