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

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

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

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

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

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

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

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

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

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

Интерактивная запись: заполнение в форме элемента

Самый простой случай — ручное заполнение. Откройте элемент справочника, перейдите на вкладку с табличной частью и добавьте строку кнопкой «Добавить» или клавишей Insert. Заполните колонки и нажмите «Записать» или «Записать и закрыть». Пока элемент не записан, строки существуют только в памяти формы — при закрытии без записи они пропадут.

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

Программная запись: базовый пример кода

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

// Находим существующий элемент

СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоНаименованию("Комплект крепежа");

Если СсылкаНаЭлемент.Пустая() Тогда

Возврат; // элемент не найден — строки писать некуда

КонецЕсли;

Объект = СсылкаНаЭлемент.ПолучитьОбъект();

// Добавляем строку в табличную часть "СоставКомплекта"

НоваяСтрока = Объект.СоставКомплекта.Добавить();

НоваяСтрока.Компонент = Справочники.Номенклатура.НайтиПоКоду("000123");

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

НоваяСтрока.ЕдиницаИзмерения = Справочники.ЕдиницыИзмерения.НайтиПоКоду("796");

Объект.Записать();

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

Создание нового элемента с табличной частью

Если элемента ещё нет, создайте его через СоздатьЭлемент(), заполните реквизиты шапки и строки, затем запишите:

Объект = Справочники.Номенклатура.СоздатьЭлемент();

Объект.Наименование = "Новый комплект";

Строка = Объект.СоставКомплекта.Добавить();

Строка.Компонент = КомпонентСсылка;

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

Объект.Записать();

// После записи ссылка доступна: Объект.Ссылка

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

Изменение и удаление существующих строк

Для изменения строки её сначала нужно найти. Коллекция табличной части поддерживает метод Найти(Значение, ИмяКолонки) и обход в цикле:

Объект = СсылкаНаЭлемент.ПолучитьОбъект();

// Найти и изменить строку

Строка = Объект.СоставКомплекта.Найти(КомпонентСсылка, "Компонент");

Если Строка <> Неопределено Тогда

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

КонецЕсли;

// Удалить строки по условию — обход с конца

Индекс = Объект.СоставКомплекта.Количество() - 1;

Пока Индекс >= 0 Цикл

Если Объект.СоставКомплекта[Индекс].Количество = 0 Тогда

Объект.СоставКомплекта.Удалить(Индекс);

КонецЕсли;

Индекс = Индекс - 1;

КонецЦикла;

Объект.Записать();

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

Запись в транзакции и обработка ошибок

Если запись табличной части — часть более крупной операции (например, загрузка из файла или обмен), оборачивайте её в транзакцию. Тогда при ошибке база не останется в частично записанном состоянии:

НачатьТранзакцию();

Попытка

Объект = СсылкаНаЭлемент.ПолучитьОбъект();

Объект.СоставКомплекта.Очистить();

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

Строка = Объект.СоставКомплекта.Добавить();

Строка.Компонент = ДанныеСтроки.Компонент;

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

КонецЦикла;

Объект.Записать();

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

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

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

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

Дополнительно полезно использовать Объект.ПроверитьЗаполнение() перед записью — метод вернёт Ложь, если обязательные реквизиты строк или шапки не заполнены, и вы сможете сообщить об этом до попытки записи.

Массовая загрузка и альтернативные подходы

Для разовой массовой загрузки (например, из Excel) удобнее использовать типовую обработку «Загрузка данных из табличного документа» (доступна в конфигурациях на БСП) или написать внешнюю обработку с тем же кодом, что приведён выше, внутри цикла по строкам файла. Прямая запись в таблицы базы средствами SQL недопустима: она нарушает целостность данных и лицензионные ограничения платформы.

Если строк очень много (тысячи на элемент) или они часто меняются независимо друг от друга, табличная часть — не лучшее решение. Рассмотрите регистр сведений с измерением «элемент справочника»: он позволяет писать записи независимо, не блокируя весь элемент, и быстрее выбирается запросом.

Сравнение вариантов

Табличная часть справочника

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

Регистр сведений (подчинённый или независимый)

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

Загрузка из табличного документа (БСП)

Подходит для разового переноса данных из Excel без программирования. Ограничение — требует аккуратного сопоставления колонок и не подходит для регулярных интеграций.

Проверка результата и типичные ошибки

После записи откройте элемент в режиме предприятия и убедитесь, что строки на месте и значения корректны. Программно проверить можно запросом к табличной части: ВЫБРАТЬ ... ИЗ Справочник.Номенклатура.СоставКомплекта ГДЕ Ссылка = &Ссылка. Если запрос возвращает строки — запись прошла успешно.

Типичные ошибки
01
Добавили строку, но забыли Объект.Записать() — данные остались только в памяти и потерялись
02
Работают со ссылкой вместо объекта: Ссылка.ТабличнаяЧасть доступна только для чтения, изменить строки можно только через ПолучитьОбъект()
03
Удаление строк в цикле Для Каждого — часть строк пропускается из-за смещения индексов
04
Запись элемента без учёта того, что его параллельно редактирует пользователь — чужие изменения затираются
05
Неверные имена реквизитов табличной части — ошибка 'Поле объекта не обнаружено' при выполнении
Контрольные точки

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

Строки в форме элемента
Норма

Добавленные строки видны после переоткрытия элемента

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

Строки исчезли — запись не выполнялась или была откачена

Запрос к табличной части
Норма

Запрос возвращает ожидаемое количество строк с корректными значениями

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

Строк нет или значения пустые — проверьте имена реквизитов и вызов Записать()

Журнал регистрации
Норма

Нет ошибок за время выполнения обработки

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

Ошибки блокировок или проверки заполнения — транзакция отменена

FAQ

Можно ли записать строку в табличную часть, не записывая весь элемент?

Нет. Табличная часть физически привязана к элементу и сохраняется только вместе с ним при вызове Записать(). Если нужна независимая запись отдельных строк, используйте регистр сведений.

Почему возникает ошибка «Поле объекта не обнаружено» при обращении к строке?

Чаще всего указано неверное имя реквизита табличной части или имя самой табличной части. Откройте конфигуратор и сверьте имена в метаданных справочника — они могут отличаться от синонимов, видимых в форме.

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

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

Чем отличается РежимЗаписи у справочника и нужно ли проведение?

Справочники не проводятся — у них нет режима проведения, доступен только обычный Записать(). Проведение относится к документам. У справочника можно лишь управлять обменом данными через Объект.ОбменДанными.Загрузка = Истина, если нужно записать без проверок.

Безопасно ли ставить ОбменДанными.Загрузка = Истина при записи?

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

Итог

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

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