CADXChange

Toutes les commandes LISP

CXATTCOPYBlocs et attributsVersion 1.0.0Testé dans AutoCAD

Copier les valeurs d'attributs d'un bloc vers d'autres

Prend les valeurs d'attributs d'un bloc et les écrit dans les autres blocs sélectionnés, pour toutes les étiquettes ou seulement celles que vous nommez.

Comment l'utiliser

  1. Saisissez CXATTCOPY et cliquez sur le bloc source.
  2. Sélectionnez les blocs à renseigner.
  3. Saisissez les étiquettes à copier, séparées par des virgules, ou - pour toutes.

Bon à savoir

  • Seules les étiquettes présentes dans les deux blocs sont copiées.

Le charger dans AutoCAD

  1. Enregistrez le fichier où vous voulez.
  2. Tapez APPLOAD, choisissez le fichier et cliquez sur Charger.
  3. Tapez le nom de la commande : CXATTCOPY.

Pour l'avoir à chaque démarrage, ajoutez-le à la Mallette de démarrage dans la même boîte de dialogue, ou chargez un dossier entier d'un coup avec le chargeur facultatif. À propos du chargeur facultatif

Testé dans AutoCAD (version complète). D'autres programmes qui exécutent AutoLISP peuvent fonctionner, mais ils n'ont pas été testés.

Le code

Du texte brut, rien de caché. Copiez-le dans un fichier nommé cxattcopy.lsp ou téléchargez-le.

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

Historique des versions

Version 1.0.0 · 27 octobre 2026

Première version.

Besoin de le faire sur de nombreux dessins ?

BlockSync effectue ce genre de tâche sur tout un dossier de dessins en une seule passe.

BlockSync

Autres commandes : Blocs et attributs