Табличная часть как вложенная таблица 1С 8.3: создание в конфигураторе и работа из кода

· 9 мин

Содержание

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

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

Что называют вложенной таблицей в 1С

Термин встречается в трёх местах, и путать их не стоит.

ГдеКак выглядитХранится в базе
📦 Табличная часть объектаДокумент.РеализацияТоваровУслуг.Товарыда, отдельной таблицей
🔎 Поле-вложенная таблица в запросеТовары.(Номенклатура, Количество)нет, это результат выборки
🧮 Колонка таблицы значенийколонка с типом ТаблицаЗначенийнет, только в памяти

Табличная часть решает главную задачу: у одного документа может быть сколько угодно однотипных строк. Шапка хранит дату, организацию и контрагента. Строки хранят то, чего заранее не сосчитать: позиции, суммы, сотрудников.

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

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

Структура табличной части: колонки, типы данных, свойства

Колонки табличной части в конфигураторе называются реквизитами. Каждый реквизит получает имя, синоним и тип.

Стандартные реквизиты

У любой табличной части есть два реквизита, которые платформа создаёт сама:

  • 🔢 НомерСтроки — порядковый номер, платформа пересчитывает его при добавлении, удалении и сдвиге строк;
  • 🔗 Ссылка — ссылка на объект-владелец. В коде строки она не нужна, но в запросе по табличной части через неё соединяют строки с шапкой.

Типы реквизитов

Реквизит табличной части может иметь примитивный тип (число, строка, дата, булево), ссылочный тип (ссылку на справочник, документ, перечисление) или составной тип. Табличная часть внутри табличной части в конфигураторе не создаётся — вложенность в базе только одного уровня.

Свойства, которые чаще всего настраивают

  • 📏 длина и точность для чисел: под суммы обычно 15.2, под количество 15.3;
  • ✅ Проверка заполнения — «Выдавать ошибку», если без значения строку записывать нельзя;
  • 🧭 Связи параметров выбора и Параметры выбора — чтобы в колонке «Договор» выбирались только договоры контрагента из шапки;
  • 📇 Индексировать — если по колонке часто ищут в запросах.

Само свойство табличной части Проверка заполнения со значением «Выдавать ошибку» запрещает записывать объект с пустой таблицей.

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

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

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

Обновление структуры базы требует монопольного доступа. Делайте это, когда пользователи вышли из программы, и после резервной копии.

Итоги в подвале таблицы

Чтобы под колонкой «Сумма» выводился итог, включите у элемента-таблицы свойство Подвал. У колонки укажите ПутьКДаннымПодвала = Объект.Материалы.ИтогСумма. Итог платформа считает сама, писать код не нужно.

Работа с вложенной таблицей через встроенный язык 1С

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

Добавление, обход и удаление строк

// Добавить строку
НоваяСтрока = ДокументОбъект.Материалы.Добавить();
НоваяСтрока.Номенклатура = Номенклатура;
НоваяСтрока.Количество = 2;
НоваяСтрока.Цена = 150;
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена; // 300

// Обойти все строки
Для Каждого Строка Из ДокументОбъект.Материалы Цикл
	Строка.Сумма = Строка.Количество * Строка.Цена;
КонецЦикла;

// Итог по колонке
ВсегоСумма = ДокументОбъект.Материалы.Итог("Сумма");

// Удалить строки с нулевым количеством: обход с конца
Всего = ДокументОбъект.Материалы.Количество();
Для Сч = 1 По Всего Цикл
	Строка = ДокументОбъект.Материалы[Всего - Сч];
	Если Строка.Количество = 0 Тогда
		ДокументОбъект.Материалы.Удалить(Строка);
	КонецЕсли;
КонецЦикла;

Граница цикла Всего считается один раз до начала обхода. Индексы идут от последнего к первому, поэтому удаление строки не сдвигает ещё не проверенные.

Поиск строк

  • 🔍 Найти(Значение, "Номенклатура") — первая строка с этим значением или Неопределено;
  • 📋 НайтиСтроки(Новый Структура("Номенклатура", Ном)) — массив всех подходящих строк;
  • 🔃 Сортировать("Сумма Убыв") — сортировка на месте.

Свернуть табличную часть

У табличной части нет метода Свернуть, он есть у таблицы значений. Приём практика — выгрузить, свернуть и загрузить обратно:

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

