- PVSM.RU - https://www.pvsm.ru -
Привет!
Проектирование конструкторской документации для систем автоматизации в EPLAN ELECTRIC P8 — это интересный и многогранный процесс. Обычно он включает:
разработку электрических принципиальных схем шкафов;
компоновку оборудования в 3D;
оформление чертежей и генерацию отчётов.
На каждом этапе стандартные средства EPLAN Platform предлагают немало инструментов: макросы символов, табличные обработки, объекты-заполнители, экспорт и многое другое. Но со временем, когда база компонентов уже наполнена, схемы и компоновки отлажены, стандартного функционала начинает не хватать — хочется добавить что-то своё. И здесь на помощь приходит EPLAN API.
Главная сложность работы с API — необходимость разбираться не только в базовом функционале EPLAN, но и в языке C#, а также в среде разработки Visual Studio. Таких специалистов немного. Конечно, можно заказать доработки у профессионалов, но бюджет на это есть не всегда, поэтому многим инженерам приходится развивать собственные навыки и осваивать API самостоятельно.
Я сам занимаюсь разработкой РКД на АСУТП и столкнулся с этими трудностями: документация есть, но она скорее справочная, чем обучающая, и примеров для новичков там почти нет. Русскоязычных источников тоже немного: помог Форум АСУТП [1] и одна статья на Хабре [2] про создание простого Add-In.
В этой статье я попробую восполнить пробел: приведу примеры кода с пояснениями, чтобы начинающим разработчикам было проще войти в тему. Я сознательно оставляю примеры максимально простыми — чтобы сосредоточиться на сути, а не на красоте кода.
Итак, EPLAN Platform позволяет использовать API двумя способами: Scripts и Add-In’s.
Script - это обычный текстовый файл, содержащий код дополнения. Для его запуска можно просто в программе указать путь до файла *.cs и EPLAN его сам компилирует и запустит. Для запуска скриптов не требуется дополнительных лицензий, но они очень ограничены по функционалу: имеют ограниченный доступ к объектной модели EPLAN, отсутствует возможность получения свойств объектов. Обзор структуры и возможностей скриптов приведен тут [3].
Add-In - это полноценное дополнение, которое компилируется в библиотеку *.dll. Для возможности подключения таких дополнений имеется два вида лицензий: runtime и developer. Runtime лицензия позволяет запускать модули, подписанные самой компанией EPLAN или сертифицированными разработчиками. Developer лицензия позволяет подключать любые библиотеки без подписи.
Для автоматизации взаимодействия с существующими объектами EPLAN возможностей скриптов становится недостаточно, поэтому далее коснемся только разработки Add-In’s.
В этом разделе частично продублирую статью [2] про создание Add-In'а из-за изменений в интерфейсе MS Visual Studio и API 2025.
При создании нового проекта в MS Visual Studio необходимо выбрать шаблон "Библиотека классов (.NET Framework)".

На следующем шаге выберем платформу .NET Framework 4.8.1.

После создания проекта необходимо добавить ссылки на библиотеки Eplan.EplApi, которые расположены в папке установки EPLAN (в моем случае это C:Program FilesEPLAN2025Platform2025.0.3Bin).

В свойствах проекта в разделе Сборка выбираем целевую платформу x64.

В разделе "Приложение" указываем имя сборки в формате Eplan.EplAddIn.XXXX, где XXXX - имя нашего приложения.

