Farbnamen aus dem RAL-Code ermitteln

Problemstellung

Wie war denn noch der Name für RAL3000? Oh, auch noch den englischen? Kurz in der Tabelle gesucht, oder auf Seiten wie ral-farben.de geschaut: Feuerrot / Flame red. Ok, aber das für jedes Projekt? Die gebräuchlichsten sind schnell im Kopf oder auf dem Spicker und der englische Farbname lässt sich ja in der Übersetzungsdatenbank ablegen. Aber das muss doch einfacher gehen, oder?

Problemlösung

Ok, die Frage ist hier schon etwas plakativ. Daher einfach kurz zur möglichen Ausgangslage: Im Projekt sind zB. die benutzerdefinierten Felder 90/91 für den RAL-Code und den Farbnamen der Schaltschränke, die Felder 92/93 entsprechend für die Klemmkästen. Erstmal angenommen, alle Felder sind Multilang, es kommt also ein ??_??@.. beim auslesen zurück. Daher kommt einfach die Lösung aus Multilang-Strings einfach auslesen zum Einsatz. Das Auslesen an sich ist recht einfach (Ähnlich zu Erstelldatum in Seiten manipulieren, nur über XEsGetProjectPropertyAction), wie auch das neu einschreiben (XEsSetProjectPropertyAction). Fehlt nur noch eine Liste, gegen die geprüft und aus der dann die Daten gezogen werden. Da bieten sich zwei Typen gut an:

Weiterlesen

Erstelldatum in Seiten manipulieren

Problemstellung

Erstmal: Warum sollte man das machen wollen? Nunja: Im Basisprojekt sind gewisse Seiten schon vorab erstellt worden. Wird das Basisprojekt kopiert, wird auch das Erstellungsdatum der Seiten (egal ob nun vollkommen leer als Vorlage, oder gefüllt als Legende etc.) mit kopiert. Damit ergibt sich zwangsweise ein älteres Datum in den Seiten als im Projekt selbst. Das sieht etwas uncool aus, oder bringt nur sehr viele Fragen mit sich (besonders in gewissen Kundenkreisen). Und dann ist das nicht einfach nur eine Zeichenfolge, sondern ein Zahlenwert..

Problemlösung

Das Schreiben von Seiteneigenschaften mit XEsSetPagePropertyAction hatte ich ja schon beschrieben, nun muss nur noch geklärt werden, was geschrieben werden soll. Der Zahlenwert sind die Sekunden, die seit dem 1.1.1970 vergangen sind, in Unix die Sekunde 0. Es lässt sich auch einfach selbst heraus finden: Nach dem Anpassen eines Formulars einfach mal in das passende Feld für den Timestamp der letzten Änderung schauen!

Weiterlesen

Funktionen im Wandel der Versionen

Problemstellung

Scripte sollen möglichst unabhängig von Versionen laufen (und dennoch gerne alles mitnehmen, was dem Nutzer hilft) um auch nach Upgrades auf die neuere Version nicht erstmal wieder Probleme zu verursachen. Immerhin geht es bei den meisten Funktionen in den Scripten (zumindest da, wo sie regelmäßig zum Einsatz kommen) um mehr als nur seltene Sonderaufgaben etwas komfortabler zu gestalten. Nicht selten hängt indirekt mit daran, ob ein Auftragspensum überhaupt machbar, oder ein gewisser Dokumentenumfang in gegebener Zeit erstellt, oder die immer gleichen Arbeitsabläufe sichergestellt werden können. Und nein, das ist tatsächlich keine Übertreibung. Ist von jetzt auf gleich erstmal die Funktion weg und es müssen damit wieder manuell Dateien abgelegt werden…

Lösungsansatz

Die folgende Tabelle habe ich mir mal als Hilfestellung zusammen geschoben, welche Funktion in welcher Version verfügbar ist/war. Auch wenn ich beruflich eher immer auf der neuesten Produktivversion arbeite (aktuell 2023), ist es dennoch nicht verkehrt auch die ausgelaufenen Funktionen im Blick zu halten. Zum einen kann man gelegentlich auch mal den Ballast abwerfen, zum anderen findet man auch neue Funktionen, die EPlan (teilweise noch in der Beta-Version) eingeführt hat.

Achtung! Die Tabelle enthält nur die allgemein dokumentierten Funktionen. Es gibt noch einiges mehr, was EPlan nicht dokumentiert hat. An der Stelle auch immer der Tipp mal bei suplanus zu schauen. Johann Weiher sitzt einfach näher an der Quelle und hat oftmals die eine oder andere Funktion (oft in meinen Beiträgen verlinkt, sofern genutzt).

Weiterlesen

Multilang-Strings einfach auslesen

Problemstellung

Beim Auslesen einer Eigenschaft in EPlan kommt ein String wie ??_??@Inhalt des Feldes; oder bei übersetzten Feldern eher de_DE@Inhalt des Feldes;en_US@Content of the field; was aber gewünscht war, war nur Inhalt des Feldes. Ursache ist in beiden fällen ein als mehrsprachig markiertes Feld, welches einen Multilang-String aufnehmen, verarbeiten und darstellen kann. Vergleiche mit anderen Strings sind so natürlich schon zum scheitern verurteilt, wenn das nicht berücksichtigt wird.

