Обработка «Схема связей» показывает прямо в базе, как связаны объекты конфигурации: какие регистры двигает документ, кто ссылается на справочник и через какой реквизит. Пригодится, чтобы посмотреть или вспомнить связи в типовой конфигурации, не открывая конфигуратор.
Слева — все объекты конфигурации, разложенные по видам, с поиском; у каждого два числа — сколько объектов ссылается на него и на сколько ссылается он. Выбранный объект встаёт в центр: справа — на что он ссылается, слева — кто ссылается на него, под схемой — через какой реквизит. Щелчок по соседу делает центром его.
Как это выглядит
«Номенклатура»: слева — кто на неё ссылается, по видам; группа «Документы» раскрыта. Пунктир — связь только через реквизит составного типа.
Когда соседей с одной стороны больше двенадцати, обработка собирает их в группы по видам — «Документы · 230», «Регистры сведений · 87». Щелчок по группе раскрывает её, повторный — сворачивает. Щелчок по объекту переносит его в центр. В таблице под схемой — все связи с подписью, через что: реквизит, реквизит табличной части, измерение, ресурс, «движения» или «владелец». Если связей с объектом несколько, его строка раскрывается деревом и показывает каждую.
«Авансовый отчёт» — центр после щелчка из группы «Документы»; справа раскрыты регистры накопления, которые он двигает.
Реквизит составного типа означает связь, которая может быть, а может и не быть. Самый частый пример — дополнительные реквизиты БСП: они есть почти у каждого объекта и могут ссылаться на что угодно. Такие связи обработка рисует пунктиром, а флажок «Без составных типов» их убирает.
Конфигурация без БСП: у «Контрагентов» соседей меньше двенадцати, группы не нужны. Список слева свёрнут по видам
Схема для документации
Кнопка «Текст PlantUML» выдаёт схему текстом PlantUML — такой, какая она сейчас на экране. Свёрнутая группа — один прямоугольник «Документы · 230», раскрытая — все её объекты. Составная связь — пунктиром, на стрелке — через что. Текст можно вставить в plantuml.com, Confluence или редактор с PlantUML и получить картинку для документации. Большую схему лучше брать в SVG: PNG на plantuml.com обрезается по высоте. Для «Контрагентов» из демо, сокращённо:
@startuml
left to right direction
rectangle "Справочник\nКонтрагенты" as c #DBE8FF;line.bold
rectangle "Документ\nЗаказ" as n5 #DCF3D5
n5 --> c : Покупатель
rectangle "Регистр сведений\nХарактеристики" as n10 #FFE6CC
n10 ..> c : измерение Объект (составной, 2)\nресурс Значение (составной, 15)
rectangle "Справочник\nРегионы" as n13 #DBE8FF
c --> n13 : Регион
@enduml
Кнопка «Сохранить схему» отдаёт файл HTML: сверху схема, под ней вся таблица связей, с названием конфигурации и датой. Файл открывается в любом браузере.
Как это сделано
Связи всей конфигурации
Связь объекта с соседом живёт в типе его реквизита. Обработка обходит справочники, документы, планы, бизнес-процессы, задачи, регистры и константы и у каждой части берёт типы, из которых состоит её тип. Объект метаданных по типу возвращает Метаданные.НайтиПоТипу:
Для Каждого Часть Из ЧастиОбъекта(ОбъектМД, Коллекция) Цикл
Типы = Часть.МД.Тип.Типы();
Если Типы.Количество() > 20 Тогда
Широких = Широких + 1;
Продолжить;
КонецЕсли;
Для Каждого ТипЧасти Из Типы Цикл
Куда = Метаданные.НайтиПоТипу(ТипЧасти);
Если Куда <> Неопределено Тогда
ДобавитьСвязь(Связи, Откуда, Куда.ПолноеИмя(), Часть.Через, Типы.Количество());
КонецЕсли;
КонецЦикла;
КонецЦикла;
Тип шире двадцати — это «любая ссылка» или определяемый тип на всё подряд. Такой реквизит связан со всей конфигурацией, и я не беру его в связи: обработка только сообщает, сколько таких реквизитов. Число типов остаётся у каждой связи — по нему схема отличает прямую связь от составной.
Две связи в типах реквизитов не видны, их обработка добавляет отдельно: регистры, которые двигает документ, — из Движения, и владельцев справочника — из Владельцы.
Какие части есть у объекта, нам известно по его коллекции: у регистров — измерения, ресурсы и реквизиты, у остальных — реквизиты и табличные части. Проверять наличие раздела обращением в попытке не нужно:
Если СтрНачинаетсяС(Коллекция, "Регистры") Тогда
ДобавитьЧасти(Части, ОбъектМД.Измерения, "измерение ");
ДобавитьЧасти(Части, ОбъектМД.Ресурсы, "ресурс ");
ДобавитьЧасти(Части, ОбъектМД.Реквизиты, "");
Иначе
ДобавитьЧасти(Части, ОбъектМД.Реквизиты, "");
Для Каждого ТЧ Из ОбъектМД.ТабличныеЧасти Цикл
ДобавитьЧасти(Части, ТЧ.Реквизиты, ПредставлениеЧасти(ТЧ) + ": "); // синоним ТЧ, в модуле — не длиннее 25 знаков
КонецЦикла;
КонецЕсли;
Собрать один раз
Обход всей типовой конфигурации занимает около секунды — на каждый щелчок это много. Поэтому обработка собирает связи один раз при открытии и кладёт таблицу во временное хранилище формы. На каждый выбор объекта она берёт таблицу оттуда и ищет его связи по индексу:
Связи.Индексы.Добавить("Откуда");
Связи.Индексы.Добавить("Куда");
ЭтотОбъект.АдресСвязей = ПоместитьВоВременноеХранилище(Связи, ЭтаФорма.УникальныйИдентификатор);
// при выборе объекта
Все = ПолучитьИзВременногоХранилища(ЭтотОбъект.АдресСвязей);
Для Каждого Направление Из СтрРазделить("Куда,Откуда", ",") Цикл
// Куда = центр — на центр ссылаются; Откуда = центр — центр ссылается
Отбор = Новый Структура(?(Направление = "Куда", "Куда", "Откуда"), ПолноеИмя);
Для Каждого Связь Из Все.НайтиСтроки(Отбор) Цикл
// …
КонецЦикла;
КонецЦикла;
Хранилище привязано к форме: закрыли обработку — данные ушли вместе с ней.
Схема в поле HTML
Штатным элементом формы такую схему не построить: у графической схемы нет метода «добавить элемент». Поэтому схема — HTML-документ в поле формы. Линии со стрелками — SVG, узлы — HTML-ссылки поверх:
// Слева — линия от узла к центру; по горизонтали — доли ширины поля
Линия = "<line x1=""32%"" y1=""" + (Y + 10) + """ x2=""40%"" y2=""" + ЦентрY + """";
// …
ЭтотОбъект.Узлы.Добавить(Узел.Ключ);
Узлы.Добавить("<a class=""n " + Узел.Класс + """ href=""#n" + XMLСтрока(ЭтотОбъект.Узлы.Количество() - 1)
+ """ title=""" + ЭкранироватьHTML(Узел.Подсказка) + """ style=""left:" + ?(Слева, "1", "67") + "%;top:" + Y + "px"">"
+ ЭкранироватьHTML(Узел.Текст) + "</a>");
По горизонтали всё в процентах — и у узлов, и у линий SVG: схема занимает всю ширину поля, и на широком экране длинные имена влезают целиком. На узком экране она не сжимается, а прокручивается.
Почему узлы не внутри SVG: щелчок по ссылке внутри SVG доходит до 1С, но в ДанныеСобытия.Href приходит «[object SVGAnimatedString]» — у SVG-ссылки адрес не строка. У обычной HTML-ссылки адрес приходит целиком. В адресе стоит номер узла, а в реквизите формы Узлы по этому номеру лежит, что за узел: объект или группа. Номер вместо имени объекта избавляет от раскодирования кириллицы:
&НаКлиенте
Процедура СхемаПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
Позиция = СтрНайти(ДанныеСобытия.Href, "#n");
Если Позиция = 0 Тогда
Возврат;
КонецЕсли;
СтандартнаяОбработка = Ложь;
Узел = ЭтотОбъект.Узлы[Число(Сред(ДанныеСобытия.Href, Позиция + 2))].Значение;
Части = СтрРазделить(Узел, "|");
Если Части[0] = "О" Тогда
ПоказатьЦентр(Части[1]);
Иначе
РаскрытьГруппу(Части[1], Части[2]);
КонецЕсли;
КонецПроцедуры
СтандартнаяОбработка = Ложь отменяет переход по адресу — поле не уходит на другую страницу, обработка просто перерисовывает схему вокруг нового центра.
После серверного вызова, который перерисовал поле HTML, у списка слева снова срабатывает ПриАктивизацииСтроки — с той же строкой, что была. Если сравнивать эту строку с центром схемы, обработчик увидит расхождение и вернёт центр к объекту из списка, и щелчок по соседу словно не работает. Поэтому список сравнивает строку с той, которую выбрал последней, а не с центром.
На чём проверено
Я проверял на платформе 1С:Предприятие 8.5 (8.5.1.1522) и «Управлении нашей фирмой» 3.0 (3.0.14.143). В веб-клиенте, на серверной базе. Без БСП — на своей конфигурации, на той же платформе.
На 8.3 я не проверял. Может, откроется, а может, и нет.
Состав поставки
SkhemaSvyazey.epf— внешняя обработка «Схема связей», код открыт.
Проверено на следующих конфигурациях и релизах:
- Управление нашей фирмой, редакция 3.0, релизы 3.0.14.143
Вступайте в нашу телеграмм-группу Инфостарт


