FAQ: MAKRO und SKRIPT / Rund um AutoCAD
FAQ 30. Okt. 2008, 12:46

FAQ: Menü-MAKROs und SKRIPTe
________________________________________________________________________________________

VORAB:
Makros und Skripte funktionieren in der "Vollversion" und in "Acad-LT" 100% identisch
ABER: Da man in Makros und Skripten nur Funktionen nutzt welche die Software zur Verfügung
stellt kann es natürlich vorkommen das so ein Helferlein auch mal nur in der Vollversion bzw.
nur in der LT-Version arbeitet - da in beiden Versionen Funktionen existieren welche es in
der jeweils anderen nicht gibt.
________________________________________________________________________________________


SKRIPT

Eine einfache Textdatei ( Ascii / ANSI ) mit der Endung *.SCR - man kann sie also mit einem
Texteditor ansehen und verändern. Darin speichert man eine feste Befehls-/Eingabefolge welche
dann beim ausführen der Skriptdatei über den Befehlsaufruf "SCRIPT" oder kurz "SR" abgearbeitet
wird.

Eine Skript-Datei erstellen, zB. über NotePad: Neue Datei, Menü Datei,
Speichern unter.. dann als Dateityp "Textdokument" oder "Textdokument - MS-DOS-Format"
auswählen und beim Dateinamen die Endung "TXT" durch "SCR" ersetzen.

Im Skript kann man alles Umsetzen was man manuell/händisch auch direkt über die
Befehlszeile ausführen kann.
Aus diesem Grund kann man in Skripten auch kein DIESEL
einsetzen da DIESEL- Funktionen nur in Menüs funktionieren.

VORTEIL    Skript: Kann auch mehrere Dateien nacheinander verarbeiten. (hier nicht Thema)
NACHTEIL Skript: Im Ablauf eines Skriptes gibt es keine Möglichkeit der Benutzereingabe,
das Skript lässt also keine Unterbrechung zu um dem User die Möglichkeit zu geben eine
Eingabe vorzunehmen.


MAKRO

Makros (auch Menü- und Buttonmakros) sind Befehls-/Eingabefolgen welche in einem Menü
hinterlegt sind. Alle Einträge der Menüs "Datei" "Bearbeiten" usw. aber auch jedem
Button eines Werkzeugkastens ist so ein Makro hinterlegt.

Die Erstellung einer Werkzeugfläche, eines Menüs oder eines Paletteneintrages etc.
ist hier nicht Thema, daher wird auch nicht darauf eingegangen - behandelt wird nur
der Aufbau der hinterlegten Makros.

In Makros kann man alles Umsetzen was man manuell/händisch auch direkt über die
Befehlszeile ausführen kann, plus noch ein wenig mehr (DIESEL).

Benutzereingaben können einbaut werden, jedoch muß die Anzahl fest definiert sein, das
Makro wartet also eine (oder mehrere) Benutzereingaben ab und wird dann weiter abgearbeitet,
auch kann auf DIESEL zurückgegriffen werden, dies kann besonders den LT-User
interessieren da diesem ja kein LISP zur Verfügung steht.


Makro & Skript - Allgemeines

Man nutzt beides immer aus dem gleichen Grund: Man möchte sich die Arbeit erleichtern!

Wenn man Acad nur über die Befehlszeile bedient (genau das macht man hier), so wird man
feststellen das teilweise eine andere Arbeitsweise nötig wird, so muß man zB. Namen von
Systemvariablen wissen welche man vorher einfach über ein paar Mausklicks eingestellt hat.
Auch gibt es einige Befehle welche man für gewöhnlich nutzt - diese aber ein Dialogfenster
haben und das kann man mit einem Makro/Skript nicht steuern. Für viele Fälle gibt es aber
eine extra Befehlszeilenversionen oder ggf. einen anderen Befehl mit dem man das Gleiche
erziehlen kann ! Leider gibt es aber auch einige Ausnahmen (danke AutoDESK)

