Как связать две табличные части на управляемой форме 1С по принципу «мастер – деталь»?

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

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

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

Архитектура данных и выбор ключа связи

Для корректного реляционного связывания создадим две табличные части в объекте метаданных (например, в документе):

  1. Главная табличная часть (например, НомераТруб или Товары) — содержит реквизиты основной строки и ключевое поле связи (например, реквизит ИД или КлючСвязи).
  2. Подчиненная табличная часть (например, Услуги) — содержит реквизит связи ИД (или КлючСвязи), а также реквизиты подчиненных записей (номенклатуру услуги, количество, стоимость и т.д.).

Важно: Не используйте стандартный реквизит НомерСтроки в качестве ключа связи! При удалении, сортировке или перемещении строк главной таблицы платформа автоматически пересчитывает номера строк, что приведет к полной рассинхронизации данных. В качестве ключа связи рекомендуется использовать УникальныйИдентификатор (или строковый GUID фиксированной длины), либо целочисленный реквизит (тип Число(10, 0)).

Настройка синхронизации таблиц на управляемой форме

Разберем по шагам логику клиентского кода для синхронизации отображения главной и подчиненной таблиц.

Шаг 1. Фильтрация подчиненной таблицы при смене строки в главной таблице

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


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

Шаг 2. Генерация ключа при создании новой строки в главной таблице

В событии ПриНачалеРедактирования главной таблицы проверяем, является ли строка новой. Если строка только создается, генерируем для нее уникальный идентификатор.


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

Шаг 3. Заполнение ключа связи в подчиненной таблице

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


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

Шаг 4. Каскадное удаление подчиненных строк

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


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

Обработка краевых случаев и контроль целостности

Проанализируем тонкости, которые необходимо учесть для обеспечения надежной работы интерфейса:

  1. Защита от добавления без выбранного родителя: В событии ПередНачаломДобавления подчиненной таблицы обязательно проверяйте условие Элементы.НомераТруб.ТекущиеДанные = Неопределено. Если в главной таблице не выделено ни одной строки, следует установить Отказ = Истина и выдать предупреждение пользователю.
  2. Копирование строк главной таблицы: Если пользователь копирует строку в главной таблице (Копирование = Истина в ПриНачалеРедактирования), платформенный механизм продублирует старый ИД. В этом случае необходимо сформировать новый уникальный ключ для копии и программно продублировать все связанные строки подчиненной ТЧ, присвоив им сгенерированный ключ.
  3. Контроль «осиротевших» строк на сервере: В модуле объекта в процедуре ПередЗаписью полезно реализовать серверную очистку: запросом выгрузить все уникальные ключи из главной ТЧ и удалить из подчиненной ТЧ строки с ключами, которых нет в главной.

Альтернативные способы отображения

В зависимости от бизнес-требований можно рассмотреть и другие решения:

  1. Отображение через ДеревоЗначений: На форму выводится один элемент с типом ДеревоЗначений, где верхний уровень — это товары, а вложенные узлы — услуги. При открытии дерево заполняется из двух табличных частей документа, а при записи программно выгружается обратно.
  2. Редактирование во вспомогательной форме: В главной таблице добавляется кнопка или гиперссылка «Состав услуг», открывающая отдельное модальное или всплывающее окно с таблицей услуг только для выбранного товара. Это исключает перегрузку основного экрана документа.
← На главную