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

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

Как выгрузить таблицу значений на форму в 1С

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

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

Ошибки на этом этапе встречаются регулярно: разработчик заполняет таблицу на сервере, но на форме она пустая; либо колонки видны, но без данных; либо при каждом обновлении таблица дублируется. Все эти проблемы связаны с непониманием механизма передачи данных между сервером и клиентом в управляемых формах.

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

Почему таблицу значений нельзя просто «показать» на форме

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

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

Отсюда главное правило: любые манипуляции с объектом ТаблицаЗначений (запросы, заполнение, свёртка) выполняются в серверных процедурах, а на форму попадает только результат преобразования.

Способ 1: статический реквизит формы с известной структурой

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

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

&НаСервере

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

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

// Переносим таблицу значений в реквизит формы

ЗначениеВДанныеФормы(ТЗ, Товары);

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

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

Порядок действий для статического реквизита
  1. 1
    Откройте форму в конфигураторе, добавьте реквизит типа «ТаблицаЗначений»
  2. 2
    Добавьте подчинённые реквизиты-колонки с нужными типами
  3. 3
    Перетащите реквизит в дерево элементов формы
  4. 4
    В серверной процедуре получите ТаблицуЗначений (запрос или программно)
  5. 5
    Перенесите данные через ЗначениеВДанныеФормы() или Реквизит.Загрузить(ТЗ)
  6. 6
    Откройте форму в режиме предприятия и проверьте заполнение

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

Когда структура таблицы заранее неизвестна — например, колонки зависят от настроек пользователя или формируются произвольным запросом — реквизиты создаются программно. Это делается только на сервере и только до момента отображения формы, обычно в ПриСозданииНаСервере.

&НаСервере

Процедура СоздатьТаблицуНаФорме(ТЗ)

// 1. Формируем описание добавляемых реквизитов

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

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

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

Для Каждого Колонка Из ТЗ.Колонки Цикл

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

Колонка.ТипЗначения, "ТаблицаДанных", Колонка.Заголовок));

КонецЦикла;

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

// 2. Создаём элемент формы — таблицу

ЭлементТаблица = Элементы.Добавить("ТаблицаДанных", Тип("ТаблицаФормы"));

ЭлементТаблица.ПутьКДанным = "ТаблицаДанных";

// 3. Создаём колонки элемента

Для Каждого Колонка Из ТЗ.Колонки Цикл

ЭлементКолонка = Элементы.Добавить("Колонка_" + Колонка.Имя,

Тип("ПолеФормы"), ЭлементТаблица);

ЭлементКолонка.ПутьКДанным = "ТаблицаДанных." + Колонка.Имя;

ЭлементКолонка.Вид = ВидПоляФормы.ПолеВвода;

КонецЦикла;

// 4. Загружаем данные

ЗначениеВДанныеФормы(ТЗ, ТаблицаДанных);

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

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

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

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

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

&НаСервере

Процедура НастроитьСписокНаСервере()

СписокДанных.ТекстЗапроса =

"ВЫБРАТЬ Товар, Количество

|ИЗ РегистрНакопления.ОстаткиТоваров.Остатки(&Период, )";

СписокДанных.Параметры.УстановитьЗначениеПараметра("Период",

ТекущаяДатаСеанса());

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

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

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

Статический реквизит ТЗ

Подходит при известной структуре колонок; минимум кода, простая настройка. Ограничение: нельзя менять состав колонок в режиме предприятия.

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

Подходит при динамической структуре; полный контроль. Ограничение: больше кода, риск ошибок при повторном создании.

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

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

Заполнение таблицы значений перед выводом

Чаще всего таблица значений получается результатом запроса методом Выгрузить(). Но её можно собрать и вручную — это типичный сценарий при загрузке данных из файлов или расчётах:

&НаСервере

Функция СформироватьТаблицу()

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Наименование",

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

ТЗ.Колонки.Добавить("Сумма",

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

Для Сч = 1 По 10 Цикл

Строка = ТЗ.Добавить();

Строка.Наименование = "Позиция " + Сч;

Строка.Сумма = Сч * 100;

КонецЦикла;

Возврат ТЗ;

КонецФункции

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

Обновление данных и обратное чтение с формы

При повторном заполнении таблицы (например, по кнопке «Обновить») сначала очистите реквизит, иначе строки добавятся к существующим:

&НаКлиенте

Процедура ОбновитьДанные(Команда)

ОбновитьДанныеНаСервере();

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

&НаСервере

Процедура ОбновитьДанныеНаСервере()

Товары.Очистить(); // очистка реквизита формы

ТЗ = СформироватьТаблицу();

ЗначениеВДанныеФормы(ТЗ, Товары);

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

Для обратной операции — когда пользователь редактировал таблицу на форме и данные нужно обработать на сервере — используется ДанныеФормыВЗначение:

&НаСервере

Процедура ОбработатьНаСервере()

ТЗ = ДанныеФормыВЗначение(Товары, Тип("ТаблицаЗначений"));

// дальше с ТЗ работаем как с обычной таблицей значений

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

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

Проверка результата и диагностика проблем

После вывода таблицы проверьте три вещи: данные отображаются в нужном количестве строк, типы колонок корректны (даты показываются как даты, ссылки открываются по двойному щелчку), повторное обновление не дублирует строки. Если таблица пустая — первым делом убедитесь, что запрос вообще что-то вернул: временно выведите ТЗ.Количество() через Сообщить() до вызова ЗначениеВДанныеФормы.

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

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

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

Строки в таблице на форме
Норма

Количество строк совпадает с ТЗ.Количество() на сервере

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

Таблица пустая или строк меньше — проверяйте ЗначениеВДанныеФормы и имена колонок

Повторное обновление
Норма

Старые строки заменяются новыми

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

Строки добавляются к существующим — не вызван Очистить()

Типы данных
Норма

Даты, числа и ссылки отображаются в правильном формате

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

Все значения показаны как строки — не заданы типы колонок

FAQ

Можно ли вывести таблицу значений на обычную (неуправляемую) форму?

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

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

Используйте объект ТабличныйДокумент и построитель отчёта: ПостроительОтчета.ИсточникДанных = ТЗ, затем Вывести() в область табличного документа. Либо заполняйте ячейки в цикле по строкам таблицы через ТабДок.Область().Текст.

Почему ЗначениеВДанныеФормы выдаёт ошибку «Несоответствие типов»?

Типы колонок таблицы значений не совпадают с типами колонок реквизита формы. Например, в ТЗ колонка имеет составной тип, а в реквизите — только строка. Приведите типы к одинаковым или используйте в реквизите составной тип.

Как программно удалить динамически созданную таблицу с формы?

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

Можно ли заполнить таблицу на форме без вызова сервера?

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

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

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

Итог

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

Таблица значений — серверный объект, на форму её данные попадают только через реквизит формы: ЗначениеВДанныеФормы() или Загрузить(). При известной структуре создавайте реквизит в конфигураторе, при динамической — программно через ИзменитьРеквизиты(). Перед повторным заполнением очищайте реквизит, а типы и имена колонок держите одинаковыми в ТЗ и в реквизите.