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