| |
| Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte |
Autor
|
Thema: Werte von Attributen in Blöcken ändern (1908 mal gelesen)
|
Maier2018 Mitglied Schlaumaier
Beiträge: 25 Registriert: 15.01.2018 Autocad 2021
|
erstellt am: 18. Jan. 2021 13:53 <-- editieren / zitieren --> Unities abgeben:
Hallo Zusammen, ich möchte nach dem Einfügen von einem Block, Attributen einen bestimmten Wert zuweisen. Das wäre mit setpropertyvalue recht einfach gelöst. Nur sind manche Attribute mehrfach im Block vorhanden - also Duplikate. D.h. ich habe einen Block in dem "Attribut1" drei mal vorhanden ist und ich möchte allen drei den selben Wert zuweisen. Momentan habe ich nur eine nicht so elegante Lösung herausgefunden: Code:
(setpropertyvalue blockname "ATT1" WERT) (setpropertyvalue blockname "ATT11" WERT) (setpropertyvalue blockname "ATT12" WERT)
Es scheint, dass Autocad die Attributnamen einfach nur durchnummeriert. Ich schätze, dies wäre durch eine Schleife einfach zu lösen, nur habe ich wenig Erfahrung mit Schleifen. Hoffe jemand kann mir da helfen... Vielen Dank vorab! Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Andreas Kraus Mitglied Elektrotechniker
Beiträge: 1356 Registriert: 11.01.2006 WIN 10 ACAD 2022
|
erstellt am: 18. Jan. 2021 19:01 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
Hallo Maier 2018, ich hoffe Axels Seiten sind dir bekannt. http://www.autolisp.info/index.htmlDa ist sehr viel sehr gut erklärt. Schleifen: Es gibt Foreach, While und Repeat als Schleifen. Außerdem noch Vlax-For für Collections und natürlich Mapcar für die Anwendung von Funktionen auf Listen. Hier sind Repeat und While erklärt: http://www.autolisp.info/schleifen1.html Foreach ist hier: http://www.autolisp.info/listen6.html Und Vlax-For hier: http://activex.autolisp.info/collections.html Mapcar würde ich mal ganz separat behandeln, ist aber hier meine Lieblinsfunktion weil sie auch eine Rückgabe liefert. Bei deinem Problem dass du vielleicht nicht weist wieviele Attribute mit welchem Namen an einem BlocK hängen würde ich einfach mal alle auslesen und dann die bearbeiten die ich brauche. (vlax-invoke obj_name 'GetAttributes) liefert die eine Liste der Attribute am Block. Bitte beachte dass hier nicht der Elementname sondern der Objektname gebraucht wird. Diese Liste mit einer Schleife abarbeiten und in der Schleife nur was arbeiten wenn der Attributname passt. Code: (foreach att (vlax-invoke obj_name 'GetAttributes) (if (= (vla-get-tagstring att) "ATT1") (vla-put-textstring att "neuer Wert") ) )
Ist jetzt einfach mal "dreckig runtergetippt" also ohne jegliche Fehlerüberwachung usw. (ist z.B. der Layer entsperrt) und natürlich kannst/musst du "ATT1" und "neuer Wert" deinen Bedürfnissen anpassen. Wie du an den Objektnamen vom Block kommst ist auch deine Sache Viel Spass damit ------------------ Geht nicht, gibts nicht Gruß Andreas http://kraus-cad.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Maier2018 Mitglied Schlaumaier
Beiträge: 25 Registriert: 15.01.2018 Autocad 2021
|
erstellt am: 19. Jan. 2021 14:37 <-- editieren / zitieren --> Unities abgeben:
Hallo Andreas, danke für die Antwort. Tatsächlich habe ich gestern schon die while und repeat Schleifen auf Axels Seite studiert. Ich habe aber wohl eine wichtige Kleinigkeit bei meinem Problem verschwiegen: da wir eine OEM Version von Autocad erworben haben, sind bei uns alle ActiveX Befehle "gesperrt"... Die können wir also leider nicht ausführen. Autocad stellt sich einfach dumm und sagt es kennt den Befehl nicht. Wenn du mir nun einen Tipp geben könntest, mit welchen Befehlen ich die Schleife aufbauen könnte, ohne ActiveX... Meine Überlegung war, dass ich eine Schleife bastel die einen Block nach einem Attributnamen durchsucht mit einem Platzhalter am Ende - Also Suche nach "ATT1*Platzhalter*" und überschreibe den Wert mit "Wert1". >>>> Nach dem ich den Text oben getippert habe, fällt mir auf, dass die Schleife von dir genau das macht, oder?
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
CADwiesel Moderator CAD4FM UG
Beiträge: 1968 Registriert: 05.09.2000 AutoCAD, Bricscad Wir machen das Mögliche unmöglich
|
erstellt am: 19. Jan. 2021 14:53 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
Im Kern brauchst du ENTNEXT. Damit hangelst du dich durch die Attribute, wenn deine Blockref welche hat. Hier mal ein Lisp codeschnipsel mit dem du was machen könntest... Code: (defun attchange (elem attname gcwert wert / aslst) (setq aslst (entget elem)) (if (= (cdr (assoc 0 aslst)) "INSERT") (progn (if (= (cdr (assoc 66 aslst)) 1) (progn (setq aslst (entget (entnext (cdr (assoc -1 aslst))))) (while (/= (cdr (assoc 0 aslst)) "SEQEND") (if (= (cdr (assoc 2 aslst)) attname) (progn (if (= (cdr (assoc gcwert aslst)) "") (entmod (subst (cons gcwert wert) (assoc gcwert aslst) aslst ) ;_ end of subst ) ;_ end of entmod (entmod (subst (cons gcwert (strcat (cdr (assoc gcwert aslst)) ";" wert) ) ;_ end of cons (assoc gcwert aslst) aslst ) ;_ end of subst ) ;_ end of entmod ) ;_ end of if (entupd (cdr (assoc 330 aslst))) ) ;_ end of progn ) ;_ end of if (setq aslst (entget (entnext (cdr (assoc -1 aslst)))) ) ;_ end of setq ) ;_ end of while ) ;_ end of progn ) ;_ end of if ) ;_ end of progn ) ;_ end of if )
Programmaufruf könnte so aussehen:
Code: (attchange elem ;insert Ename (car(entsel)) "RNR" ;Attributname 1 "neuerWert" ; der zu setzende Wert )
------------------ Gruß CADwiesel Besucht uns im CHAT
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Maier2018 Mitglied Schlaumaier
Beiträge: 25 Registriert: 15.01.2018 Autocad 2021
|
erstellt am: 19. Jan. 2021 15:23 <-- editieren / zitieren --> Unities abgeben:
|
cadffm Moderator 良い精神
Beiträge: 21533 Registriert: 03.06.2002 Alles
|
erstellt am: 19. Jan. 2021 15:39 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
|
Maier2018 Mitglied Schlaumaier
Beiträge: 25 Registriert: 15.01.2018 Autocad 2021
|
erstellt am: 20. Jan. 2021 08:15 <-- editieren / zitieren --> Unities abgeben:
Der Codeschnipsel von CADWiesel funktioniert wunderbar für mich! Musste nur etwas abgeändert werden, damit der Attributwert ersetzt und nicht mittels strcat an den ursprünglichen Wert angehängt wird. DANKE! Code:
(defun attchange (elem attname gcwert wert / aslst) (setq aslst (entget elem)) (if (= (cdr (assoc 0 aslst)) "INSERT") (progn (if (= (cdr (assoc 66 aslst)) 1) (progn (setq aslst (entget (entnext (cdr (assoc -1 aslst))))) (while (/= (cdr (assoc 0 aslst)) "SEQEND") (if (= (cdr (assoc 2 aslst)) attname) (progn (if (= (cdr (assoc gcwert aslst)) "") (entmod (subst (cons gcwert wert) (assoc gcwert aslst) aslst ) ;_ end of subst ) ;_ end of entmod (entmod (subst (cons gcwert wert ) ;_ end of cons (assoc gcwert aslst) aslst ) ;_ end of subst ) ;_ end of entmod ) ;_ end of if (entupd (cdr (assoc 330 aslst))) ) ;_ end of progn ) ;_ end of if (setq aslst (entget (entnext (cdr (assoc -1 aslst)))) ) ;_ end of setq ) ;_ end of while ) ;_ end of progn ) ;_ end of if ) ;_ end of progn ) ;_ end of if )
Habe auch den Testblock+Testprogramm angehängt, mit dem ich das Programm getestet habe. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Bernd P Ehrenmitglied V.I.P. h.c. cook-general
Beiträge: 3358 Registriert: 07.06.2001 W10-64bit, AMD Ryzen 7 3700X,32GB RAM, Sapphire Pulse Radeon RX 570 8G G5, Canon TX-3000 MFP, Maus Cherry MW4500, Sub:Infrastructure Design Suite, Office 365
|
erstellt am: 20. Jan. 2021 11:35 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
Servus, hab mir das LISP angepasst, es wird kein Block eingefügt sondern es muss einer ausgewählt werden. Hab 3 Fragen dazu. 1. Die Auswahl von dynamischen Blöcken funktioniert mit "(setq obj_ename (car(entsel "\nBlock wählen: ")))" nicht. mit "(setq obj_ename (vlax-ename->vla-object (car (entsel))))" bekomme ich "Fehlerhafter Argumenttyp: lentityp #<VLA-OBJECT IAcadBlockReference 00000173bd877d88>" 2. Wenn die Attribute einen Mehrzeiligen Inhalt hatten funktioniert es auch nicht mehr. 3. Kann man den Inhalt aus einem bestimmten Attribut als Vorgabe für WERT1 machen? ------------------ <----- Bitte Systeminfo eintragen, warum siehst du hier. Schöne Grüsse aus der Steiermark Bernd P. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadffm Moderator 良い精神
Beiträge: 21533 Registriert: 03.06.2002 Alles
|
erstellt am: 20. Jan. 2021 12:35 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
Ich fange mal an >>1. Die Auswahl von dynamischen Blöcken funktioniert mit "(setq obj_ename (car(entsel "\nBlock wählen: ")))" nicht Mit entsel wählt man höchstens Blockreferenzen, nie einen Block. Dabei sollte dann auch völlig egal sein ob die Blockreferenz von einem dynamischen Block stammt oder nicht. >>"mit "(setq obj_ename (vlax-ename->vla-object (car (entsel))))" bekomme ich "Fehlerhafter Argumenttyp: lentityp #<VLA-OBJECT IAcadBlockReference 00000173bd877d88>" Daran ist aber nicht die Zeile an sich schuld, aber der restliche code erwartet an obj_ename wohl keine vla-objekt, sondern einen ENAME. Die Änderungen der Zeile war also nicht nur falsch, sondern auch noch unnötig. Deine Zeile von 1.) sollte also die einzige Anpassung sein welche für BlockREFERENZ wählen nötig wird (neben dem entfernen der command-EINFÜGE Zeile natürlich) (setq obj_ename (car(entsel)))
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Bernd P Ehrenmitglied V.I.P. h.c. cook-general
Beiträge: 3358 Registriert: 07.06.2001 W10-64bit, AMD Ryzen 7 3700X,32GB RAM, Sapphire Pulse Radeon RX 570 8G G5, Canon TX-3000 MFP, Maus Cherry MW4500, Sub:Infrastructure Design Suite, Office 365
|
erstellt am: 20. Jan. 2021 15:51 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
1. *faceplam* hab es am Anfang anscheinend an einem dyn Block mit mehreren Zeilen versucht.... Aus einem anderen meiner Fragen geholt, jetzt klappt es auch mit mehrzeiligen Attribute. https://ww3.cad.de/foren/ubb/Forum145/HTML/003960.shtml Code: (defun attchange (elem attname gcwert wert / aslst) (setq aslst (entget elem)) (if (= (cdr (assoc 0 aslst)) "INSERT") (progn (if (= (cdr (assoc 66 aslst)) 1) (progn (setq aslst (entget (entnext (cdr (assoc -1 aslst))))) (while (/= (cdr (assoc 0 aslst)) "SEQEND") (if (= (cdr (assoc 2 aslst)) attname) (progn (if (= (cdr (assoc gcwert aslst)) "") (entmod (subst (cons gcwert wert) (assoc gcwert aslst) aslst ) ;_ end of subst ) ;_ end of entmod (entmod (subst (cons gcwert wert) ;_ end of cons (assoc gcwert (reverse aslst)) aslst ) ;_ end of subst ) ;_ end of entmod ) ;_ end of if (entupd (cdr (assoc 330 aslst))) ) ;_ end of progn ) ;_ end of if (setq aslst (entget (entnext (cdr (assoc -1 aslst)))) ) ;_ end of setq ) ;_ end of while ) ;_ end of progn ) ;_ end of if ) ;_ end of progn ) ;_ end of if )
------------------ <----- Bitte Systeminfo eintragen, warum siehst du hier. Schöne Grüsse aus der Steiermark Bernd P. [Diese Nachricht wurde von Bernd P am 20. Jan. 2021 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Bernhard GSD Mitglied
Beiträge: 482 Registriert: 29.08.2002 AutoCAD 2020(Deu); Windows 10 PRO x64(Deu)
|
erstellt am: 01. Feb. 2021 15:41 <-- editieren / zitieren --> Unities abgeben: Nur für Maier2018
Ich verwende 2 Lisp-Befehle zum Attribut-Handling: (:attget [blockname]) Liefert Dotted-pair Liste, die mit (CDR (ASSOC...) auszulesen ist. Code: (DEFUN :attget (#name / #att #elem #rückliste #ende) (WHILE (NOT #ende) (SETQ #elem (ENTGET (SETQ #name (ENTNEXT #name)))) (IF (= (CDR (ASSOC 0 #elem)) "SEQEND") (SETQ #ende T) (SETQ #rückliste (CONS (CONS (CDR (ASSOC 2 #elem)) (CDR (ASSOC 1 #elem))) #rückliste)) ) ) #rückliste )
(:attakt [blockname] [attributbezeichnung] [neuerwert])
Code: (DEFUN :attakt (#name #bez #wert / #brk #elem) (WHILE (NOT #brk) (SETQ #elem (ENTGET (SETQ #name (ENTNEXT #name)))) (IF (= (CDR (ASSOC 0 #elem)) "SEQEND")(SETQ #brk T) (IF (= (CDR (ASSOC 2 #elem)) #bez) (PROGN (SETQ #elem (SUBST (CONS 1 #wert)(ASSOC 1 #elem) #elem)) (ENTMOD #elem)(ENTUPD #name) ) ) ) ) )
------------------ Gruß aus Wien Bernhard Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |