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