К статье
Практический материал

Разработка и Конфигурация · 13 мин

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

Практическое руководство: как вывести таблицу значений на управляемую форму 1С через реквизит формы, динамический список и программное заполнение.

Задача вывести таблицу значений на управляемую форму встречается почти в каждой доработке 1С: это может быть результат произвольного запроса, промежуточные данные расчёта, загруженный из файла список строк или набор данных, которого нет ни в одном объекте конфигурации. В отличие от обычных форм, где таблицу значений можно было напрямую назначить элементу управления, управляемые формы требуют другого подхода — через реквизит формы с типом «ТаблицаЗначений» и программное заполнение на сервере.

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

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

Способ 1: реквизит формы типа «ТаблицаЗначений»

Это стандартный и самый надёжный способ. В конфигураторе откройте управляемую форму, перейдите на вкладку «Реквизиты» и добавьте новый реквизит, указав тип «ТаблицаЗначений». После этого в дереве реквизитов разверните его и добавьте колонки — для каждой задайте имя и тип (строка, число, дата, ссылка и т.д.). Имена колонок должны совпадать с именами колонок таблицы значений, которую вы будете загружать программно.

Затем перетащите реквизит из панели реквизитов в дерево элементов формы — платформа автоматически создаст таблицу формы с колонками-полями. При необходимости настройте свойства элемента: «ТолькоПросмотр», «Шапка», «КоманднаяПанель» и режим редактирования.

Заполнение выполняется только в серверном контексте. Типичный код выглядит так:

&НаСервере

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 100

| Номенклатура.Ссылка КАК Номенклатура,

| Номенклатура.Код КАК Код

|ИЗ

| Справочник.Номенклатура КАК Номенклатура";

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

ЗначениеВРеквизитФормы(ТЗ, "МояТаблица");

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

Здесь «МояТаблица» — имя реквизита формы. Метод ЗначениеВРеквизитФормы() преобразует серверную таблицу значений в данные формы, которые видит клиент. Обратное преобразование — РеквизитФормыВЗначение("МояТаблица") — используется, когда нужно получить заполненную пользователем таблицу обратно в виде объекта ТаблицаЗначений.

Способ 2: программное создание реквизитов при динамической структуре

Если набор колонок известен только в момент выполнения — например, вы загружаете произвольный файл или строите отчёт с переменным числом колонок — реквизиты создаются программно в обработчике ПриСозданииНаСервере. Для этого используется метод формы ИзменитьРеквизиты(), которому передаётся массив добавляемых реквизитов типа «РеквизитФормы».

&НаСервере

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

Добавляемые = Новый Массив;

Добавляемые.Добавить(Новый РеквизитФормы("ТЗДанные",

Новый ОписаниеТипов("ТаблицаЗначений")));

Добавляемые.Добавить(Новый РеквизитФормы("Колонка1",

Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(150)),

"ТЗДанные", "Колонка 1"));

Добавляемые.Добавить(Новый РеквизитФормы("Колонка2",

Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)),

"ТЗДанные", "Колонка 2"));

ИзменитьРеквизиты(Добавляемые);

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

После создания реквизитов нужно программно добавить и элементы формы: таблицу (Элементы.Добавить() с типом «ТаблицаФормы»), привязать её к реквизиту через свойство ПутьКДанным, затем добавить колонки-поля, каждой указав путь вида «ТЗДанные.Колонка1». Без привязки элементов к данным таблица на форме отобразится пустой.

Учтите ограничение: ИзменитьРеквизиты() нельзя вызывать повторно для уже существующих реквизитов без их удаления — платформа выдаст ошибку о дублировании. Если форма открывается многократно с разной структурой, либо пересоздавайте форму, либо передавайте в массив удаляемых реквизитов имена ранее добавленных.

Способ 3: динамический список с произвольным запросом

Если данные берутся из базы запросом и не требуют редактирования, часто удобнее обойтись без таблицы значений вообще. Добавьте на форму реквизит типа «ДинамическийСписок», установите флаг «Произвольный запрос» и впишите текст запроса. Платформа сама выполнит запрос и отобразит результат, с поддержкой сортировки, отбора и динамического обновления.

