Табличная часть объекта 1С: как устроена, как добавить в конфигураторе и обработать кодом

· 10 мин

Содержание

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

Типичная ситуация: бухгалтер просит добавить в поступление колонку «Номер партии», а программист должен решить, где её хранить — в реквизите документа или в строке табличной части. Ответ зависит от того, одно значение на документ или своё на каждую строку. Механика табличных частей задаётся платформой 8.3, поэтому она одинакова для БП, ЗУП, УТ и самописных конфигураций.

Что такое табличная часть и чем она отличается от реквизита

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

У каждой табличной части есть два стандартных реквизита, их не нужно создавать:

  • 🔢 НомерСтроки — порядковый номер строки, начинается с 1;
  • 🔗 Ссылка — ссылка на объект-владелец (документ или элемент справочника).

В базе данных табличная часть лежит в отдельной таблице. Её строки связаны с основной таблицей объекта по ссылке и упорядочены по номеру строки. Отсюда два практических следствия:

  1. Табличная часть не живёт отдельно от объекта. Удалили документ — удалились и его строки.
  2. Записать одну строку нельзя. При записи объекта платформа перезаписывает всю табличную часть целиком.

Табличная часть и таблица значений

Их часто путают, потому что методы похожи.

ПризнакТабличная частьТаблица значений
Где описанаВ конфигураторе, у объекта метаданныхСоздаётся кодом: Новый ТаблицаЗначений
Хранится в базеДа, вместе с объектомНет, только в памяти
Набор колонокЗадан в конфигуратореЛюбой, добавляется кодом
Индексы для поискаНетЕсть: Индексы.Добавить()
Свернуть строкиНет методаЕсть: Свернуть()

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

Виды табличных частей: у каких объектов они бывают

Табличную часть можно добавить не к любому объекту метаданных. Она есть у прикладных объектов, которые хранят «шапку» и строки:

  • 📄 документы — товары, услуги, оплаты;
  • 📚 справочники — например, контактные лица, дополнительные реквизиты;
  • 🧾 планы счетов — субконто счета (это отдельная стандартная табличная часть ВидыСубконто);
  • 📊 планы видов характеристик, планы видов расчёта, планы обмена;
  • 🔄 бизнес-процессы и задачи;
  • 🛠 обработки и отчёты — здесь табличная часть не хранится в базе, она живёт, пока открыта форма или существует объект обработки.

У регистров, констант, перечислений и журналов документов табличных частей нет. Регистр сам по себе набор записей, его «строки» — это записи регистра.

Пользовательские и стандартные

По происхождению табличные части делятся на два вида:

ВидКто создаётПример
ПользовательскаяРазработчик в конфигуратореТовары в документе
СтандартнаяПлатформаВидыСубконто у плана счетов, БазовыеВидыРасчета у плана видов расчёта

Особенность иерархических справочников

У табличной части иерархического справочника есть свойство Использование. Оно задаёт, у кого будут строки: только у элементов, только у групп или у тех и других. По умолчанию — для элемента. Если в группе табличная часть не видна, первым делом проверьте это свойство.

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

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

Шаг 1. Добавить табличную часть

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

Шаг 2. Описать колонки

  1. Выделите новую табличную часть и снова нажмите добавление — появится реквизит табличной части.
  2. Задайте имя и тип: Номенклатура — СправочникСсылка.Номенклатура, Количество — Число (15, 3), Сумма — Число (15, 2).
  3. При необходимости задайте свойства колонки: проверку заполнения, выбор по связям параметров, индексирование.

Шаг 3. Вывести на форму

  1. Откройте форму объекта на вкладке Формы.
  2. В правом верхнем окне Реквизиты раскройте Объект и найдите табличную часть.
  3. Перетащите её мышью в дерево элементов слева. Платформа создаст элемент Таблица с колонками.
  4. Лишние колонки удалите из элементов формы — из данных объекта они не исчезнут.

Шаг 4. Обновить конфигурацию базы данных

Нажмите F7 или Конфигурация → Обновить конфигурацию базы данных. Новая табличная часть — это новая таблица в базе, поэтому изменение структуры требует монопольного доступа. В клиент-серверной базе пользователи, скорее всего, должны будут выйти.

Перед обновлением структуры рабочей базы сделайте резервную копию: Администрирование → Выгрузить информационную базу в конфигураторе или средствами СУБД.

Если нужна табличная часть в расширении

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

Работа с табличными частями на встроенном языке

Из модуля объекта табличная часть доступна по имени, из модуля формы — через основной реквизит Объект. На сервере это ТабличнаяЧасть, на форме — ДанныеФормыКоллекция. Набор основных методов у них близкий.

Основные методы

МетодЧто делает
Добавить()Добавляет строку в конец, возвращает её
Вставить(Индекс)Вставляет строку в позицию
Удалить(Строка)Удаляет строку (по строке или индексу)
Очистить()Удаляет все строки
Количество()Число строк
Итог("Сумма")Сумма по колонке
НайтиСтроки(Структура)Массив строк по отбору
Выгрузить() / Загрузить()В таблицу значений и обратно
ВыгрузитьКолонку("Имя")Массив значений одной колонки
Сортировать("Колонка Убыв")Сортировка строк

Индекс строки начинается с 0, а НомерСтроки — с 1. На этом часто ошибаются.

Заполнить табличную часть кодом

Пример для модуля объекта документа: перенести строки из таблицы значений и посчитать сумму.

