В практике разработки на платформе 1С:Предприятие часто возникает задача отображения сложных иерархических структур. Классический пример — производство, где в рамках одного документа нужно отразить несколько замесов теста, и для каждого замеса указать свой состав ингредиентов и список выпущенной продукции. Платформа 1С не поддерживает «вложенные» табличные части на уровне метаданных, однако существует несколько проверенных способов реализовать такую логику. Разберем их подробно.
Это стандартный промышленный подход, который используется в большинстве типовых конфигураций (например, ERP или ЗУП). Суть метода заключается в том, что мы создаем две или более «плоских» табличных части и связываем их программно с помощью специального реквизита — ключа связи.
Проанализируем шаги реализации этого метода:
Тесто) создадим реквизит КлючСвязи с типом Число или УникальныйИдентификатор.Состав и Выпуск) создадим реквизит с таким же именем и типом.Рассмотрим пример программной фильтрации. Для этого нам понадобится обработчик события ПриАктивизацииСтроки у элемента формы, отображающего основную таблицу:
&НаКлиенте
Процедура ТестоПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Тесто.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Элементы.Состав.ОтборСтрок = Новый ФиксированнаяСтруктура("КлючСвязи", -1);
Иначе
Элементы.Состав.ОтборСтрок = Новый ФиксированнаяСтруктура("КлючСвязи", ТекущиеДанные.КлючСвязи);
КонецЕсли;
КонецПроцедуры
Важный нюанс: при добавлении новой строки в основную таблицу необходимо генерировать новый уникальный ключ связи. Если вы используете число, можно вычислять его как максимальный существующий ключ + 1. Если УникальныйИдентификатор — использовать встроенную функцию платформы.
При использовании связанных таблиц мы должны вручную обеспечить целостность данных. Проанализируем ситуацию: что произойдет, если пользователь удалит строку с замесом теста? Подчиненные строки в таблице состава останутся «сиротами» и будут занимать место в базе, а также могут исказить отчеты.
Для решения этой проблемы необходимо прописать логику в событии ПередУдалением или ПослеУдаления основной таблицы. Выясним, как это выглядит в коде:
&НаКлиенте
Процедура ТестоПередУдалением(Элемент, Отказ)
ТекущиеДанные = Элементы.Тесто.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
КлючДляУдаления = ТекущиеДанные.КлючСвязи;
// Находим и удаляем все связанные строки в подчиненной таблице
МассивСтрокДляУдаления = Объект.Состав.НайтиСтроки(Новый Структура("КлючСвязи", КлючДляУдаления));
Для Каждого СтрокаСостава Из МассивСтрокДляУдаления Цикл
Объект.Состав.Удалить(СтрокаСостава);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Аналогично стоит поступить и с копированием. При копировании строки документа стандартными средствами 1С, ключи связи в новой строке будут идентичны старым, что приведет к перемешиванию данных. Разберем по шагам: в событии ПриКопировании или через специализированную команду копирования нужно сгенерировать новый КлючСвязи для новой строки-родителя и продублировать все строки-потомки с этим новым ключом.
Если интерфейс с двумя таблицами кажется пользователю неудобным, мы можем использовать ДеревоЗначений. Это позволяет отображать данные в иерархическом виде с возможностью сворачивания и разворачивания узлов (как в справочниках с группами).
Проанализируем особенности этого подхода:
ДеревоЗначений не может быть реквизитом документа. Данные всё равно придется хранить в плоских табличных частях (как в первом способе).Этот метод сложнее в реализации, так как требует написания процедур синхронизации данных между элементами формы и объектом документа, но он обеспечивает максимально «лаконичный» и современный интерфейс.
Как упоминалось в обсуждении, иногда целесообразно вынести состав (вложенную часть) в отдельный справочник. Это особенно полезно, если одни и те же составы замесов повторяются из дня в день.
Выясним преимущества этого метода:
Однако, если состав каждого замеса уникален и меняется «на лету» в зависимости от влажности муки или температуры в цехе, то лучше оставить данные внутри документа, чтобы не забивать справочник тысячами разовых записей.
Чтобы не перегружать форму документа множеством таблиц, можно использовать модальные или вспомогательные формы. Разберем, как это работает: В основной таблице замесов создается кнопка (или колонка с гиперссылкой) «Редактировать состав». При нажатии открывается отдельная форма, в которую передается текущий набор данных. Пользователь вводит состав в отдельном окне, нажимает «ОК», и данные возвращаются в скрытую табличную часть основного документа.
Это позволяет сконцентрировать внимание пользователя на конкретной задаче и избежать ошибок при случайном переключении строк в основной таблице.
Мы рассмотрели несколько вариантов реализации иерархии в документах 1С. Самым надежным и гибким является использование двух табличных частей со связью по ключевому полю. Проанализировав требования к удобству и объему данных, вы можете дополнить этот механизм программной фильтрацией или использованием деревьев значений для визуализации. Главное — помнить о поддержании целостности связей при удалении и копировании строк.