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