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

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

1С: как программно заполнить табличную часть документа

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

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

Базовые инструменты — методы Добавить(), Загрузить() и Заполнить(), а также построчное присвоение реквизитов. Принципиально важно различать работу с объектом документа на сервере и заполнение табличного поля на форме: смешение этих подходов — самая частая причина ошибок у начинающих разработчиков. Ниже разобраны все основные сценарии с примерами кода и ограничениями.

Где выполняется заполнение: объект, форма, фоновое задание

Прежде чем писать код, определите контекст исполнения. Если заполнение происходит в модуле объекта, в обработке, в фоновом задании или в серверной процедуре, вы работаете с объектом ДокументОбъект и его табличной частью напрямую — это основной и самый надёжный способ. Изменения становятся постоянными только после вызова Записать().

Если заполнение инициируется пользователем кнопкой на управляемой форме, типовой подход — обернуть логику в серверную процедуру, получить объект через РеквизитФормыВЗначение("Объект"), заполнить табличную часть и вернуть данные обратно через ЗначениеВРеквизитФормы(). Напрямую обращаться к данным объекта из клиентской процедуры нельзя — управляемая форма не даёт доступа к методам объекта на клиенте.

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

Построчное заполнение методом Добавить()

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

ДокОбъект = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

ДокОбъект.Дата = ТекущаяДатаСеанса();

ДокОбъект.Организация = Организация;

ДокОбъект.Контрагент = Контрагент;

Для Каждого СтрокаДанных Из ДанныеДляЗаполнения Цикл

НоваяСтрока = ДокОбъект.Товары.Добавить();

НоваяСтрока.Номенклатура = СтрокаДанных.Номенклатура;

НоваяСтрока.Количество = СтрокаДанных.Количество;

НоваяСтрока.Цена = СтрокаДанных.Цена;

НоваяСтрока.Сумма = СтрокаДанных.Количество * СтрокаДанных.Цена;

КонецЦикла;

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

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

Пакетная загрузка методом Загрузить()

Когда данные уже собраны в таблицу значений — например, результатом запроса — табличную часть удобно заполнить одним вызовом Загрузить(). Метод очищает табличную часть и переносит в неё строки таблицы значений, сопоставляя колонки и реквизиты по именам.

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

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

"ВЫБРАТЬ

| Остатки.Номенклатура КАК Номенклатура,

| Остатки.КоличествоОстаток КАК Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки";

Запрос.УстановитьПараметр("Период", КонецДня(ДатаИнвентаризации));

Запрос.УстановитьПараметр("Склад", Склад);

ДокОбъект.Товары.Загрузить(Запрос.Выполнить().Выгрузить());

Два условия корректной работы: имена колонок таблицы значений должны совпадать с именами реквизитов табличной части, а типы значений должны быть совместимы. Колонки, которых нет среди реквизитов, будут проигнорированы; реквизиты, для которых нет колонки, останутся незаполненными. Если нужно дополнить данные после загрузки, пройдитесь по строкам циклом и дозаполните недостающие реквизиты.

Помните, что Загрузить() полностью заменяет содержимое табличной части. Если нужно добавить строки к существующим, предварительно выгрузите текущие данные через Выгрузить(), объедините с новыми и загрузите результат — либо используйте построчное добавление.

Заполнение через типовой механизм Заполнить() и обработку заполнения

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

Если вы дорабатываете типовую конфигурацию, правильное место для своей логики заполнения — расширение конфигурации с аннотацией &После("ОбработкаЗаполнения") или собственная процедура, вызываемая из команды формы. Прямая правка типового модуля усложнит последующие обновления.

// Пример: заполнение табличной части по документу-основанию

Процедура ЗаполнитьПоОснованию(ДокументОснование) Экспорт

Для Каждого СтрокаОснования Из ДокументОснование.Товары Цикл

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

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаОснования);

КонецЦикла;

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

Метод ЗаполнитьЗначенияСвойств() копирует одноимённые свойства из источника в приёмник — это удобно при копировании строк между табличными частями с похожим составом реквизитов. Учтите, что копируются только совпадающие по именам свойства, а реквизиты с несовместимыми типами могут вызвать ошибку.

Заполнение из управляемой формы по команде пользователя

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

&НаКлиенте

Процедура ЗаполнитьОстатками(Команда)

ЗаполнитьОстаткамиНаСервере();

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

