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