Видео инструкция по созданию проекта Add-In [4].
С настройками покончено, теперь необходимо создать 2 класса: IEplAddIn и IEplAction. Первый используется для регистрации Add-In и создания кнопок на Ribbon-панели, которые будут запускать будущие действия, прописанные в классах IEplAction.
Переименуем автоматически созданный Class1.cs в AddInModule.cs и добавим в него следующее содержание:
using Eplan.EplApi.ApplicationFramework;
namespace Test
{
public class AddInModule : IEplAddIn
{
public bool OnExit()
{
return true;
}
public bool OnInit()
{
return true;
}
public bool OnInitGui()
{
return true;
}
public bool OnRegister(ref bool bLoadOnStart)
{
var ribbonBar = new Eplan.EplApi.Gui.RibbonBar();
ribbonBar.AddCommand("Тест", "ActionTest");
bLoadOnStart = true;
return true;
}
public bool OnUnregister()
{
var ribbonBar = new Eplan.EplApi.Gui.RibbonBar();
ribbonBar.RemoveCommand("ActionTest");
return true;
}
}
}
Начиная с версии EPLAN 2022 классические панели заменены на Ribbon и необходимо создавать и удалять кнопки на этой панели.
В этом классе можно добавлять для кнопок иконки, комментарии, всплывающие подсказки и сортировать их. Справка по использованию Ribbon [5].
В текущем примере на вкладке “Расширения” в группе “API” создается новая кнопка с текстом “Тест”, выполняющая действие ActionTest, имя которого должно быть задано в отдельном классе: IEplAction в методе OnRegister.
Так как кнопки добавляются и удаляются в методах OnRegister и OnUnregister, то после внесения изменений в этих методах (например, добавления новой кнопки) чтобы увидеть обновленную информацию в Ribbon-панели, необходимо выгрузить Add-In, перезагрузить EPLAN и заново загрузить Add-In.
В целом, уже на этом этапе можно скомпилировать библиотеку и загрузить её в EPLAN. На Ribbon-панели появится дополнительная вкладка “Расширения”, и на ней появится единственная кнопка “Тест”, которая будет неактивной, так как мы ещё не сделали никаких действий для неё.
Добавляем класс ActionTest.cs
Добавим в проект еще один класс (Shift+Alt+C) и назовем его ActionTest.cs
using Eplan.EplApi.ApplicationFramework;
using System;
using System.Windows.Forms;
namespace Test
{
public class ActionTest : IEplAction
{
public bool Execute(ActionCallingContext oActionCallingContext)
{
MessageBox.Show("Hello World");
return true;
}
public void GetActionProperties(ref ActionProperties actionProperties)
{
}
public bool OnRegister(ref string Name, ref int Ordinal)
{
Name = "ActionTest";
Ordinal = 20;
return true;
}
}
}
Метод OnRegister вызывается при регистрации Add-In, в нем задается имя и приоритет, которые регистрируются в EPLAN. Метод Execute выполняется при вызове Action, например при нажатии на кнопку, которую создали на предыдущем шаге. Более подробная инструкция по Action [6].
Многие методы API EPLAN требуют в качестве аргументов текущий проект и страницу, так что первым делом запишем в переменные текущий проект и первую выделенную страницу:
Project proj = new SelectionSet().GetCurrentProject(false);
if (proj == null) return false;
Page pg = new SelectionSet().GetSelectedPages().FirstOrDefault();
Для взаимодействия с существующими объектами можно использовать 2 инструмента
SelectionSet - выдает набор всех выделенных элементов
DMObjectsFinder - позволяет найти необходимые объекты по заданным критериям
В объектной модели EPLAN множество различных типов объектов, и чтобы понять, с чем конкретно вы имеете дело, можно вывести тип выделенного объекта в сообщении:
SelectionSet Set = new SelectionSet();
if (Set.Selection.Count() == 0)
{
return false;
}
foreach (StorableObject selObj in Set.Selection)
{
MessageBox.Show(selObj.ToString());
}
Когда мы уже выяснили, с каким типом объекта имеем дело, то можем преобразовать StorableObject к нужному типу и дальше уже с ним взаимодействовать.
List<Terminal> TerminalsList = new List<Terminal>();
SelectionSet Set = new SelectionSet();
if (Set.Selection.Count() == 0)
{
return false;
}
foreach (StorableObject selObj in Set.Selection)
{
if (selObj is Terminal)
{
Terminal SelectedTerminal = selObj as Terminal;
TerminalsList.Add(SelectedTerminal);
}
}
Справка по инструменту SelectionSet [7].
Возможности поиска DMObjectsFinder хорошо иллюстрируются следующим рисунком.

Краткий пример поиска графических элементов на текущей странице:
DMObjectsFinder oDMO = new DMObjectsFinder(proj);
PlacementsFilter filter = new PlacementsFilter
{
Page = pg
};
foreach (Placement pcc in oDMO.GetPlacements(filter))
{
if (pcc is GraphicalPlacement)
{
GraphicalPlacement gp = pcc as GraphicalPlacement;
if (gp.Layer.Name == "Выноски") gp.Remove();
}
}
В этом примере происходит поиск всех размещенных на текущей странице объектов. Если размещенный объект является графикой (линии, прямоугольники и др.), то проверяем на каком слое он расположен и удаляем в случае, если слой называется "Выноски".
Справка по DMObjectsFinder [8]
По умолчанию после выполнения любого пользовательского Action в EPLAN полностью сбрасывается список отменяемых действий (Отменить ввод CTRL+Z), что очень неудобно, учитывая отсутствие кнопки "Сохранить". Чтобы такого не произошло, необходимо позаботиться о возможности отмены действий в своем Add-In. Для этого существуют 2 инструмента: UndoManager и SafetyPoint, которые можно использовать совместно.
using (UndoStep undoStep = new UndoManager().CreateUndoStep())
{
undoStep.SetUndoDescription("DoStuff");
using (SafetyPoint safetyPoint = SafetyPoint.Create())
{
try
{
// Do stuff
safetyPoint.Commit();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
safetyPoint.Rollback();
}
}
}
При использовании такой конструкции сохраняется возможность отмены действий пользователем, а, при возникновении исключений, выполненные действия отменяются автоматически.
У каждого объекта в API DataModel имеются свойства (Properties), которые мы можем увидеть на первой вкладке свойств.