Problemlösung

Nun gibt es zwei verschiedene Ansätze, die mir direkt in den Sinn kommen:

  • Nach ; splitten, den ersten Teil bei @ splitten und schon ist der zweite Teil das Ergebnis. Das ist allerdings auch immer der hoffentlich deutsche oder allgemeine Teil, gesichert ist das nicht. Nun könnte man noch nach dem ersten Splitt alle Elemente durchsuchen und nach de_DE@ oder ??_??@ (oder eben nach der gewünschten Zielsprache) im Anfang prüfen, aber auch das ist weder schön noch performant
  • Suchen mit regulären Ausdrücken direkt nach dem richtigen Ausdruck in der passenden Sprache mit Fallback-Lösung
Weiterlesen

Externe Daten in die EPlan Artikeldatenbank einschleusen

Problemstellung

Es existieren sicherlich in einigen Unternehmen und Betrieben Listen mit speziell gepflegten eigenschaften. Das macht auch durchaus Sinn, Beispielsweise um den Typenschlüssel bestimmter Hersteller per VBA in Excel zu dekodieren. Wie bei allen Automationen: Das kann der Rechner schneller, akkurater und mit Beachtung aller Sonderfälle. Doch dann liegen die Infos in einer Exceltabelle und manuelles CopyPaste ist alles andere als Smart. Wie also überführen?

Problemlösung

Nun gibt es verschiedene Ansätze, wie die Daten nun von der Quelle in das Ziel gelangen.

Weiterlesen

Seiteneigenschaften manipulieren

Problemstellung

Unter gewissen Bedingungen soll das Normblatt der Seiten angepasst werden (zB. für Aufgaben jeweils ein etwas anderes, oder bei automatisierten Importen). Klar kann man das auch manuell erledigen: Alle betreffenden Seiten markieren, Normblattname anpassen und fertig. Aber das ist absolut nicht smart.

Lösungansatz

Was muss nun eigentlich passieren? Da auf die Parameter von Seiten (und auch von Bauteilen u.ä.) nicht via Array oder ähnlichem Konstrukt zugegriffen werden kann, müssen die erst selektiert werden. Das geht wie von Johann Weiher umgesetzt über edit:

// übernommen von https://suplanus.de/selectionset-pages/ Zeile 58 ff
private void SelectPage(string page) {
  ActionCallingContext actionCallingContext = new ActionCallingContext();
  actionCallingContext.AddParameter("PAGENAME", page);
  new CommandLineInterpreter().Execute("edit", actionCallingContext);
}

Alternativ könnte der Nutzer auch einzelne Seiten markieren und dann die Funktion ausführen. Das macht beispielsweise Sinn, wenn es um diverse Einstellungen geht. Nun aber noch eben das neue Normblatt definieren. Dafür gibt es die XEsSetPagePropertyAction, die noch die Eigenschaft und den Wert braucht. Es macht hier Sinn es sich an zu gewöhnen ein Try-Catch-Block um den Aufruf zu setzen, damit der Nutzer nicht nachher kryptische Fehlermeldungen bekommt und das ganze mit unter direkt abbricht.

Weiterlesen

Aktionen auf Projektordner anwenden

Problemstellung

Es gibt da noch Altbestände diverser Projekte, oder es soll einfach der aktuelle Stand jedes Projektes als PDF ausgeschrieben werden. Manuell geht das bei wenigen Projekten, bei einigen hundert Projekten aber nicht mehr.

Problemlösung

Das lässt sich zum einen über das Projektmanagement lösen, aus meiner geht das allerdings etwas schöner und unabhängiger direkt über ein Script. Für den Einstieg lässt sich gut der FolderBrowserDialog nutzen, über den der Stammordner ausgewählt wird. Danach geht’s weiter mit GetFiles und ein Loop über alle Funde (ggf. auch Rekursiv über alle Unterverzeichnisse).

public void doOverProjectFolder() {
  FolderBrowsingDialog srcFolder = new FolderBrowsingDialog();
  srcFolder.Description  = "Projektordner der bearbeitet werden soll"; // Beschreibung
  srcFolder.SelectedPath = PathMap.SubstitutePath("$(MD_PROJECTS)");   // Default path
  DialogResult srcFolderRes = srcFolder.ShowDialog();
  if (srcFolderRes == DialogResult.Cancel) {
    // Meldung beim Abbruch für den Nutzer
    return;
  }
  string[] files = Directory.GetFiles(srcFolder.SelectedPath, "*.el*", SearchOption.AllDirectories);
  foreach(string file in files) {
    // do something
  }
}

Projektnummern mit RegularExpressions finden

Problemstellung