Процедура ЗаполнитьТовары(ТаблицаИсточник) Экспорт

	Товары.Очистить();

	Для Каждого СтрокаИсточника Из ТаблицаИсточник Цикл
		НоваяСтрока = Товары.Добавить();
		НоваяСтрока.Номенклатура = СтрокаИсточника.Номенклатура;
		НоваяСтрока.Количество   = СтрокаИсточника.Количество;
		НоваяСтрока.Цена         = СтрокаИсточника.Цена;
		НоваяСтрока.Сумма        = НоваяСтрока.Количество * НоваяСтрока.Цена;
	КонецЦикла;

	СуммаДокумента = Товары.Итог("Сумма");

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

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

Удалить строки по условию

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

КоличествоСтрок = Товары.Количество();
Для Сч = 1 По КоличествоСтрок Цикл
	Строка = Товары[КоличествоСтрок - Сч];
	Если Строка.Количество = 0 Тогда
		Товары.Удалить(Строка);
	КонецЕсли;
КонецЦикла;

Второй способ — собрать строки через НайтиСтроки(Новый Структура("Количество", 0)) и удалить каждую из полученного массива.

Свернуть одинаковые строки

У табличной части нет метода Свернуть(), поэтому делают через таблицу значений:

ТЗ = Товары.Выгрузить();
ТЗ.Свернуть("Номенклатура, Цена", "Количество, Сумма");
Товары.Загрузить(ТЗ);

Событие на форме при изменении колонки

Чтобы пересчитать сумму при вводе количества, выделите колонку ТоварыКоличество в элементах формы, на палитре свойств найдите событие ПриИзменении и создайте обработчик:

&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
	ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
	ТекущиеДанные.Сумма = ТекущиеДанные.Количество * ТекущиеДанные.Цена;
КонецПроцедуры

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

К строкам обращаются как к отдельной таблице через точку:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Товары.НомерСтроки,
|	Товары.Номенклатура,
|	Товары.Количество,
|	Товары.Сумма
|ИЗ
|	Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
|	Товары.Ссылка = &Ссылка
|УПОРЯДОЧИТЬ ПО
|	Товары.НомерСтроки";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Выборка = Запрос.Выполнить().Выбрать();

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

Типичные ошибки при работе с табличными частями

Диагностика: выберите симптом

Примеры табличных частей в типовых конфигурациях

Разобраться в чужой табличной части проще всего на типовых документах. Точное имя табличной части смотрите в конфигураторе: откройте объект и раскройте узел Табличные части на вкладке Данные. В режиме 1С:Предприятие ориентируйтесь по вкладкам формы.

Что обычно лежит в табличных частях типовых решений:

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

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

Проверьте себя
Где хранить номер договора, если он один на весь документ?
Какой индекс у первой строки табличной части?
Есть ли у табличной части метод Свернуть()?

Оптимизация: когда табличная часть тормозит

Табличная часть удобна до определённого объёма. Документ на 20 000 строк будет открываться и записываться заметно медленнее, потому что при каждой записи все строки удаляются и вставляются заново.

Что помогает на практике:

  • 📦 Не раздувайте одну табличную часть. Если строки нужны только для отчёта, а не для учёта, храните их в регистре сведений, а в документе — итоги.
  • 🔎 Не разыменовывайте ссылки в цикле. Каждое Строка.Номенклатура.ЕдиницаИзмерения в цикле — отдельное обращение к базе. Получите нужные поля одним запросом по табличной части с соединением.
  • ⚡ Ищите по таблице значений с индексом. НайтиСтроки по табличной части перебирает строки. Для частого поиска выгрузите её, добавьте индекс ТЗ.Индексы.Добавить("Номенклатура") и ищите в таблице значений.
  • 🗂 Индексируйте колонку, по которой фильтруете в запросах. У реквизита табличной части есть свойство Индексировать. Оно полезно, если вы часто ищете документы по значению в строках, например по номенклатуре.
  • 🖥 Не гоняйте табличную часть между клиентом и сервером. Каждый серверный вызов из формы передаёт данные формы. Заполнение и пересчёт сотен строк делайте в одной процедуре &НаСервере, а не построчно.
  • 📤 Используйте ВыгрузитьКолонку, когда нужен только массив значений одной колонки, например для параметра запроса В (&Номенклатура).

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

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

Сколько строк может быть в табличной части?
Жёсткого лимита, с которым сталкиваются на практике, нет. Ограничивает производительность: документы на десятки тысяч строк долго открываются и записываются, такие данные лучше разносить по нескольким документам или регистру.
Можно ли переименовать табличную часть, если в ней уже есть данные?
Да, данные сохранятся: платформа связывает метаданные с таблицей по внутреннему идентификатору, а не по имени. Но придётся исправить все обращения в коде, запросах и отчётах, иначе появятся ошибки «Поле объекта не обнаружено».
Чем отличается Объект.Товары на форме от Товары в модуле объекта?
На форме это данные формы (ДанныеФормыКоллекция), доступные на клиенте. В модуле объекта — табличная часть прикладного объекта на сервере. Методы похожи, но, например, Выгрузить() в таблицу значений доступен только на сервере.
Как сделать, чтобы документ не записывался без строк?
Установите у табличной части свойство проверки заполнения в значение «Выдавать ошибку». Тогда при проведении документа (у непроводимых объектов — при записи) платформа не пропустит пустую табличную часть и покажет сообщение пользователю.
Можно ли сделать табличную часть внутри табличной части?
Нет, вложенных табличных частей платформа не поддерживает. Обычно делают вторую табличную часть и связывают строки ключом — например, колонкой КлючСтроки с уникальным идентификатором.