Atribut Auslesen - Speichern unter / Lisp
nebuCADnezzar 12. Dez. 2019, 11:18

Moinmoin zusammen

Ich steh mal wieder aufm Schlauch, wo ich doch dachte dass is einfach :-)
Meistens kann ich mir LISP's suchen und die mir so anpassen wie ichs brauche, meine eigenen Programierfähigkeiten sind leider wegen nichtnutzens sehr verschrumpelt...

Also ich habe nen spezifischen Block aus dem ich genau ein spezifisches Atribut auslesen will und damit dann einfach nur speichern unter (Dateiname=Attribut)

Leider hab ich nur "wähle Block" Lisps mit andren Funktionen gefunden die mich dann überforderten nur den von mir gewünschten codeschipsel zu stibizen...

Gerne nem ich mal wieder n schubser in die richtige Richtung :-)

Schöne Grüsse
nubu

cadffm 12. Dez. 2019, 11:29

Willst du die Blockreferenz selber wählen (oder das Programm selbsttätig)?
Falls du die Blockreferenz wählen möchtest:
Ist der aktuelle Attributwert sichtbar am Bildschirm?

nebuCADnezzar 12. Dez. 2019, 12:50

Hallo cadffm

Das Programm soll den Block+Atribut selbständig auswählen. Es gibt den Block auch nur einmal (zur Sicherheit wäre eine "in diesem Ansichtfenster" abfrage möglich)
Es handelt sich um den Plankopf, und ein (sichtbares) Attribut davon möchte ich als Dateinamen.

Am Schluss möchte ich "speichern-spezial" drücken und das dwg wird mit dem Attribut wert als Dateinamen gespeichert.
Soll den Sinn haben dass ich den Namen nicht von Hand rumkopiern muss.

Und ich möchte "layouts_to_dwg.lsp" was ich irgendwo gefunden hab noch optimieren dass ich "speichern-spezial" da auch integriere damit diese auch grad richtig abgespeichert werden!

Gruss

cadffm 12. Dez. 2019, 13:04

Wenn es kein dynamischer Block ist, dann nimm dieses hier:
https://ww3.cad.de/foren/ubb/Forum145/HTML/002860.shtml#000002

Für den Fall der Fälle ist auf die GROSSkleinSchreibung des Attributnamens zu achten,
also immer daran denken oder bezogen auf den Link ein strcase hinzufügen
(=(strcase(cdr(assoc 2(entget obj))))"RAUM-NR:"))
(=(strcase(cdr(assoc 2(entget obj))))(strcase "Raum-Nr:")))

Auch wenn du es jetzt einmal richtig machst, in drei Jahren stolperst du (unnötig) darüber, also einen Kommentar ergänzen oder das strcase.

nebuCADnezzar 12. Dez. 2019, 14:28