WENN es zu einem Befehl eine zusätzliche Befehlszeilenversion gibt, dann wird diese mit
vorangestelltem Minus "-" gestartet, populäres Beispiel: Befehl LAYER, hier kommt man mit
einem Makro oder Script nicht weiter weil sich das Dialogfeld "Layereigenschaften-Manager"
öffnet. Es gibt jedoch zum erstellen, editieren und steuern von Layer die Befehlszeilenversion
"-LAYER" weitere Beispiele: -MTEXT, -PLOT oder auch -REIHE

Es gibt aber auch andere Dialogfenster, wie zB. "Datei wählen" , ein Fenster welches zum
speichern oder öffnen/auswählen von Dateien dient kann man umgehen in dem man die SysVar
"FILEDIA" auf 0 stellt, dann wird eine Befehlszeilenversion genutzt. einige andere Dialoge,
zum Beispiel das Fenster des LMAN aus den Expresstools, werden mit der SysVar "CMDDIA" gesteuert.
Die Systemvariable EXPERT kann auch mal hilfreich sein, die Hilfe[F1] dazu listet nicht alle Meldungen auf
die damit unterdrückt werden können, daher ist Expert immer ein Versuch wert.

Es gibt noch einige weitere "ganz normale" Befehle/Systemvariablen die hilfreich sind. Auch wenn
man vorher noch nie etwas davon gehört hat , steht aber alles in der Acadhilfe beschrieben            
Beispiele aus eigener Erfahrung: GRAPHBLD oder WAHL sowie zB. den Geometrierechner CAL

Bester Tip zum erstellen von Skripten und Makros: Die Eingabefolge 1:1 in der Befehlszeile
langsam abarbeiten und praktisch jeden Tastenschlag beachten und notieren
, denn ein Makro/Skript
läuft nur sauber wenn alles 100%ig stimmt. Acad sagt normalerweise ziemlich deutlich was es von
einem verlangt - nachzulesen in der Befehlszeile/Textfenster(F2)

Wenn man Eingaben mit Leerzeichen machen möchte/muß, zB. Speicherpfadangabe mit Leerzeichen,
dann muß man dies ggf. in Anführungszeichen stellen da ein Leerzeichen normalerweise als
als <Enter> interpretiert wird - je nach Situation/Befehl.
Wenn ein Leerzeichen nicht als Enter interpretiert wird (Wenn Acad eine Texteingabe verlangt die Leerzeichen zulässt),
muß man stattdessen im Script den Zeilenumbruch und im Makro das passende Steuerzeichen nutzen.
(wobei man im Makro als Enter sowieso ein Semikolon nehmen sollte wegen der besseren Übersichtlichkeit gegenüber dem Leerzeichen)

Themen in der AutoCAD-Hilfe:
Zum einen natürlich alle Systemvariablen und Befehle, zum anderen aber auch Themen wie
"Verwenden von Sonderzeichen und Steuerzeichen in Makros" Und für Texte auch das Thema
"Textsymbole und Sonderzeichen"
. Für Makro-Geschichten natürlich auch alles was mit DIESEL
zusammenhängt.
Und Weiter: Klick! und noch weiter: Klick!

Es gibt einfach zu viel Möglichkeiten und Ideen um sie hier beschreiben und für jeden
ist ja etwas anderes wichtig, ich nenne hier nur mal 2-3 Dinge als Anregung:
Zum erstellen und manipulieren von Geometrie kann die Nutzung des Geometrierechners "_cal"
von Vorteil sein, aber nur für Vollversion-User. LT-User können sich zum speichern und
abrufen von Text und Zahlenwerten eigene Variablen kreieren mit "SETENV" und "GETENV" .

Für den Vollversion Anwender gibt es hier noch eine kleine Lispfunktion mit deren
Hilfe man DIESEL-Ausdrücke direkt in der Befehlszeile testen kann, gestartet wird die
Funktion mit dem Aufruf "Diesel" (wie damit umzugehen ist kann man im FAQ-Artikel "APPLOAD"
nachlesen, auch sinnig in diesem Fall evtl. der Artikel "ACADDOC" des User FAQ.)
:

Code:

(defun c:DIESEL (/ s)
(while (/= "" (setq s (getstring "\nDIESEL: " T)))(princ (menucmd (strcat "m=" s))))
(princ)
)

*** HelloWorld ***


