Curiously I could not find the post (posted 2014-ish) so I wrote something from scratch.
(defun _genericize-dxf-data ( dxf-data )
(vl-remove-if
(function
(lambda (p)
(or
(minusp (car p))
(member (car p) '(0 330 360 5 100 66))
)
)
)
dxf-data
)
)
(defun _entmake-from-entity-and-map ( entity map )
( (lambda ( entity-data )
(entmake
(mapcar
(function
(lambda ( p / p! )
(if (setq p! (assoc (car p) entity-data))
p!
p
)
)
)
map
)
)
)
(_genericize-dxf-data (entget entity))
)
)
(defun _entmake-insert-from-insert ( insert )
(_entmake-from-entity-and-map
insert
'(
(0 . "INSERT")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
(100 . "AcDbBlockReference")
(66 . 1)
(2 . "UNNAMED")
(10 -12.611 33.6579 0.0)
(41 . 1.0)
(42 . 1.0)
(43 . 1.0)
(50 . 0.0)
(70 . 0)
(71 . 0)
(44 . 0.0)
(45 . 0.0)
(210 0.0 0.0 1.0)
)
)
)
(defun _entmake-attrib-from-attdef ( attdef )
(_entmake-from-entity-and-map
attdef
'( (0 . "ATTRIB")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
(100 . "AcDbText")
(10 -12.0677 32.7299 0.0)
(40 . 0.381851)
(1 . "VAL-1")
(50 . 0.0)
(41 . 1.0)
(51 . 0.0)
(7 . "Standard")
(71 . 0)
(72 . 0)
(11 0.0 0.0 0.0)
(210 0.0 0.0 1.0)
(100 . "AcDbAttribute")
(280 . 0)
(2 . "ATT-1")
(70 . 0)
(73 . 0)
(74 . 0)
(280 . 0)
)
)
)
(defun _entmake-seqend-from-insert ( insert )
(_entmake-from-entity-and-map
insert
'( (0 . "SEQEND")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
)
)
)
Bring it all together in a wrapper function ...
(defun _add-attribs-to-insert ( insert ss-attdefs / i e lst object attribs )
(and
(progn (vl-load-com) t)
(eq 'pickset (type ss-attdefs))
(< 0 (setq i (sslength ss-attdefs)))
(setq object (vlax-ename->vla-object insert))
(_entmake-insert-from-insert insert)
(cond
((eq :vlax-false (vla-get-hasattributes object)))
((vl-every
(function (lambda (a) (_entmake-attrib-from-attdef a)))
(mapcar 'vlax-vla-object->ename (vlax-invoke object 'getattributes))
))
)
(progn
(repeat i (setq lst (cons (ssname ss-attdefs (setq i (1- i))) lst)))
(vl-every '_entmake-attrib-from-attdef lst)
)
(_entmake-seqend-from-insert insert)
(progn
(vla-put-lock
(vla-item
(vla-get-layers (vla-get-activedocument (vlax-get-acad-object)))
(cdr (assoc 8 (entget insert)))
)
:vlax-false
)
(entdel insert)
(repeat (setq i (sslength ss-attdefs))
(vl-catch-all-apply 'entdel (list (ssname ss-attdefs (setq i (1- i)))))
)
T
)
)
)
Bring it all together in a command ...
(defun c:add-attribs-to-insert ( / insert ss ss-attdefs )
(princ
(if
(and
(setq insert (car (entsel "\nSelect existing insert: ")))
(eq "INSERT" (cdr (assoc 0 (entget insert))))
(setq ss-attdefs (ssget '((0 . "attdef"))))
(_add-attribs-to-insert insert ss-attdefs)
)
"\nDone."
"\nFailed."
)
)
(princ)
)
As mentioned previously, this technique allows each instance of a block to sport it's own number of attributes, c/w unique tags if desired. Also, one can make any of the attributes constant after the fact, making them effectively read-only to users. The latter is different than constant attributes which are common to each instance of the block.
Please note that the supplied code creates a new instance of a selected block insert (deleting the original instance - this will impact other programs that rely on the existing insert's handle), populating the new instance with any previous attributes as well as adding the new ones.
See the image below which demonstrates 4 instance of the block "x" (which is defined attribute-less), each having it's own attributes. Attached dwg illuminates same.
Finally, code was written quickly and is not bomb proof, I'll leave that up to you.
Edit: Revised the _add-attribs-to-insert function as it was creating the new attributes in the reverse order desired.
Cheers.