Этот способ выигрывает на больших объёмах: динамический список читает данные порциями, а таблица значений загружается в память целиком. Ограничение — динамический список предназначен для просмотра, а не для редактирования произвольных данных, и не подходит, если источником служит не запрос к базе, а, например, файл или веб-сервис.

Сравнение способов вывода

Реквизит ТаблицаЗначений

Универсальный вариант: подходит для любых источников и редактирования. Минус — вся таблица в памяти сервера и клиента.

Программные реквизиты

Единственный вариант при заранее неизвестной структуре колонок. Минус — больше кода и сложнее сопровождение.

Динамический список

Лучший выбор для просмотра данных запроса из базы: порционное чтение, встроенные сортировка и отбор. Не подходит для редактирования и внешних источников.

Клиент-серверное взаимодействие и передача данных

Частая ошибка новичков — попытка заполнить таблицу в клиентской процедуре тем же кодом, что работал в обычных формах. На клиенте объекта «ТаблицаЗначений» нет: есть только коллекция данных формы. Поэтому запросы, выгрузки и вызов ЗначениеВРеквизитФормы() выполняются строго в процедурах с директивой &НаСервере.

Каждый серверный вызов сериализует данные формы и передаёт их между клиентом и сервером. Если таблица содержит десятки тысяч строк, это заметно тормозит открытие формы и каждое обращение к серверу. Практические меры: ограничивайте выборку (ПЕРВЫЕ N, отборы), выводите только нужные колонки, а для больших данных рассмотрите динамический список или постраничную загрузку.

Для добавления строк без полной перезагрузки таблицы работайте с коллекцией напрямую: НоваяСтрока = Объект.МояТаблица.Добавить(); (или ЭтаФорма.МояТаблица.Добавить() для реквизита формы). Такое добавление выполняется на клиенте без серверного вызова и не сбрасывает текущую позицию пользователя в таблице.

Оформление и интерактивность таблицы на форме

После вывода данных обычно требуется довести таблицу до рабочего состояния. Для таблицы только для просмотра установите у элемента свойство «ТолькоПросмотр» или уберите командную панель, чтобы пользователь не мог добавить строку. Для редактируемой таблицы настройте события: ПриИзменении колонки для пересчёта связанных значений, ПередУдалением для контроля удаления.

Условное оформление формы позволяет подсвечивать строки по условию без единой строчки кода — например, красить строки с отрицательным остатком. Настраивается через «УсловноеОформление» формы: задаётся отбор по полю реквизита и оформление (цвет фона, шрифт) для указанных полей таблицы.

Если нужен итог по колонке, у элемента колонки включите свойство «ОтображатьВПодвале» и «ГоризонтальноеПоложениеВПодвале», а для числовых колонок платформа умеет показывать сумму автоматически при включённом свойстве таблицы «Подвал» и соответствующей настройке поля.

Если таблица на форме отображается, но колонки приходят в «неправильном» порядке после программного заполнения — проверьте порядок колонок в реквизите формы или в дереве элементов, а не в самой таблице значений. Отображение управляется элементами формы, и их можно просто перетащить мышью в конфигураторе.
ПЗ
Практическое замечание

Типичные ошибки и их диагностика

Самая частая проблема — «таблица пустая, хотя запрос данные возвращает». Причины: имя реквизита в ЗначениеВРеквизитФормы() не совпадает с реальным именем реквизита; элемент таблицы привязан к другому реквизиту (проверьте свойство «ПутьКДанным»); заполнение вызывается на клиенте и код серверной части просто не выполняется; имена колонок запроса (псевдонимы) не совпадают с именами колонок реквизита.

Вторая группа ошибок — падение с сообщением о несоответствии типов. Оно возникает, когда колонка реквизита имеет тип «Строка(10)», а в таблице значений лежит строка длиннее, или когда тип колонки запроса — ссылка на справочник, которого нет в составе типа колонки реквизита. Лечится выравниванием описаний типов: тип колонки реквизита должен включать все типы данных, которые реально придут из источника.

