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

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

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

Как программно добавить строку в табличную часть документа 1С: методы Добавить(), заполнение реквизитов, работа на клиенте и сервере, типичные ошибки.

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

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

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

Базовый способ: метод Добавить() у табличной части

Если у вас есть объект документа (полученный через ПолучитьОбъект() или созданный через Документы.РеализацияТоваровУслуг.СоздатьДокумент()), добавление строки выглядит так:

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

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

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

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

НоваяСтрока.Количество = 5;

НоваяСтрока.Цена = 1200;

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

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

Метод Добавить() возвращает объект типа «строка табличной части», и именно через него заполняются реквизиты. Если не сохранить возвращаемое значение, обратиться к добавленной строке можно по индексу: ДокументОбъект.Товары[ДокументОбъект.Товары.Количество() - 1], но это менее читаемо.

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

bsl
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = ВыбраннаяНоменклатура;
НоваяСтрока.Количество = 1;

Добавление строки из формы документа

В модуле формы документа табличная часть доступна через реквизит формы Объект. Код Объект.Товары.Добавить() добавит строку в данные формы, и она сразу отобразится в интерфейсе без дополнительного обновления.

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

Для интерактивного добавления (когда пользователь должен сразу увидеть курсор в новой строке) используется метод таблицы формы: Элементы.Товары.ДобавитьСтроку(). Он имитирует нажатие кнопки «Добавить» и вызывает стандартные обработчики ПриНачалеРедактирования и ПередНачаломДобавления.

Выбор между клиентом и сервером

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

Маршрут решения

Как выбрать действие

Нужно просто добавить пустую строку для ручного вводаИспользуйте Элементы.Товары.ДобавитьСтроку() на клиенте
Строку нужно заполнить данными из базы (цены, остатки)Добавляйте и заполняйте строку в серверной процедуре через Объект.Товары.Добавить()
Документ создаётся или изменяется вне формы (обмен, обработка)Работайте с объектом документа и вызывайте Записать()

Заполнение табличной части по данным другого документа

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

Для Каждого СтрокаЗаказа Из ЗаказОбъект.Товары Цикл

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

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

КонецЦикла;

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

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

Пересчёт сумм и вызов обработчиков заполнения

Программное добавление строки не вызывает обработчики формы вида ТоварыКоличествоПриИзменении — они срабатывают только при интерактивном редактировании. Поэтому если в типовой логике сумма рассчитывается в таком обработчике, при программном заполнении её нужно пересчитать самостоятельно.

Правильный подход — вынести расчёт в отдельную процедуру (например, РассчитатьСуммуСтроки(СтрокаТабличнойЧасти)) и вызывать её и из обработчиков формы, и из кода программного заполнения. Так гарантируется одинаковая логика при любом способе добавления строки.

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

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

Добавление строки перед записью и в подписках на события

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

В ПередЗаписью объект ещё доступен для изменения, и добавленная строка сохранится вместе с документом. Здесь важно защититься от зацикливания и дублирования: перед добавлением проверяйте, нет ли уже такой строки методом Найти() или НайтиСтроки(), иначе при каждой перезаписи будет появляться новая строка.

ПараметрыОтбора = Новый Структура("Номенклатура", УслугаДоставки);

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

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

НоваяСтрока.Номенклатура = УслугаДоставки;

НоваяСтрока.Количество = 1;

КонецЕсли;

Типичные ошибки и как их избежать

Самая частая ошибка — добавление строк в ссылку, а не в объект. Конструкция ДокументСсылка.Товары.Добавить() недоступна: у ссылки табличная часть доступна только для чтения. Нужно сначала получить объект: ДокументОбъект = ДокументСсылка.ПолучитьОбъект().

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

Третья типичная проблема — добавление строк в документ, который не может быть проведён: не заполнены обязательные реквизиты шапки, дата запрета редактирования закрыта. Вызов Записать(РежимЗаписиДокумента.Проведение) вызовет исключение, и все добавленные строки не сохранятся. Оборачивайте запись в попытку-исключение и анализируйте текст ошибки.

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

Проверка результата

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

Программно проверить можно так: получить объект заново из базы и сравнить ДокументОбъект.Товары.Количество() с ожидаемым числом, а также вычислить итог по колонке суммы через ДокументОбъект.Товары.Итог("Сумма"). Если документ проведён, дополнительно проверьте движения по регистрам — они должны соответствовать добавленным строкам.

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

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

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

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

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

Строк меньше — запись не выполнилась или произошло исключение

Суммы по строкам и итог документа
Норма

Суммы рассчитаны, итог сходится с расчётным

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

Суммы нулевые — не вызван пересчёт после заполнения

Движения документа по регистрам
Норма

Есть записи по каждой строке товаров

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

Движений нет — документ записан без проведения

FAQ

Как добавить строку в табличную часть, если документ уже проведён?

Получите объект через ПолучитьОбъект(), добавьте строку и запишите документ с режимом Проведение. Учтите: изменение проведённого документа перепроведёт его, движения по регистрам будут пересчитаны, а при закрытом периоде запись будет запрещена.

Чем отличается Добавить() от Вставить()?

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

Почему после Добавить() строка не видна в открытой форме документа?

Если код выполняется вне формы (в обработке, фоновом задании), он меняет объект в базе, а открытая форма показывает свою копию данных. Пользователю нужно перечитать документ (команда «Перечитать») или переоткрыть форму. Одновременное редактирование одного документа в форме и кодом чревато конфликтом при записи.

Как добавить строку в табличную часть на управляемой форме тонкого клиента?

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

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

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

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

Нет. Строки табличной части хранятся вместе с документом и сохраняются только при его записи. Отдельно записать строку табличной части нельзя — любое изменение требует вызова Записать() у объекта документа.

Итог

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

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