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