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