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

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

Как обратиться к табличной части справочника в 1С

Как обратиться к табличной части справочника 1С 8.3: обращение из модуля объекта, формы, запроса. Примеры кода, типичные ошибки и ответы на вопросы.

Табличная часть справочника в 1С — это коллекция строк, хранящаяся внутри элемента справочника и связанная с ним по ссылке. Чтобы обратиться к ней, нужно сначала получить объект элемента (а не просто ссылку), а затем работать с табличной частью как с коллекцией строк через точку: Объект.ИмяТабличнойЧасти.

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

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

Что такое табличная часть справочника и где она хранится

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

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

Важное ограничение: табличная часть существует только внутри своего владельца. Нельзя создать строку табличной части, не привязанную к элементу справочника, и нельзя сослаться на строку извне иначе как через пару «ссылка + номер строки» (или уникальный ключ строки).

Обращение к табличной части из модуля объекта

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

Процедура ПередЗаписью(Отказ)

Для Каждого СтрокаСостава Из Состав Цикл

Если СтрокаСостава.Количество <= 0 Тогда

Отказ = Истина;

Сообщить("В строке " + СтрокаСостава.НомерСтроки + " не указано количество");

КонецЕсли;

КонецЦикла;

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

Здесь Состав — имя табличной части. Коллекция поддерживает стандартные методы: Количество(), Добавить(), Удалить(Строка), Очистить(), Найти(Значение, ИмяКолонки), НайтиСтроки(Отбор), Итог(ИмяКолонки), Выгрузить() для получения таблицы значений.

Метод Выгрузить() особенно полезен, когда нужно передать данные в запрос или выполнить свёртку: ТЗ = Состав.Выгрузить(); ТЗ.Свернуть("Номенклатура", "Количество");.

Обращение из внешнего кода: чтение и изменение

Из внешнего модуля (общего модуля, обработки, модуля документа) работа начинается со ссылки на элемент. Для чтения достаточно обратиться через ссылку — платформа сама подгрузит данные:

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

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

Сообщить(Строка.Материал);

КонецЦикла;

Для изменения обязательно получаем объект, иначе изменения не сохранятся:

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

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

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

НоваяСтрока.Материал = Справочники.Материалы.НайтиПоНаименованию("Сталь");

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

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

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

Обращение к табличной части из формы

На управляемой форме элемента справочника табличная часть обычно представлена как реквизит формы типа «ДанныеФормыКоллекция». Обращение идёт через объект формы: Объект.Состав, где Объект — основной реквизит формы.

&НаКлиенте

Процедура ЗаполнитьПоУмолчанию(Команда)

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

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

&НаСервере

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

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

// добавление строк

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

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

Текущая строка табличного поля на форме доступна через Элементы.Состав.ТекущиеДанные. Это объект ДанныеФормыЭлементКоллекции — его можно читать и изменять на клиенте, но у него нет методов коллекции.

Получение данных табличной части запросом

Запрос — оптимальный способ читать табличные части многих элементов сразу. В языке запросов табличная часть адресуется через точку: Справочник.Номенклатура.Состав.

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

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

"ВЫБРАТЬ

| Состав.Ссылка КАК Элемент,

| Состав.Материал,

| Состав.Количество

|ИЗ

| Справочник.Номенклатура.Состав КАК Состав

|ГДЕ

| Состав.Ссылка = &Ссылка";

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

Выборка = Запрос.Выполнить().Выбрать();

Запрос работает быстрее цикла по объектам, потому что не поднимает в память сами элементы справочника. Это особенно заметно при выборке по сотням и тысячам элементов. Обратная сторона: запрос только читает данные, изменить табличную часть через запрос нельзя.

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

Сравнение способов доступа

Через ссылку в цикле

Подходит для чтения одного-двух элементов. Просто, но медленно при массовой обработке.

ПолучитьОбъект() + Записать()

Единственный корректный способ изменения. Выполняет проверки логики, но перезаписывает элемент целиком.

Запрос

Лучший вариант для чтения больших объёмов и отчётов. Не позволяет изменять данные.

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

Самая частая ошибка — попытка изменить табличную часть через ссылку: Ссылка.Состав.Добавить(). Код может даже не упасть сразу, но изменения не сохранятся, потому что ссылка не имеет метода Записать() для объекта.

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

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

Типичные ошибки
01
Изменение через ссылку без ПолучитьОбъект() — изменения теряются без ошибки или падает исключение
02
Удаление строк внутри цикла Для Каждого — часть строк пропускается из-за сдвига индексов
03
Пропущенный Записать() после изменений — данные остаются только в памяти
04
Вызов Найти() или Выгрузить() на клиенте в управляемой форме — ошибка «Метод объекта не обнаружен»
05
Обращение к несуществующему имени табличной части — опечатка выявляется только в runtime

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

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

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

Проверка = ОбъектЭлемента.Ссылка.Состав.Количество();

Если Проверка <> ОжидаемоеКоличество Тогда

ВызватьИсключение "Записано строк: " + Проверка;

КонецЕсли;

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

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

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

Количество строк после записи
Норма

Совпадает с ожидаемым числом

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

Меньше ожидаемого — часть строк не добавилась или удалилась

Данные в режиме предприятия
Норма

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

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

Форма пуста — запись не выполнилась или открыта другая версия элемента

Результат запроса
Норма

Запрос возвращает строки табличной части

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

Пустая выборка — проверьте имя табличной части и параметр отбора

Итог

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

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

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

Можно ли обратиться к табличной части справочника, не открывая объект?

Да, для чтения. Через ссылку (Ссылка.ИмяТабличнойЧасти) или запросом данные доступны без вызова ПолучитьОбъект(). Но изменить и сохранить строки без получения объекта нельзя — ссылка предназначена только для чтения.

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

Чаще всего имя табличной части указано с опечаткой или не совпадает с именем в конфигураторе. Откройте свойства справочника в конфигураторе на закладке «Данные» и сверьте точное имя. Также ошибка возникает, если обратиться к табличной части у переменной, которая содержит не ссылку на справочник, а другой тип.

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

Используйте метод Найти(Значение, "ИмяКолонки") для первой подходящей строки или НайтиСтроки(Новый Структура("Колонка", Значение)) для массива всех совпадений. Оба метода доступны на сервере и в модуле объекта, но не на клиенте управляемой формы.

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

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

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

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

Можно ли выгрузить табличную часть в таблицу значений?

Да, методом Выгрузить(): ТЗ = Объект.Состав.Выгрузить();. Полученную таблицу значений удобно сворачивать, сортировать, передавать в запрос как временную таблицу или использовать для сравнения «было/стало». Метод доступен на сервере и в толстом клиенте.