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

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

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

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

Почему не работает простая загрузка данных?

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

Если мы попытаемся выполнить привычный для обычных форм код:


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

то мы столкнемся с тем, что таблица на форме останется пустой или платформа вернет ошибку о том, что объект не обнаружен. Выясним причину этого поведения. Метод СоздатьКолонки() у элемента формы действительно существует, но он умеет визуализировать только те колонки, которые уже явно объявлены в структуре реквизита формы. Если сам реквизит ТЗДляВыгрузки изначально не имеет колонок в конфигураторе, метод просто не сможет ничего отобразить.

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

Решение 1. Программное создание динамической Таблицы Значений

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

  1. Выполняем запрос и получаем результат. Сначала мы выгружаем результат запроса в обычную прикладную таблицу значений в памяти сервера.
  2. Очищаем старые колонки. Если мы вызываем этот код повторно (например, при изменении параметров запроса), нам обязательно нужно удалить старые элементы формы и старые реквизиты, чтобы избежать ошибок дублирования имен.
  3. Формируем массивы для изменения реквизитов. Платформа 1С требует, чтобы создание реквизитов формы происходило пакетом через метод ИзменитьРеквизиты(). Мы подготавливаем массив новых реквизитов.
  4. Применяем изменения на форме. Вызываем метод ИзменитьРеквизиты().
  5. Заполняем данные. Копируем данные из прикладной таблицы значений в новый реквизит формы с помощью метода ЗначениеВРеквизитФормы().
  6. Создаем визуальные колонки на форме. Программно добавляем элементы формы типа ПолеФормы и связываем их с данными.

Посмотрим на пример готовой процедуры, реализующей этот алгоритм:


&НаСервере
Процедура ОбновитьТаблицуНаФорме(Запрос)

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

КонецПроцедуры

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

Решение 2. Использование Динамического списка (ДС)

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

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

Выясним, как правильно передавать параметры в запрос динамического списка. Делать это нужно обязательно до открытия формы (например, в обработчике события ПриСозданииНаСервере), иначе платформа выдаст ошибку о незаполненных параметрах.

Рассмотрим пример установки параметров динамического списка:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // Установка начальных значений параметров для динамического списка "ТЗДляВыгрузки"
    ТЗДляВыгрузки.Параметры.УстановитьЗначениеПараметра("НачДата", Период.ДатаНачала);    
    ТЗДляВыгрузки.Параметры.УстановитьЗначениеПараметра("КонДата", Период.ДатаОкончания);    

КонецПроцедуры

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

Особенности сортировки и порядка колонок в Динамическом списке

При использовании Динамического списка разработчики часто сталкиваются с неочевидной деталью: порядок полей в тексте запроса (в секции ВЫБРАТЬ...) может не совпадать с порядком колонок на форме. Почему это происходит?

Дело в том, что порядок колонок в таблице формы для динамического списка определяется:

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


// Пример перемещения колонки "КоличествоОборот" в самое начало таблицы
Элементы.Переместить(Элементы.ТЗДляВыгрузкиКоличествоОборот, Элементы.ТЗДляВыгрузки);

Сравнительный анализ: Динамическая ТЗ или Динамический список?

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

Выбирайте программную Таблицу Значений (ТЗ), если:

Выбирайте Динамический список (ДС), если:

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

← На главную