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