&НаСервере

Процедура ЗаполнитьОстаткамиНаСервере()

ДокОбъект = РеквизитФормыВЗначение("Объект");

ДокОбъект.Товары.Очистить();

// ... заполнение ДокОбъект.Товары ...

ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

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

Порядок действий при заполнении из формы
  1. 1
    Создайте команду формы и кнопку в табличной части или командной панели
  2. 2
    В клиентском обработчике вызовите серверную процедуру без параметров-объектов
  3. 3
    На сервере получите объект через РеквизитФормыВЗначение("Объект")
  4. 4
    Очистите табличную часть, если требуется замена данных
  5. 5
    Заполните строки методом Добавить() или Загрузить()
  6. 6
    Верните данные через ЗначениеВРеквизитФормы()
  7. 7
    Проверьте, что форма отображает новые строки и признак модифицированности

Выбор способа и типичные ошибки

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

Сравнение способов заполнения

Добавить() построчно

Подходит для циклов с условиями и индивидуальным расчётом реквизитов; код длиннее, но полностью управляем

Загрузить() из таблицы значений

Оптимален для результата запроса; требует совпадения имён колонок и полностью заменяет содержимое табличной части

ЗаполнитьЗначенияСвойств()

Удобен при копировании строк между похожими табличными частями; не копирует свойства с разными именами

ОбработкаЗаполнения()

Стандартное место для заполнения при вводе на основании; не подходит для заполнения по кнопке на форме

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

Контроль результата и безопасная запись

Перед записью документа полезно проверить заполненность обязательных реквизитов строк: пустая номенклатура или нулевое количество могут привести к ошибкам проведения или к некорректным данным в учёте. Минимальная проверка — наличие строк в табличной части и заполненность ключевых реквизитов каждой строки.

Запись выполняйте с осмысленным режимом: РежимЗаписиДокумента.Запись сохраняет документ без движений, Проведение — сразу формирует движения по регистрам. Если заполнение выполняется массово по многим документам, оборачивайте запись каждого документа в попытку/исключение и фиксируйте ошибки, чтобы один проблемный документ не прервал всю обработку.

Если ДокОбъект.Товары.Количество() = 0 Тогда

ВызватьИсключение "Табличная часть не заполнена: нет данных для документа";

КонецЕсли;

Попытка

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

Исключение

ЗаписьЖурналаРегистрации("ЗаполнениеДокумента",

УровеньЖурналаРегистрации.Ошибка, , ,

ОписаниеОшибки());

КонецПопытки;

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

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

Количество строк в табличной части
Норма

Совпадает с количеством строк источника данных

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

Строк меньше (отборы запроса отсекли данные) или больше (дубли при повторном запуске)

Заполненность сумм и цен
Норма

Все расчётные реквизиты заполнены, итоги сходятся с источником

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

Пустые суммы — не вызвана логика расчёта из обработчиков формы

Проведение документа
Норма

Документ проводится без сообщений об ошибках

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

Ошибки о незаполненных реквизитах или отрицательных остатках

Частые вопросы

Как заполнить табличную часть у существующего документа, а не у нового?

Получите объект по ссылке: ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();, затем изменяйте табличную часть и вызывайте Записать(). Работать напрямую со ссылкой нельзя — через неё табличная часть доступна только для чтения.

Почему после Загрузить() пропали строки, которые были в документе?

Метод Загрузить() полностью очищает табличную часть перед переносом данных. Если нужно сохранить существующие строки, выгрузите их методом Выгрузить(), добавьте новые строки в полученную таблицу значений и загрузите объединённый результат, либо используйте построчное Добавить().

Почему не рассчитывается сумма, хотя на форме она считается автоматически?

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

Можно ли заполнить табличную часть без записи документа?

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

Как избежать дублей строк при повторном нажатии кнопки заполнения?

Перед заполнением вызывайте Товары.Очистить(), если повторное заполнение должно заменять данные. Если нужно дополнять, проверяйте наличие строки по ключевому реквизиту через Найти() или НайтиСтроки() перед добавлением.

Чем отличается заполнение в обычных формах от управляемых?

В обычных формах объект документа доступен на клиенте напрямую, и разделение на клиентские и серверные процедуры не требуется. В управляемых формах вся работа с объектом выполняется только на сервере через РеквизитФормыВЗначение() и обратное преобразование.

Итог

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

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