Folgendes Szenario dürften so einige Sachbearbeiter kennen: Es gibt ein Sammelbecken mit Dateien, die unter anderem eine Projektnummer oder Auftragsnummer beinhalten. Ziel für diese Dateien sind die entsprechenden Projektordner in einer zentralen Struktur. Auch die Projektordner beinhalten die Projektnummer oder Auftragsnummer. So eine Struktur dürfte in vielen Unternehmen, ob Old School auf einem Serverlaufwerk oder etwas aktueller in der Cloud.

Lösungsansatz

Doch wie findet man nun 1. die Nummer in dem Dateinamen und 2. den korrekten Zielordner(besonders wenn der nicht direkt im Stammverzeichnis liegt)? Das Stichwort ist hier RegularExpressions oder eben Reguläre Ausdrücke. Damit lassen sich aber nicht nur Nummernfolgen finden sondern komplexe Ausdrücke, Passwörter auf Konformität prüfen (min x Stellen, Groß/Kleinbuchstaben, Sonderzeichen, etc.), oder auch ganze Formelparser bauen. Soweit soll es hier aber nicht gehen.

Ok, wir nehmen mal an, dass unsere Auftragsnummer, nach der wir suchen möchten, beispielsweise folgendes Format hat: P<Jahreszahl>-<fortlaufende Nummer, 5 Stellen>. Um mal ohne viel Aufwand RegExs zu testen, eignet sich regex101.com super und soll hier auch zum Einsatz kommen. Als Testobjekte sollen dafür mal P2023-45627, P2015-33456, P1999-11223 und P1976-00132 dienen. Damit das nun nicht zu leicht wird, könnte vor/hinter der Projektnummer nichts, Unterlagen, Rev.B, Zeichnung-12345 stehen.

Um nun den Suchbegriff abzubilden, braucht es eigentlich nur folgendes:

([pP][0-9]{4}-[0-9]{5})
(        : Öffnet die Matchgruppe
[pP]     : Ein p oder P
[0-9]{4} : 4 Zeichen, alles von 0-9 erlaubt
-        : Trennzeichen (ggf. auch [-_] möglich, wenn Fehleingaben berücksichtigt werden sollen
[0-9]{5} : 5 Zeichen, alles von 0-9 erlaubt
)        : Schließt die Matchgruppe
Weiterlesen

How to start with EPLAN Scripting

Gehen wir mal davon aus: C# ist bekannt und auch Programmabläufe müssen wir hier nicht mehr reden. Für den ersten Start, sollte man die entsprechende Hilfe-Seite von EPlan kennen. Auch die Seiten von Johann Weiher ist immer unheimlich hilfreich und sein Buch kann ich sehr empfehlen (besonders für den Einstieg). Übrigens: Die API-Hilfe von EPlan ist an einigen Stellen umfangreicher und genauer.

Zum einfachen Testen einer Funktion ist die Vorlage hier gut geeignet (direkt mit ActionCallingContext, kann weg gelassen werden, wenn es keine Parameter gibt):

// Angelehnt an https://eep8a.de/v3/scripts/02_Actions_ausfuehren/#03-action-mit-parameter
using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.Scripting;

public class test_nuttshell {
  [Start]
  public void myfuction() {
    CommandLineInterpreter cli = new CommandLineInterpreter();
    ActionCallingContext   acc = new ActionCallingContext();

    acc.AddParameter("<Parametername #1>", "<Parameterwert #1>");
    acc.AddParameter("<Parametername #2>", "<Parameterwert #2>");
    //...
    acc.AddParameter("<Parametername #n>", "<Parameterwert #n>");
    
    cli.Execute("XGedStartInteractionAction", acc);
  }
}

Das ganze einfach in einer Textdatei mit der Endung „*.cs“ speicher und testen. Es reicht nun das Script zu starten, dann wird die Funktion nach dem Triggerwort für das Event Start ausgeführt. Das ist allerdings eher für seltener gebrauchte Tools sinnvoll. Später macht es Sinn dann die Funktionen über Menüs oder Events wie OnMainStart zu triggern:

// Angelehnt an https://eep8a.de/v3/scripts/02_Actions_ausfuehren/#03-action-mit-parameter
using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.Scripting;

public class test_nuttshell {
  [DeclareAction(ACTION_NAME)]
  public void myfuction() {
    CommandLineInterpreter cli = new CommandLineInterpreter();
    ActionCallingContext   acc = new ActionCallingContext();

    acc.AddParameter("<Parametername #1>", "<Parameterwert #1>");
    acc.AddParameter("<Parametername #2>", "<Parameterwert #2>");
    //...
    acc.AddParameter("<Parametername #n>", "<Parameterwert #n>");
    
    cli.Execute("XGedStartInteractionAction", acc);
  }
}

Alternativ können Scripte und Funktionen auch über die Befehlszeile mit den entsprechenden Parametern ausgeführt werden. Im-/Exporte aus anderen Tools lassen sich so einfach realisieren, wenn das entsprechende Eplan installiert ist:

"<Pfad zur w3u.exe>" /NoSplash /Quiet /Auto /Variant:electric /NoLoadWorkspace ....