CADXChange

Tutti i comandi LISP

CXATTCOPYBlocchi e attributiVersione 1.0.0Provato in AutoCAD

Copiare i valori degli attributi da un blocco ad altri

Prende i valori degli attributi di un blocco e li scrive negli altri blocchi selezionati, per tutti i tag oppure solo per quelli indicati.

Come si usa

  1. Digita CXATTCOPY e clicca il blocco di origine.
  2. Seleziona i blocchi da compilare.
  3. Inserisci i tag da copiare, separati da virgole, oppure - per tutti.

Da sapere

  • Vengono copiati solo i tag presenti in entrambi i blocchi.

Caricarlo in AutoCAD

  1. Salva il file dove preferisci.
  2. Digita APPLOAD, scegli il file e premi Carica.
  3. Digita il nome del comando: CXATTCOPY.

Per averlo a ogni avvio, aggiungilo alla Raccolta di avvio nella stessa finestra, oppure carica un'intera cartella in una volta con il caricatore facoltativo. Il caricatore facoltativo

Provato in AutoCAD (versione completa). Altri programmi che eseguono AutoLISP potrebbero funzionare, ma non sono stati provati.

Il codice

Testo semplice, niente di nascosto. Copialo in un file chiamato cxattcopy.lsp oppure scaricalo.

;;; ============================================================================
;;; CXATTCOPY - Copy attribute values from one block to others
;;; Version 1.0.0
;;; CADXChange LISP tools - https://cadxchange.net/resources/lisp/cxattcopy
;;; Tested in: AutoCAD (full version). Other programs that run AutoLISP may work but are not tested.
;;; Copyright (c) CADXChange. Free for personal and commercial use; do not resell or
;;; republish it as a collection. Terms: https://cadxchange.net/legal/lisp-terms
;;; ============================================================================

;; Copy attribute values from the block SOURCE to every block in TARGETS that has the same tags.
;; TAGS is a list of tag names, or nil for all tags of the source. Returns how many values were copied.
(defun cx:attcopy-run (source targets tags / n)
  (setq n 0)
  (foreach e targets
    (if (/= e source)
      (foreach tg (if tags tags (cx:tags (list source)))
        (if (and (cx:att-find e tg) (cx:att-find source tg))
          (progn
            (cx:att-set e tg (cx:att-get source tg))
            (setq n (1+ n)))))))
  n)