Но также у большинства объектов имеются свойства (PropertyPlacements), которые отображаются на листе и которые мы можем настроить на вкладке "Отображение".

Для идентификации PropertyPlacements можно получить название и номер используя следующие поля:
...PropertyPlacements[ ].DisplayedProperty.Definition.Name
...PropertyPlacements[ ].DisplayedProperty.AsInt
Пример скрытия свойства <20008> ОУ (идентифицирующее, без структуры проекта) для объектов обзора модели:
SelectionSet Set = new SelectionSet();
if (Set.Selection.Count() == 0)
{
return false;
}
foreach (StorableObject selObj in Set.Selection)
{
if (selObj is ViewPart)
{
ViewPart SelectedViewPart = selObj as ViewPart;
foreach (PropertyPlacement prop in SelectedViewPart.PropertyPlacements)
{
if (prop.DisplayedProperty.AsInt == 20008) prop.IsVisible = false;
}
}
}
Помимо PropertyPlacements можно использовать заранее подготовленные порядки свойств (PropertyPlacementsSchemas) и присваивать их выбранному объекту
SelectionSet Set = new SelectionSet();
if (Set.Selection.Count() == 0)
{
return false;
}
foreach (StorableObject selObj in Set.Selection)
{
if (selObj is ViewPart)
{
ViewPart SelectedViewPart = selObj as ViewPart;
SelectedViewPart.Properties.INSTANCE_ACTIVE_PROPERTYSET.Set ("Turbo_Output");
}
}
Справка по Properties [9] и PropertyPlacements [10]. Перечень всех свойств EPLAN с возможностью сортировки и фильтрации можно посмотреть здесь [11].
Eplan позволяет через API получить доступ ко всем настройкам как для чтения, так и для записи. Для чтения или записи конкретной настройки необходимо определить её имя. Это можно сделать путем экспорта настроек в xml и дальнейшего нахождения в файле нужной настройки. Например как это выглядит для выбора стиля оформления:


