Табличная часть как вложенная таблица 1С 8.3: создание в конфигураторе и работа из кода
Содержание
Вложенная таблица в 1С — это набор строк, который принадлежит одному объекту. Чаще всего это табличная часть документа или справочника: список товаров в реализации, состав комплекта, перечень сотрудников в приказе. Создают её в конфигураторе на закладке Данные объекта, а из кода обращаются как Объект.ИмяТабличнойЧасти.
Второе значение термина — поле запроса, в котором для каждой строки результата лежит своя маленькая таблица. Третье — колонка таблицы значений с типом ТаблицаЗначений. Ниже разобраны все три случая: как такую таблицу создать, использовать во встроенном языке и не потерять на ней производительность. Всё сказанное относится к платформе 8.3 и управляемым формам.
Что называют вложенной таблицей в 1С
Термин встречается в трёх местах, и путать их не стоит.
| Где | Как выглядит | Хранится в базе |
|---|---|---|
| 📦 Табличная часть объекта | Документ.РеализацияТоваровУслуг.Товары | да, отдельной таблицей |
| 🔎 Поле-вложенная таблица в запросе | Товары.(Номенклатура, Количество) | нет, это результат выборки |
| 🧮 Колонка таблицы значений | колонка с типом ТаблицаЗначений | нет, только в памяти |
Табличная часть решает главную задачу: у одного документа может быть сколько угодно однотипных строк. Шапка хранит дату, организацию и контрагента. Строки хранят то, чего заранее не сосчитать: позиции, суммы, сотрудников.
Табличные части есть у справочников, документов, планов видов характеристик, планов счетов, планов видов расчёта, планов обмена, бизнес-процессов и задач. У регистров табличных частей нет: регистр сам по себе таблица.
Если строки нужно хранить независимо от объекта, читать по периодам или отбирать по измерениям — это задача регистра сведений, а не табличной части.
Структура табличной части: колонки, типы данных, свойства
Колонки табличной части в конфигураторе называются реквизитами. Каждый реквизит получает имя, синоним и тип.
Стандартные реквизиты
У любой табличной части есть два реквизита, которые платформа создаёт сама:
- 🔢
НомерСтроки— порядковый номер, платформа пересчитывает его при добавлении, удалении и сдвиге строк; - 🔗
Ссылка— ссылка на объект-владелец. В коде строки она не нужна, но в запросе по табличной части через неё соединяют строки с шапкой.
Типы реквизитов
Реквизит табличной части может иметь примитивный тип (число, строка, дата, булево), ссылочный тип (ссылку на справочник, документ, перечисление) или составной тип. Табличная часть внутри табличной части в конфигураторе не создаётся — вложенность в базе только одного уровня.
Свойства, которые чаще всего настраивают
- 📏 длина и точность для чисел: под суммы обычно 15.2, под количество 15.3;
- ✅
Проверка заполнения— «Выдавать ошибку», если без значения строку записывать нельзя; - 🧭
Связи параметров выбораиПараметры выбора— чтобы в колонке «Договор» выбирались только договоры контрагента из шапки; - 📇
Индексировать— если по колонке часто ищут в запросах.
Само свойство табличной части Проверка заполнения со значением «Выдавать ошибку» запрещает записывать объект с пустой таблицей.
Как создать вложенную таблицу в конфигураторе 1С
Типовую конфигурацию на поддержке лучше дорабатывать расширением: так обновления ставятся без сравнения и объединения. Новую табличную часть в расширении можно добавить к заимствованному объекту. В собственной конфигурации порядок такой.
- Откройте конфигуратор и дерево метаданных:
Конфигурация → Открыть конфигурацию. - Двойным щелчком откройте нужный документ или справочник.
- Перейдите на закладку
Данные. - В блоке «Табличные части» нажмите кнопку добавления. Задайте имя латиницей или кириллицей без пробелов, например
Материалы. - Выделите новую табличную часть и добавьте в неё реквизиты:
Номенклатура,Количество,Цена,Сумма. - Задайте каждому реквизиту тип и свойства из предыдущего раздела.
- Откройте форму объекта на закладке
Формы. Перетащите табличную часть из панели реквизитов формы (Объект → Материалы) в дерево элементов. Платформа создаст элемент «Таблица» с колонками. - Сохраните конфигурацию и выполните
Конфигурация → Обновить конфигурацию базы данных(F7).
Обновление структуры базы требует монопольного доступа. Делайте это, когда пользователи вышли из программы, и после резервной копии.
Итоги в подвале таблицы
Чтобы под колонкой «Сумма» выводился итог, включите у элемента-таблицы свойство Подвал. У колонки укажите ПутьКДаннымПодвала = Объект.Материалы.ИтогСумма. Итог платформа считает сама, писать код не нужно.
Работа с вложенной таблицей через встроенный язык 1С
На сервере табличная часть объекта — это коллекция строк со своим набором методов. Ниже приёмы, которые нужны в каждой второй доработке.
Добавление, обход и удаление строк
// Добавить строку
НоваяСтрока = ДокументОбъект.Материалы.Добавить();
НоваяСтрока.Номенклатура = Номенклатура;
НоваяСтрока.Количество = 2;
НоваяСтрока.Цена = 150;
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена; // 300
// Обойти все строки
Для Каждого Строка Из ДокументОбъект.Материалы Цикл
Строка.Сумма = Строка.Количество * Строка.Цена;
КонецЦикла;
// Итог по колонке
ВсегоСумма = ДокументОбъект.Материалы.Итог("Сумма");
// Удалить строки с нулевым количеством: обход с конца
Всего = ДокументОбъект.Материалы.Количество();
Для Сч = 1 По Всего Цикл
Строка = ДокументОбъект.Материалы[Всего - Сч];
Если Строка.Количество = 0 Тогда
ДокументОбъект.Материалы.Удалить(Строка);
КонецЕсли;
КонецЦикла;
Граница цикла Всего считается один раз до начала обхода. Индексы идут от последнего к первому, поэтому удаление строки не сдвигает ещё не проверенные.
Поиск строк
- 🔍
Найти(Значение, "Номенклатура")— первая строка с этим значением илиНеопределено; - 📋
НайтиСтроки(Новый Структура("Номенклатура", Ном))— массив всех подходящих строк; - 🔃
Сортировать("Сумма Убыв")— сортировка на месте.
Свернуть табличную часть
У табличной части нет метода Свернуть, он есть у таблицы значений. Приём практика — выгрузить, свернуть и загрузить обратно:
ТЗ = ДокументОбъект.Материалы.Выгрузить();
ТЗ.Свернуть("Номенклатура, Цена", "Количество, Сумма");
ДокументОбъект.Материалы.Загрузить(ТЗ);
Колонки, которых нет в списке свёртки, пропадут, поэтому при загрузке они окажутся пустыми. Перечислите в параметрах все колонки, которые нужно сохранить.
Табличная часть на форме
В модуле формы Объект.Материалы — это не табличная часть, а коллекция данных формы. Добавлять, удалять и искать строки можно и на клиенте. Методы Выгрузить и Загрузить работают только на сервере, поэтому массовые операции выносите в процедуру с директивой &НаСервере.
Вложенная таблица значений в памяти
Если нужна многоуровневая структура только на время расчёта, колонку таблицы значений делают типа ТаблицаЗначений:
Заказы = Новый ТаблицаЗначений;
Заказы.Колонки.Добавить("Заказ");
Заказы.Колонки.Добавить("Строки", Новый ОписаниеТипов("ТаблицаЗначений"));
СтрокаЗаказа = Заказы.Добавить();
СтрокаЗаказа.Заказ = ДокументСсылка;
СтрокаЗаказа.Строки = ДокументСсылка.Товары.Выгрузить();
В базу такую конструкцию не записать. Хранить её можно только сериализованной, например в реквизите типа ХранилищеЗначения.
Вложенные таблицы в запросах
Язык запросов умеет вернуть табличную часть как поле. Для каждого документа в результате будет одна строка, а в поле Товары — его строки.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка КАК Ссылка,
| Реализация.Товары.(
| Номенклатура,
| Количество,
| Сумма
| ) КАК Товары
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Дата МЕЖДУ &Начало И &Конец";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ВыборкаТоваров = Выборка.Товары.Выбрать();
Пока ВыборкаТоваров.Следующий() Цикл
// ВыборкаТоваров.Номенклатура, ВыборкаТоваров.Сумма
КонецЦикла;
КонецЦикла;
Значение поля Выборка.Товары — это результат запроса, поэтому у него вызывается Выбрать(). Если весь результат выгрузить в таблицу значений, в колонке Товары окажутся таблицы значений.
Такой вид удобен для печатных форм: шапка и строки приходят одним запросом. Для отборов, группировок и соединений обращайтесь к табличной части как к самостоятельной таблице:
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Товары.Ссылка КАК Документ
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Номенклатура = &Номенклатура"
РАЗЛИЧНЫЕ здесь обязательно: если товар встречается в документе в двух строках, без него документ попадёт в результат дважды.
КлючСвязи типа число, во второй та же колонка указывает на родительскую строку.ТаблицаЗначений, в базу не записывается.Примеры вложенных таблиц в типовых конфигурациях
В типовых решениях табличные части повсюду. Несколько примеров, которые видит каждый пользователь.
- 🧾 В 1С:Бухгалтерии 3.0 у документа «Реализация (акты, накладные, УПД)» товары и услуги лежат в разных табличных частях —
ТоварыиУслуги. Поэтому на форме это две закладки. - 📥 У поступления товаров и услуг то же разделение.
- 📒 У плана счетов есть стандартная табличная часть
ВидыСубконто: в ней перечислены аналитики счёта. - 💼 У плана видов расчёта платформа создаёт табличные части
БазовыеВидыРасчета,ВедущиеВидыРасчетаиВытесняющиеВидыРасчета.
Что делает пользователь с табличной частью
Пользователю не нужен конфигуратор, чтобы работать со строками:
- ➕
Ins— добавить строку,F9— скопировать текущую,Del— удалить; - 📑 команда «Подбор» во многих документах открывает список номенклатуры и добавляет сразу несколько позиций;
- 📤
Ещё → Вывести список…выводит строки в табличный документ, его можно сохранить в Excel; - 📥 в части документов БП 3.0 на командной панели таблицы товаров есть загрузка строк из файла.
Как ускорить работу с большими табличными частями
В базе каждая табличная часть — отдельная таблица СУБД с именем вида _Document123_VT456. При записи объекта платформа записывает табличные части целиком, даже если изменилась одна строка. Отсюда главные правила.
- 📉 Не копите в одном документе десятки тысяч строк. Запись идёт дольше, документ дольше держит блокировку. Разбейте операцию на несколько документов, например по складам или по дням.
- 🚫 Не читайте строки через ссылку в цикле.
ДокументСсылка.Товарызагружает из базы весь объект целиком. Для сотни документов это сотня полных чтений вместо одного запроса. - 🧮 Считайте суммы запросом к табличной части с
СУММАиСГРУППИРОВАТЬ ПО, а не обходом строк. - 🔁 Не вызывайте
Записать()внутри цикла по строкам. Измените все строки, потом запишите объект один раз. - 📇 Включите индекс у колонки, если по ней регулярно отбирают в запросах. Каждый индекс замедляет запись, поэтому индексируйте только то, по чему действительно ищут.
- 🖥️ На форме тяжёлые пересчёты по всем строкам делайте одним вызовом сервера, а не серверным вызовом на каждую строку.
Частые ошибки при работе с вложенными таблицами
Для Каждого сдвигает коллекцию. Обходите строки с конца по индексу, как в примере выше.РАЗЛИЧНЫЕ. Добавьте РАЗЛИЧНЫЕ или сгруппируйте по ссылке.Свернуть перечислены не все колонки. Добавьте недостающие в группировочные или суммируемые.ПолучитьОбъект(), измените строки и вызовите Записать().Ещё одна ловушка — смена типа реквизита табличной части в рабочей базе. При обновлении структуры платформа попытается преобразовать старые значения, а то, что не преобразуется, станет пустым. Перед такой правкой выгрузите информационную базу в файл.
Частые вопросы
Сколько табличных частей можно добавить к документу?
Можно ли сделать табличную часть внутри табличной части?
Чем табличная часть отличается от таблицы значений?
Как перенести строки из одного документа в другой?
Загрузить. Колонки с одинаковыми именами заполнятся автоматически.