Как реализовать структуру «таблица в таблице» в документе 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке сложных документов в 1С:Предприятие часто возникает задача отображения иерархических данных. Классический пример: список документов-оснований, где для каждого документа нужно указать свой перечень работ и их количество. Прямой поддержки «вложенных» табличных частей на уровне базы данных в 1С не существует, однако есть проверенные архитектурные паттерны, позволяющие добиться нужного результата. В этой статье мы подробно разберем, как реализовать механизм «Мастер-Деталь» и какие альтернативы существуют для визуализации таких данных.

Метод 1: Связь двух табличных частей через ключ (Master-Detail)

Это наиболее стандартный и надежный способ для управляемых форм. Суть заключается в создании двух плоских табличных частей, которые логически связаны между собой уникальным идентификатором. Рассмотрим этот процесс по шагам.

1. Настройка метаданных в конфигураторе

В документе создаем две табличные части:

  1. Основания (Мастер-таблица) — здесь будут храниться заголовки (например, ДокументОснование).
  2. СоставРабот (Деталь-таблица) — здесь будут храниться подчиненные строки.

Важный момент: в обе табличные части необходимо добавить реквизит КлючСвязи. Для обеспечения уникальности лучше всего использовать тип УникальныйИдентификатор или, в более простых случаях, Число.

2. Программная логика на форме

Чтобы при перемещении курсора в первой таблице во второй отображались только относящиеся к ней строки, проанализируем событие ПриАктивизацииСтроки. Разберем пример кода:


&НаКлиенте
Процедура ОснованияПриАктивизацииСтроки(Элемент)
    ТекущиеДанные = Элементы.Основания.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Устанавливаем отбор во второй таблице по ключу связи
        Элементы.СоставРабот.ОтборСтрок = Новый ФиксированнаяСтруктура("КлючСвязи", ТекущиеДанные.КлючСвязи);
    КонецЕсли;
КонецПроцедуры

3. Генерация ключа при добавлении строк

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


&НаКлиенте
Процедура ОснованияПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    Если НоваяСтрока И НЕ Копирование Тогда
        ТекущиеДанные = Элементы.Основания.ТекущиеДанные;
        ТекущиеДанные.КлючСвязи = Новый УникальныйИдентификатор;
    КонецЕсли;
КонецПроцедуры

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

Метод 2: Использование Дерева значений для визуализации

Если задача стоит именно в визуальном представлении «одна таблица внутри другой», проанализируем использование объекта ДеревоЗначений. Этот объект позволяет создавать неограниченное количество уровней вложенности.

Рассмотрим алгоритм работы с деревом:

  1. Создаем на форме реквизит с типом ДеревоЗначений.
  2. Добавляем колонки, которые должны быть общими для всех уровней (например, «Наименование», «Количество»).
  3. При открытии формы или при нажатии кнопки заполняем дерево данными из табличных частей документа.

Пример программного добавления узлов в дерево:


// Создаем строку верхнего уровня (Документ-основание)
НоваяСтрокаОснование = ДеревоДанных.ПолучитьОбъект().Строки.Добавить();
НоваяСтрокаОснование.Наименование = "Заказ №1";

// Создаем подчиненную строку (Работа)
НоваяСтрокаРабота = НоваяСтрокаОснование.Строки.Добавить();
НоваяСтрокаРабота.Наименование = "Монтаж оборудования";
НоваяСтрокаРабота.Количество = 1;

Выясним важную особенность: ДеревоЗначений нельзя напрямую сохранить как реквизит документа. Поэтому перед записью документа вам придется реализовать обратный процесс — «развертывание» дерева обратно в плоские табличные части.

Метод 3: Хранение вложенных данных в JSON или ХранилищеЗначения

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

Проанализируем шаги реализации:

  1. В основной табличной части создаем колонку ДанныеСтроки с типом Строка (неограниченной длины).
  2. При редактировании строки открываем отдельное всплывающее окно с таблицей.
  3. При закрытии окна упаковываем таблицу в формат JSON и сохраняем в строку.

Посмотрим на пример упаковки данных:


ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ТаблицаРабот); 
СтрокаДляХранения = ЗаписьJSON.Закрыть();

Этот метод значительно упрощает структуру метаданных, так как вам не нужно плодить множество табличных частей. Однако помните, что данные внутри JSON-строки «невидимы» для системы компоновки данных (СКД), пока вы не преобразуете их обратно в таблицу программно.

Важные рекомендации при выборе решения

Выбор конкретного метода зависит от требований к производительности и удобству пользователя:

При реализации связи через ключи, всегда используйте УникальныйИдентификатор. Избегайте связи по номеру строки (НомерСтроки), так как при удалении или сортировке строк в основной таблице номера пересчитываются, и связь с подчиненными строками в другой таблице будет безвозвратно нарушена.

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

← На главную