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