# An dieser Stelle sollten nun ein paar kommentierte Beispiele folgen, dabei gibt es die Frage ob es für den Anfang lieber
# ein einfach gestricktes Makro sein sollte oder gleich ein richtig Gutes, hierbei ist aber nicht der Nutzen des Makros
# gemeint, sondern der Makro-Aufbau. Es folgt ein einfaches Makro welches dann Schritt für Schritt verbessert wird !

Aufgabe: Automatisch einen Kreis auf einem bestimmten Layer erstellen. Die Aufgabe wird
in 2 Teile gesplittet, zunächst "Kreis erstellen" und dann wird die "Layerzuweisung" behandelt.

Kreis erstellen über die Befehlszeile "per Hand" => Textfenster(F2)
{ meine Tastatureingabe und mein<EnterTastendruck> }

Teil1=Kreis erstellen

Code:
Befehl: KREIS<Enter>
Zentrum für Kreis angeben oder [3P/2P/Ttr (Tangente Tangente Radius)]: 10,5<Enter>

Radius für Kreis angeben oder [Durchmesser]: 2.5<Enter>

Befehl:



Da man im Makro statts einem <Enter> ein Semikolon angibt lautet das Makro also wie folgt:

KREIS;10,5;2.5;


So einfach ist das ! Eine feste Koordinate für das Kreiszentrum kann gewollte und gut sein, man kann
es aber auch flexibler gestalten weil Makros auch Benutzereingaben zulassen! Im Makro wird dafür ein
Backslash eingesetzt, eine Benutzereingabe=einBackslash. Da der User eine Befehlszeileneingabe selbst
mit ENTER bestätigt wird dieses ENTER nicht in das Script eingetragen und falls die Benutzereingabe
ein Mausklick war, so braucht man dabei ja gar kein Enter. Die "10,5" im Makro gibt ja die Koordinate
für das Kreiszentrum an, das ";" danach ist die Bestätigung der Eingabe - beides tauschen wir nun gegen
einen Backslash aus:

KREIS;\2.5;


Jetzt kann der User selbst wählen ob man den Punkt mit der Maus oder über eine Koordinateneingabe
über die Befehlszeile vornimmt - Acad ist es gleich und gibt sich mit beidem zufrieden.

Die Sache mit dem Backslash = Benutzereingabe hat auch einen kleinen nebenefekt: PFADE können
nicht wie gewohnt mit Backslashs, als Ordner-Trennzeichen, angegeben werden, man ersetzt diese
durch Slashs in dem Fall.
Also nicht  D:\toll\hier\meine Datei.txt
sondern    "D:/toll/hier/meine Datei.txt"

Wenn nun zufällig bereits ein Befehl aktiv ist wenn man sein Makro startet, dann erzeugt das einen Fehler,
dies ist einfach zu testen: Befehl LINIE starten und dann direkt das Makro starten, Ergebnis:

Code:
Befehl: LINIE
Ersten Punkt angeben: KREIS

Ungültiger Punkt.
Ersten Punkt angeben:


Man muß also den aktiven Befehl vorher beenden (das wäre ganz gut) aber da auf den User eben kein Verlass
ist muß man eben im Makro dafür sorgen das gerade kein anderer Befehl aktiv ist, das kann mit drücken
der ESCape-Taste erreichen und da es Situationen gibt in denen es noch ein zweites Mal nötig ist nimmt man
gleich 2xESC. Im Makro entspricht die ESC-Taste dem Ausdruck ^C  wie es auch im AutoCAD-Hilfethema
"Verwenden von Sonderzeichen und Steuerzeichen in Makros" dokumentiert ist, also stellen wir "2xESC"
dem bisherigen Makro vorne an:

^C^CKREIS;\2.5;

jetzt läuft es nicht mehr in einen Fehler, auch wenn gerade ein anderer Befehl aktiv war:

Code:
Befehl: LINIE
Ersten Punkt angeben: *Abbruch*

Befehl:
Befehl: KREIS
Zentrum für Kreis angeben oder [3P/2P/Ttr (Tangente Tangente Radius)]: 
<Koordinaten ein> 15,5

Radius für Kreis angeben oder [Durchmesser] <2.5000>: 2.5
Befehl:


(Kurz: Wenn man es nicht ganz bewußt anders benötigt sollte jedes Makro mit "^C^C" anfangen !)


Ende von Teil1, einen Kreis erstellen können wir nun mit einem Makro, ob mit festen Zentrum oder
festem Radius, alles funktioniert hervorragend.

^C^CKREIS;10.5;2.5; Position und Radius fest vorgegeben
^C^CKREIS;10.5;\ Position fest vorgegeben, Radius mit Benutzereingabe
^C^CKREIS;\\ Position und Radius mit Benutzereingabe, dies entspricht dem ganz normalen Befehlsablauf:


Nun haben wir also schon 3 makrospezifische Dinge gelernt:

ENTER=";ESC="^CEine Benutzeringabe="\"


Es folgt ein einziges, dafür aber ausführliches Beispiel für ein Makro und ein Script, beide sollen die
gleiche Aufgabe erledigen. Ich wähle hier jedoch extra ein Beispiel bei dem auch die gravierenden Unterschiede
bzw. Möglichkeiten deutlich werden.

Wer Makros testen möchte der kann seit 2004(mit Extension) bzw. 2005 wunderbar ein Befehlswerkzeug in einer
Werkzeugpalette nutzen - dies ist schneller editierbar wie das testen in einem Menübereich der nur über
den Cui-Dialog verfügbar ist (bzw. dem editieren in MNU/MNS Dateien bis 2005). Leider scheint es ein paar
Ausnahmen zu geben in den ein Makro in der Werkzeugpalette anders arbeitet als in einem Werkzeugkasten zB.
die eine mir bekannte Ausnahme ist das setzen von CECOLOR, dies wird zwar lt. Textfenster ausgeführt aber von
AutoCAD ignoriert wenn das Makro aus einer Werkzeugpalette heraus gestartet wird.

Script: Einfach den [Start]\Zubehör\Editor wählen und loslegen (Datei speichern: entweder als normale *.txt Datei
und hinterher in *.scr umbenennen oder direkt im SpeichernUnter-Dialog "alle Dateien" einstellen (& ANSI) und
dem Dateinamen bereits die passende Extension mitgeben "meinScript1.scr")


Aufgabe: einen bestimmten Layer aktuell stellen ! (damit danach erzeugte Objekte auf diesem Layer liegen zB.)

Weil weder im Makro noch im Script ein Dialogfeld (automatisch) bedient werden kann nehmen wir die
Befehlszeilenversion des Befehls, eigentlich ruft man LAYER auf, die Befehlszeilenversion wird aber
über ein vorangestelltes "-" eingeleitet, also: "-LAYER" , die Befehlszeilenversionen erklären sich
zwar selbst, jedoch gibt es in den excellenten  Acad-Hilfethemen dazu ab und an mal eine nützliche Info dokumentiert !
Auch wichtig: Nicht zu jedem Befehl der ein Dialogfeld öffnet gibt es auch eine Befehlszeilenvariante (LEIDER).

Ich stelle jetzt mal den "Layer1" über die Befehlszeilenversion aktuell, im Textfenster(F2) sieht das so aus:
{ meine TastaturEINGABE und mein<Enter> }

Code:
Befehl: -LAYER<Enter>

Aktueller Layer:  "0"
Option eingeben
[?/Machen/SEtzen/Neu/Umbenennen/EIn/AUs/FArbe/Ltyp/LStärke/MATerial/Plot/FRieren
/Tauen/SPerren/ENtsperren/STatus/Beschreibung/ABstimmen]: SEtzen<Enter>

Namen des zu aktivierenden Layers eingeben oder <Objekt wählen>: Layer1<Enter>
Option eingeben
[?/Machen/SEtzen/Neu/Umbenennen/EIn/AUs/FArbe/Ltyp/LStärke/MATerial/Plot/FRieren
/Tauen/SPerren/ENtsperren/STatus/Beschreibung/ABstimmen]:<Enter>

Befehl:


Da man im Makro statts einem <Enter> ein Semikolon eingebe lautet das Makro also wie folgt:
-LAYER;SEtzen;MeinLay1;;