So nu hatte ich doch nen anderen Ansatz gefunden aber noch zwei Probleme:
[URL https://forums.augi.com/showthread.php?163765-Select-a-block-by-name-in-paperspace][/URL]

Bei Befehl: AED_GETNUMBER
; Fehler: Fehlerhafter Argumenttyp: lselsetp nil

Bei Befehl: SPEICHERNAFG
; Fehler: no function definition: FILEDIA


Code:
(defun C:AED_GetNumber ( / blk tag val enx)
  (setq ssSelections (ssget "x" (list (cons 0 "insert")(cons 2 "Plankopf Arbonia")(cons 410 (getvar "ctab"))))) ; Change "myBlock" to name of your block
  (setq blk              (ssname ssSelections 0))
  (setq tag "05_DNR") ;Change "myTag" to the name of the attribute
  (while
    (and
      (null val)
      (= "ATTRIB"
(cdr (assoc 0 (setq enx (entget (setq blk (entnext blk))))))
      )
    )
    (if (= (strcase tag) (strcase (cdr (assoc 2 enx))))
      (setq val (cdr (assoc 1 enx)))
    )
  )
  (princ (atoi val))
);C:AED_GetNumber

(defun c:speichenrAFG ()
(setvar "FILEDIA" 0)
  (setq n (C:AED_GetNumber))
  (command "_SAVEAS" "2018" n)
(setvar "FILEDIA" 1)
)


cadffm 12. Dez. 2019, 14:34

Du wirst anfangen müssen die mit den Basics zu beschäftigen damit "etwas anpassen" demnächst nocht "etwas besser" funktioniert.
Vielleicht versuchst du es auch mal mit dem Link von mir, der ist nicht so speziell wie dein Netzfundstück.


Bei Befehl: AED_GETNUMBER
; Fehler: Fehlerhafter Argumenttyp: lselsetp nil
Es wurde keine Blockreferenz gefunden und SSNAME läuft deswegen in diesen Fehler

Bei Befehl: SPEICHERNAFG
; Fehler: no function definition: FILEDIA
Dazu kann ich nichts sagen, denn diese Funktion hast du nicht gepostet, wir kennen diese also überhaupt nicht.

nebuCADnezzar 12. Dez. 2019, 14:52

Ich hatte mal nen LISP Kurs und hab früher auch einiges Programmiert, leider alles schon länger her, die Basics sind leider sehr, sehr eingerostet...
Aber ich hab grad einiges wieder geschafft, meine alten Reaktoren laufen wieder
(damals gelernt auf http://activex.autolisp.info/layreactor.html)
Ich hol mir alle Daten automatisch vom Plankopf vom Planlistenexcel etc, etc,...

Also ich für meinen Teil bin soweit ganz stolz dass ich dass bisher geschafft hab   

Aber ja da ich die Programme nicht 100% durchschaue ist "etwas anpassen" und vorallem das debuggen schwierig... Aber ich hab ne Theorie! Natürlich ist mein blöder Block dynamisch und wird wohl desshalb nicht gefunden

PS zuunterst im code ist defun c:speichenrAFG nuer 6 Zeilen 

cadffm 12. Dez. 2019, 15:05

Zitat:
Original erstellt von nebuCADnezzar:
PS zuunterst im code ist defun c:speichenrAFG nuer 6 Zeilen   


Das ist richtig, aber das ist ja nicht die Funktion welche die Fehlermeldung lostritt:

Bei Befehl: SPEICHERNAFG
; Fehler: no function definition: FILEDIA


Und wenn es nur ein Schreibfehler war.. tja, wir können, wie das Programm auch, nur mit dem arbeiten was wir haben 

nebuCADnezzar 12. Dez. 2019, 16:04

Hallo cadffm

So ich hab nun Dein Vorschlag zum laufen gebracht, den Block muss ich nicht als dynamisch haben, "attlesen" gibt auch den richtigen Wert zurück, nur das ichs nicht hinbekomme "attlesen" an "name" zu übergeben, bzw. "name" im "command" nicht als Wert verarbeitet wird sondern nur name...
(ich bin mir ziemlich sicher dass das ne absolut einfache Grundlagenübung wäre      ich hab auch die Theorie dass es was mit den Klammern nach defun() zu tun hat, aber alle bisher nach Zufall getesteten Varianten funktionierten auch nicht)

Code:
(DEFUN C:attlesen( / ATTWERT_LISTE AWS N)
  (if (setq aws (ssget "X" (list '(0 . "INSERT"))))
    (progn
      (setq n 0)
      (repeat (sslength aws)
        (if (=(vla-get-EffectiveName(vlax-ename->vla-object (ssname aws n)))"Plankopf_Arbonia")
          (setq AttWert_liste (cons (Test2:AttListe (ssname aws n))AttWert_liste)))
        (setq n (+ n 1))))
    (alert "Keine Blöcke vorhanden."))
  AttWert_liste)
     
(defun attlesen:AttListe (obj / AttWert)
  (if (and (entnext obj)(=(cdr(assoc 0(entget (entnext obj))))"ATTRIB"))
    (while (and(setq obj (entnext obj))
      (/= "SEQEND" (cdr(assoc 0(entget obj)))))
      (if (and(=(cdr(assoc 0(entget obj)))"ATTRIB")
              (=(strcase(cdr(assoc 2(entget obj))))(strcase "05_DNR")))
(setq AttWert (cdr(assoc 1 (entget obj)))))))
  AttWert)

(defun c:speichernAFG ()
  (setvar "FILEDIA" 0)
  (setq name (C:attlesen))
  (command "_SAVEAS" "2018" name)
  (setvar "FILEDIA" 1)
)     


cadffm 12. Dez. 2019, 16:29

Und hier weiß der Helfer wieder nicht was es mit Test2:AttListe auf sich hat und warum du eine attlesen:AttListe postest.
Aufräumen wäre mein erster Tip, dann stolpert man weniger.

Wenn dann alles geradeaus läuft so hilft sicher anstatt einen AutoCAD-Befehl zu definieren mit (DEFUN C:
ein einfaches (DEFUN zu nutzen.

Das Ergebnis ist dann aber evtl eine LISTE, da ich die verwendete Funktion von dir aber nicht kenne: Keine Ahnung.
Wenn es so ist, dann wäre
  (if (setq name (attlesen)) (command "_SAVEAS" "2018" (car name)))
die Lösung, falls es noch keine Datei mit dem Namen an dieser Stelle gibt.

Ich wohl zu gut drauf heute und lassen den Thread mal in Ruhe 


nebuCADnezzar 12. Dez. 2019, 18:19

Hallo cadffm

Vielen dank trotzdem fürs versuchen zu helfen, ich hab nun noch n paar Stunden gepröbelt aber habs leider nicht hinbekommen...

Mein anfangs Gedanke dass den Attributstext
"12345 Planname" einfach nach speichere unter "12345 Planmae.dwg"
nich so schwer sein kann hat wohl getäuscht.

Schöne Grüsse
Ich mach nu Feierabend :-)

cadffm 12. Dez. 2019, 23:08

Aber das war doch schon fast fertig? Zumindest wenn ich anstatt dem test2:attliste die andere gepostete nutze,
für dynamische blöcke läuft das auch.

Nicht um eine bestmögliche oder schöne Anpassung zu machen, sondern mit möglichst wenig Änderungen.

Code:

(defun attlesen ( BNAME ATTTAG / ATTWERT_LISTE AWS N)

(defun attlesen:AttListe (obj / AttWert)
  (if (and (entnext obj)(=(cdr(assoc 0(entget (entnext obj)))) "ATTRIB"))
    (while (and(setq obj (entnext obj))
      (/= "SEQEND" (cdr(assoc 0(entget obj)))))
      (if (and(=(cdr(assoc 0(entget obj)))"ATTRIB")
              (=(strcase(cdr(assoc 2(entget obj))))(strcase ATTTAG)))
          (setq AttWert (cdr(assoc 1 (entget obj))))
      )
   )
  )
  AttWert
)
 
  (if (setq aws (ssget "_X" '((0 . "INSERT")(66 . 1))))
    (progn
      (setq n 0)
      (repeat (sslength aws)
        (if (= (strcase(vla-get-EffectiveName(vlax-ename->vla-object (ssname aws n)))) (strcase BNAME))
            (setq AttWert_liste (cons (attlesen:AttListe (ssname aws n)) AttWert_liste))
)
        (setq n (+ n 1))
      )
    )
    (alert "Keine Blöcke vorhanden.")
   )
  AttWert_liste
)
    


(defun c:speichernAFG ()
  (if (/= 1 (length(setq name (attlesen "Plankopf_Arbonia" "05_DNR"))))
      (alert (strcat "ABBRUCH - Gefundene Attribute: " (itoa (length name))))
      (command "_SAVEAS" "2018" (car name)) ; Und wenn es bereits eine Datei gibt und es nicht die aktuelle ist.?
  )
(princ)
)



   
nebuCADnezzar 14. Jan. 2020, 13:16

Hallo cadffm

So ging ein wenig, es geht grad drunter und drüber...
Es hatte sich irgendwo n vermaledeiter Leerschlag eingeschlichen beim Blocknamen darum hatte ich Probleme...

Vielen, vielen Dank nochmal!

Sobald ich mal noch n paar min Zeit finde versuch ich dann den aktuellen Speicherpfad mit zu übergeben oder das Speichern unter Fenster zu öffnen damit man den Pfad wählen kann.

Schöne Grüsse
nebu