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