Соответственно имя настройки для использования в Add-In будет USER.MF.GuiColorScheme, а тип возвращаемого значения - int.
Settings oSettings = new Settings();
int colorScheme = oSettings.GetNumericSetting("USER.MF.GuiColorScheme", 0); // 0=Default 1=Dark 2=Light
Справка по свойствам проекта [12].
В некоторых случаях во время выполнения Action необходимо получить от пользователя информацию, например, координаты курсора в пространстве листа после клика пользователем. В этом случае EPLAN API предоставляет такую возможность в виде класса Interaction. Ниже приведен пример класса, в котором для перемещения свойств (PropertyPlacement) из подготовленного в Action списка объектов пользователю предлагается дважды кликнуть мышкой. Первый клик сохраняет координаты, куда необходимо переместить первое свойство в списке, а второй клик расстояние до последующих свойств.
using Eplan.EplApi.Base;
using Eplan.EplApi.DataModel.EObjects;
using Eplan.EplApi.EServices.Ged;
namespace Test
{
public class TestInteraction : Interaction
{
public override RequestCode OnStart(InteractionContext oContext)
{
Description = "Отменить перемещение"; //Наименование действия для UndoStep, который генерируется автоматически перед выполнением OnSuccess
return RequestCode.Point;
}
public override RequestCode OnPoint(Position oPosition)
{
//Получение координат курсора после клика
FirstPosition = oPosition.FinalPosition;
return RequestCode.Length;
}
public override RequestCode OnLength(double dLength)
{
//Получение расстояния
length = dLength;
return RequestCode.Success;
}
public override void OnSuccess(InteractionContext oContext)
{
foreach (Terminal term in TestAction.SelectedTerminals)
{
PointD TempPoint = new PointD (FirstPosition.X - term.Location.X, FirstPosition.Y- term.Location.Y);
term.PropertyPlacements[3].Location = TempPoint;
FirstPosition.X += length;
}
}
private double length = 0.0;
private PointD FirstPosition = new PointD(0, 0);
}
}
Interaction регистрируется в EPLAN по названию класса. Для вызова Interaction из Action используем ActionManager
string strAction = "XGedStartInteractionAction";
ActionManager oActionManager = new ActionManager();
Eplan.EplApi.ApplicationFramework.Action oAction = oActionManager.FindAction(strAction);
if (oAction != null)
{
ActionCallingContext oContext = new ActionCallingContext();
oContext.AddParameter("Name", "TestInteraction");
bool bRet = oAction.Execute(oContext);
/*
if (bRet)
{
new Decider().Decide(EnumDecisionType.eOkDecision, "The Action " + oAction.Name + " ended successfully!", "", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK);
}
else
{
new Decider().Decide(EnumDecisionType.eOkDecision, "The Action " + oAction.Name + " ended with errors!", "", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK);
}
*/
return bRet;
}
else
{
new Decider().Decide(EnumDecisionType.eOkDecision, "Не удалось найти XGedStartInteractionAction", "Ошибка", EnumDecisionReturn.eOK, EnumDecisionReturn.eOK);
return false;
}
Важно, чтобы значение параметра Name в строке oContext.AddParameter("Name", "TestInteraction"); точно совпадало с названием класса Interaction. Через oContext.AddParameter можно передавать в Interaction любые строковые данные.
Справка по Interactions [13].
API EPLAN открывает действительно широкие возможности. Даже простые Add-In’ы позволяют ускорить рутинные операции и сделать разработку проектов удобнее.
Порог входа, конечно, высокий: нужно разбираться и в объектной модели EPLAN, и в C#, и в особенностях самой платформы. Но чем больше практики — тем быстрее приходит понимание.
Надеюсь, приведённые в статье примеры помогут вам сэкономить время на старте и вдохновят на создание собственных дополнений. Ведь даже одна кнопка на Ribbon-панели, автоматизирующая частое действие, может заметно облегчить жизнь инженера.
Форум АСУТП [1]
Автор: tolyantez
Источник [17]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/api/429384
Ссылки в тексте:
[1] Форум АСУТП: https://asutpforum.ru/viewforum.php?f=206
[2] статья на Хабре: https://habr.com/ru/articles/271671/
[3] тут: https://www.eplan.help/en-US/infoportal/content/api/2025/Scripts.html
[4] Add-In: https://www.youtube.com/watch?v=VvURA4IfELk
[5] Ribbon: https://www.eplan.help/en-US/infoportal/content/api/2025/TheRibbon.html
[6] Action: https://www.eplan.help/en-US/infoportal/content/api/2025/Actions.html
[7] SelectionSet: https://www.eplan.help/en-US/infoportal/content/api/2025/Eplan.EplApi.HEServicesu~Eplan.EplApi.HEServices.SelectionSet.html
[8] DMObjectsFinder: https://www.eplan.help/en-US/infoportal/content/api/2025/Eplan.EplApi.DataModelu~Eplan.EplApi.DataModel.DMObjectsFinder.html
[9] Properties: https://www.eplan.help/en-US/infoportal/content/api/2025/EPLAN%5C_Properties.html
[10] PropertyPlacements: https://www.eplan.help/en-US/infoportal/content/api/2025/Eplan.EplApi.DataModelu~Eplan.EplApi.DataModel.Graphics.PropertyPlacement.html
[11] здесь: https://www.eplan.help/ru-RU/Infoportal/Content/Plattform/2025/Content/htm/properties%5C_o%5C_main.htm?tocpath=%D0%9E%D0%B1%D0%B7%D0%BE%D1%80%D1%8B%20EPLAN%7C%D0%A1%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0%20EPLAN%7C%5C_%5C_%5C_%5C_%5C_2
[12] свойствам проекта: https://www.eplan.help/en-US/infoportal/content/api/2025/WorkingWithSettings.html
[13] Interactions: https://www.eplan.help/en-US/infoportal/content/api/2025/Interactions.html
[14] EPLAN API Help System: https://www.eplan.help/en-US/infoportal/content/api/2025/index.html
[15] Suplanus EPLAN API Blog: https://suplanus.de/category/eplan/eplan-api/
[16] Suplanus EPLAN API GitHub: https://github.com/Suplanus/Suplanus.Sepla/tree/master
[17] Источник: https://habr.com/ru/articles/941830/?utm_source=habrahabr&utm_medium=rss&utm_campaign=941830
Нажмите здесь для печати.