Третья типичная ситуация — после серверного вызова таблица «схлопывается» и теряет введённые пользователем строки. Причина в том, что серверная процедура заново вызывает ЗначениеВРеквизитФормы() и затирает клиентские изменения. Перед перезаполнением либо сохраняйте текущие данные, либо переносите логику так, чтобы перезаполнение происходило только по явной команде пользователя.

Типичные ошибки
01
Заполнение ТЗ в клиентской процедуре — объект ТаблицаЗначений недоступен на клиенте, код не работает или падает
02
Несовпадение имён колонок запроса и колонок реквизита — данные молча не попадают в отображаемые поля
03
Повторный ИзменитьРеквизиты() без удаления старых реквизитов — ошибка дублирования при повторном открытии
04
Элемент таблицы не привязан к реквизиту через ПутьКДанным — на форме пустая сетка
05
Выгрузка всей таблицы базы без ограничения — зависание формы и тайм-ауты сервера

Проверка результата и отладка

Быстрый способ убедиться, что данные дошли до формы, — временно вывести количество строк: в серверной процедуре после заполнения добавьте Сообщить("Строк: " + МояТаблица.Количество()) (для реквизита формы обращение идёт как к коллекции). Если количество больше нуля, а на форме пусто — проблема в привязке элемента или колонок, а не в данных.

Для проверки состава колонок используйте отладчик: поставьте точку останова после РеквизитФормыВЗначение() и посмотрите структуру таблицы через «Вычислить выражение» (ТЗ.Колонки). Сверьте имена и типы с реквизитом формы — расхождения видны сразу.

Контрольные точки

Как проверить результат

Количество строк в реквизите формы после заполнения
Норма

Совпадает с числом строк результата запроса

Тревожный признак

Ноль при непустом запросе — проверяйте имя реквизита в ЗначениеВРеквизитФормы()

Свойство ПутьКДанным элемента таблицы
Норма

Указывает на реквизит типа ТаблицаЗначений

Тревожный признак

Пусто или указывает на другой реквизит — таблица будет пустой

Имена колонок полей таблицы
Норма

Совпадают с именами колонок реквизита и псевдонимами запроса

Тревожный признак

Опечатка в пути — колонка отображается пустой

Повторное открытие формы с динамическими реквизитами
Норма

Открывается без ошибок

Тревожный признак

Ошибка дублирования реквизита — нужен массив удаляемых

Итог

Что важно запомнить

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

Частые вопросы

Можно ли вывести таблицу значений без создания реквизита формы?

Нет, на управляемой форме любой отображаемый список должен быть привязан к данным формы — реквизиту типа «ТаблицаЗначений», «ДинамическийСписок» или табличной части объекта. Элемент формы без пути к данным не имеет источника и останется пустым. Минимальный вариант — программно созданный реквизит через ИзменитьРеквизиты().

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

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

Почему после серверного вызова пропадают введённые пользователем строки?

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

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

Установите у элемента таблицы свойство «ТолькоПросмотр» в Истина — редактирование будет запрещено, но прокрутка и выделение сохранятся. Дополнительно можно скрыть командную панель таблицы, чтобы убрать кнопки добавления и удаления. Для данных из базы вместо таблицы значений рассмотрите динамический список — он изначально ориентирован на просмотр.

Что делать, если колонки таблицы известны только во время выполнения?

Создавайте реквизиты и элементы программно в ПриСозданииНаСервере: сформируйте массив объектов РеквизитФормы (таблица и её колонки), вызовите ИзменитьРеквизиты(), затем добавьте элемент ТаблицаФормы и колонки-поля с корректными путями к данным. При повторных вызовах передавайте имена старых реквизитов в массив удаляемых, иначе получите ошибку дублирования.

Есть ли ограничение на количество строк в таблице значений на форме?

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