Falls es beim testen jetzt nicht funktioniert hat liegt das sicher daran das kein Layer "MeinLay1" in
der aktuellen DWG definiert war !? Wenn es funktionierte dann ist jetzt der Layer "MeinLay1" aktuell
und in der Befehlszeile wartet Acad auf neuen Befehle was sich an der Befehlszeile "Befehl:" zeigt.

Also: Ich muß zunächst sicherstellen das der Layer den ich im Makro SEtzen will überhaupt vorhanden
ist, sonst läuft das Makro in einen Fehler ! Netterweise schaltet AutoCAD den neu erstellten Layer
automatisch auf "aktuell" und wenn der Layer den man erstellen möchte bereits vorhanden ist, so
nimmt das der Befehl "-LAYER" bei der Option "MACHEN"(= Layer erstellen / siehe F1) zur Kenntnis
und schaltet den vorhandenen einfach aktuell und meckert nicht das der zu erstellende Layername
bereits vorhanden ist, sehr nett Herr AutoDesk.

geändertes Makro:
-LAYER;Machen;MeinLay1;;

Ob es den Layer nun vorher bereits gibt oder nicht, er wird ggf. erstellt und aktuell gesetzt !
Es sei denn..
Leider gibt es schon wieder ein mögliches Problem, wenn der Layer bereits existiert aber gefroren ist,
dann kann der Layer nicht zum aktuellen gemacht werden, also muß auch dies sichergestellt werden.
Ich ändere das Makro ab und verwende es von nun an wie folgt:

geändertes Makro:
-LAYER;TAUEN;MeinLay1;MACHEN;MeinLay1;;


Damit die ursprünglich gestellte Aufgabe "Kreis auf bestimmten Layer erstellen" erfüllt wird gibt es nun
zwei mögliche Vorgehensweisen denkbar, man erstellt den Kreis auf dem richtigen Layer oder man erstellt
den Kreis und legt ihn hinterher auf den richtigen Layer:


Teil1 - Kreis erstellen:    KREIS;10.5;2.5;
Teil2 - Layer einstellen:   -LAYER;TAUEN;MeinLay1;MACHEN;MeinLay1;;

Direkt auf richtigem Layer erstellen bedeutet man muß darauf achten das der Layer existiert und nicht gefroren ist:
^C^C-LAYER;TAUEN;MeinLay1;MACHEN;MeinLay1;;KREIS;10.5;2.5;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Im Script entspricht ein Zeilenumbruch dem <Enter> , jedoch wird das Script so sehr unübersichtlich
und ich nutze daher oftmals ein Leerzeichen wenn ich innerhalb eines Befehls <Enter> benötige, nur
für das letzte <Enter> mit dem ich den Befehl wieder verlasse nutze ich den Zeilenumbruch, einfach
weil das Script so besser "zu lesen" ist.
(Ausnahme: Acad fragt einen Textwert ab, da merkt man dann nämlich das ein Leerzeichen kein Enter ist ;) )

Hinweis: Fängt eine Zeile im Script mit einem Semikolon an so wird diese Zeile als Kommentar gewertet und nicht verarbeitet!

Code:

;-Scriptanfang
-LAYER
SEtzen
Layer1




(hier ist wichtig das es nach "MeinLay1" 2 Zeilenumbrüche gibt weil wir danach 2x Enter
benötigen, daher die zwei leeren Zeilen am ende des Script, siehe auch oben / Textfenster)

jetzt meinen 'Stil' den ich dannn auch weiter verwenden werde:

Code:

;-Scriptanfang
-LAYER SEtzen Layer1



(ich habe hier keinen Zeilenumbruch vergessen sondern nach dem "MeinLay1" noch ein Leerzeichen als Enter)


Das Makrobeispiel oben "Kreis auf bestimmten Layer erstellen" könnte also so aussehen:

Code:

-LAYER
TAUEN MeinLay1
MACHEN MeinLay1

KREIS
10.5
2.5


~ vorläufiges Ende der Geschichte ~

Koordinaten werden falsch übernommen ? Das Objekt an die Falsche Stelle verschoben ?
Wer mit Makro, Script, Command oder SendCommand AutoCAD-Zeichnungen verändert, der sollte
unbedingt die Systemvariable OSNAPCOORD prüfen bzw. einstellen, siehe hier: FAQ: OsnapCoord