CADXChange

Todos los comandos LISP

CXATTCOPYBloques y atributosVersión 1.0.0Probado en AutoCAD

Copiar los valores de atributos de un bloque a otros

Toma los valores de atributos de un bloque y los escribe en los demás bloques seleccionados, para todas las etiquetas o solo las que indiques.

Cómo se usa

  1. Escribe CXATTCOPY y haz clic en el bloque de origen.
  2. Selecciona los bloques que quieres rellenar.
  3. Introduce las etiquetas a copiar separadas por comas, o - para todas.

Conviene saber

  • Solo se copian las etiquetas que existen en ambos bloques.

Cargarlo en AutoCAD

  1. Guarda el archivo donde quieras.
  2. Escribe APPLOAD, elige el archivo y pulsa Cargar.
  3. Escribe el nombre del comando: CXATTCOPY.

Para tenerlo en cada inicio, agrégalo al Contenido de inicio en el mismo cuadro de diálogo, o carga una carpeta entera de una vez con el cargador opcional. Sobre el cargador opcional

Probado en AutoCAD (versión completa). Otros programas que ejecutan AutoLISP pueden funcionar, pero no se han probado.

El código

Texto sin más, nada oculto. Cópialo en un archivo llamado cxattcopy.lsp o descárgalo.

;;; ============================================================================
;;; 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)

Historial de versiones

Versión 1.0.0 · 27 de octubre de 2026

Primera versión.

¿Lo necesitas en muchos dibujos?

BlockSync hace este tipo de trabajo con toda una carpeta de dibujos en una sola pasada.

BlockSync

Más comandos: Bloques y atributos