(defun c:CXATTCOPY ( / *error* cx:sv r source ss tags answer n)
  (setq *error* cx:err)
  (setq r (entsel "\nClick the block to copy the attribute values from: "))
  (cond
    ((null r))
    ((/= (cx:dxf 0 (entget (car r))) "INSERT") (princ "\nThat is not a block."))
    ((null (cx:attribs (car r))) (princ "\nThat block has no attributes."))
    (T
     (setq source (car r))
     (princ (strcat "\nAttributes: " (cx:join (cx:tags (list source)) ", ")))
     (if (setq ss (ssget '((0 . "INSERT") (66 . 1))))
       (progn
         (setq answer (cx:ask-str "Tags to copy, separated by commas (- for all)" "-"))
         (setq tags (if (member answer '("-" "")) nil (mapcar 'cx:trim (cx:split answer ","))))
         (cx:start '(("CMDECHO" . 0)))
         (setq n (cx:attcopy-run source (cx:ss->list ss) tags))
         (princ (strcat "\n" (itoa n) " value(s) copied."))
         (cx:end)))))
  (princ))


;;; ---- Shared helpers (used by the command above; identical in every CADXChange tool) ----

(defun cx:dxf (code ed)
  (cdr (assoc code ed)))

;; The ATTRIB entities of a block reference, in order.
(defun cx:attribs (ins / e out)
  (setq e (entnext ins))
  (while (and e (= (cx:dxf 0 (entget e)) "ATTRIB"))
    (setq out (cons e out) e (entnext e)))
  (reverse out))

;; The attribute tags found in a list of block references, each once, in order of appearance.
(defun cx:tags (names / out)
  (foreach e names
    (foreach a (cx:attribs e)
      (if (not (member (strcase (cx:dxf 2 (entget a))) (mapcar 'strcase out)))
        (setq out (append out (list (cx:dxf 2 (entget a))))))))
  out)

;; The ATTRIB of a block reference with the tag TAG (any case), or nil.
(defun cx:att-find (ins tag / r)
  (foreach a (cx:attribs ins)
    (if (and (not r) (= (strcase (cx:dxf 2 (entget a))) (strcase tag))) (setq r a)))
  r)

;; Replace the text of a TEXT, ATTRIB, ATTDEF or MTEXT.
(defun cx:text-set (ename str / ed out)
  (setq ed (entget ename))
  (if (= (cx:dxf 0 ed) "MTEXT")
    (progn
      ;; MTEXT stores text in 250-character pieces: 3 groups for the first pieces, 1 for the last
      (foreach p ed (if (not (member (car p) '(1 3))) (setq out (cons p out))))
      (setq out (reverse out))
      (while (> (strlen str) 250)
        (setq out (append out (list (cons 3 (substr str 1 250)))) str (substr str 251)))
      (setq ed (append out (list (cons 1 str)))))
    (setq ed (subst (cons 1 str) (assoc 1 ed) ed)))
  (entmod ed)
  (entupd ename)
  T)

;; Set the attribute TAG of a block reference to VALUE; returns T when the block has that attribute.
(defun cx:att-set (ins tag value / a)
  (if (setq a (cx:att-find ins tag))
    (progn (cx:text-set a value) (entupd ins) T)))

(defun cx:att-get (ins tag / a)
  (if (setq a (cx:att-find ins tag)) (cx:dxf 1 (entget a))))

;; Close the undo step and put the system variables back.
(defun cx:end ()
  (foreach v cx:sv (setvar (car v) (cdr v)))
  (command "_.UNDO" "_End")
  (setq cx:sv nil)
  (princ))

;; Error handler: restores everything, stays quiet on Esc.
(defun cx:err (msg)
  (if (> (getvar "CMDACTIVE") 0) (command))
  (cx:end)
  (if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")))
    (princ (strcat "\nError: " msg)))
  (princ))

(defun cx:join (lst delim / out)
  (setq out "")
  (foreach s lst
    (setq out (if (= out "") s (strcat out delim s))))
  (if lst out ""))

;; Ask for a string (spaces allowed) with a default; "-" means an empty string.
(defun cx:ask-str (msg def / v)
  (setq v (getstring T (strcat "\n" msg " <" def ">: ")))
  (cond ((= v "") def) ((= v "-") "") (T v)))

;; Remove spaces and tabs at both ends.
(defun cx:trim (s / a b)
  (setq a 1 b (strlen s))
  (while (and (<= a b) (member (substr s a 1) '(" " "\t"))) (setq a (1+ a)))
  (while (and (>= b a) (member (substr s b 1) '(" " "\t"))) (setq b (1- b)))
  (substr s a (max 0 (1+ (- b a)))))

;; Split STR at every DELIM (a one-character string) into a list of strings.
(defun cx:split (str delim / out cur i c)
  (setq out nil cur "" i 1)
  (while (<= i (strlen str))
    (setq c (substr str i 1))
    (if (= c delim)
      (setq out (cons cur out) cur "")
      (setq cur (strcat cur c)))
    (setq i (1+ i)))
  (reverse (cons cur out)))

;; Save the system variables in VARS ((name . value) ...), set them, and open one undo step.
;; The caller declares cx:sv as a local so the saved values live exactly as long as the command.
(defun cx:start (vars)
  (setq cx:sv (mapcar (function (lambda (v) (cons (car v) (getvar (car v))))) vars))
  (command "_.UNDO" "_Begin")
  (foreach v vars (setvar (car v) (cdr v)))
  (princ))

;; Selection set to a list of entity names.
(defun cx:ss->list (ss / i out)
  (setq i 0)
  (if ss
    (repeat (sslength ss)
      (setq out (cons (ssname ss i) out)
            i   (1+ i))))
  (reverse out))

(princ "\nCXATTCOPY loaded. Type CXATTCOPY to start.")
(princ)

Cronologia delle versioni

Versione 1.0.0 · 27 ottobre 2026

Prima versione.

Ti serve su molti disegni?

BlockSync svolge questo tipo di lavoro su un'intera cartella di disegni in un solo passaggio.

BlockSync

Altri comandi: Blocchi e attributi