Колонки, которых нет в списке свёртки, пропадут, поэтому при загрузке они окажутся пустыми. Перечислите в параметрах все колонки, которые нужно сохранить.

Табличная часть на форме

В модуле формы Объект.Материалы — это не табличная часть, а коллекция данных формы. Добавлять, удалять и искать строки можно и на клиенте. Методы Выгрузить и Загрузить работают только на сервере, поэтому массовые операции выносите в процедуру с директивой &НаСервере.

Вложенная таблица значений в памяти

Если нужна многоуровневая структура только на время расчёта, колонку таблицы значений делают типа ТаблицаЗначений:

Заказы = Новый ТаблицаЗначений;
Заказы.Колонки.Добавить("Заказ");
Заказы.Колонки.Добавить("Строки", Новый ОписаниеТипов("ТаблицаЗначений"));

СтрокаЗаказа = Заказы.Добавить();
СтрокаЗаказа.Заказ = ДокументСсылка;
СтрокаЗаказа.Строки = ДокументСсылка.Товары.Выгрузить();

В базу такую конструкцию не записать. Хранить её можно только сериализованной, например в реквизите типа ХранилищеЗначения.

Вложенные таблицы в запросах

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

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

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	ВыборкаТоваров = Выборка.Товары.Выбрать();
	Пока ВыборкаТоваров.Следующий() Цикл
		// ВыборкаТоваров.Номенклатура, ВыборкаТоваров.Сумма
	КонецЦикла;
КонецЦикла;

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

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

"ВЫБРАТЬ РАЗЛИЧНЫЕ
|	Товары.Ссылка КАК Документ
|ИЗ
|	Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
|	Товары.Номенклатура = &Номенклатура"

РАЗЛИЧНЫЕ здесь обязательно: если товар встречается в документе в двух строках, без него документ попадёт в результат дважды.

Где хранить повторяющиеся данные?

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

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

  • 🧾 В 1С:Бухгалтерии 3.0 у документа «Реализация (акты, накладные, УПД)» товары и услуги лежат в разных табличных частях — Товары и Услуги. Поэтому на форме это две закладки.
  • 📥 У поступления товаров и услуг то же разделение.
  • 📒 У плана счетов есть стандартная табличная часть ВидыСубконто: в ней перечислены аналитики счёта.
  • 💼 У плана видов расчёта платформа создаёт табличные части БазовыеВидыРасчета, ВедущиеВидыРасчета и ВытесняющиеВидыРасчета.

Что делает пользователь с табличной частью

Пользователю не нужен конфигуратор, чтобы работать со строками:

  • ➕ Ins — добавить строку, F9 — скопировать текущую, Del — удалить;
  • 📑 команда «Подбор» во многих документах открывает список номенклатуры и добавляет сразу несколько позиций;
  • 📤 Ещё → Вывести список… выводит строки в табличный документ, его можно сохранить в Excel;
  • 📥 в части документов БП 3.0 на командной панели таблицы товаров есть загрузка строк из файла.

Как ускорить работу с большими табличными частями

В базе каждая табличная часть — отдельная таблица СУБД с именем вида _Document123_VT456. При записи объекта платформа записывает табличные части целиком, даже если изменилась одна строка. Отсюда главные правила.

  1. 📉 Не копите в одном документе десятки тысяч строк. Запись идёт дольше, документ дольше держит блокировку. Разбейте операцию на несколько документов, например по складам или по дням.
  2. 🚫 Не читайте строки через ссылку в цикле. ДокументСсылка.Товары загружает из базы весь объект целиком. Для сотни документов это сотня полных чтений вместо одного запроса.
  3. 🧮 Считайте суммы запросом к табличной части с СУММА и СГРУППИРОВАТЬ ПО, а не обходом строк.
  4. 🔁 Не вызывайте Записать() внутри цикла по строкам. Измените все строки, потом запишите объект один раз.
  5. 📇 Включите индекс у колонки, если по ней регулярно отбирают в запросах. Каждый индекс замедляет запись, поэтому индексируйте только то, по чему действительно ищут.
  6. 🖥️ На форме тяжёлые пересчёты по всем строкам делайте одним вызовом сервера, а не серверным вызовом на каждую строку.

Частые ошибки при работе с вложенными таблицами

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

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

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

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