Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LISP find block by Block Name AND where Attribute TAG1=*User Input*

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
david.faunce
5163 Views, 6 Replies

LISP find block by Block Name AND where Attribute TAG1=*User Input*

I'm new to AutoLISP. I've gone through many tutorials most of which just show you math and how to loop. There are only a handful of tutorials that deal with acutal block manipulation which is where I struggle.

 

I've seen some of the great LISP functions that Lee Mac and Nate Holt (and others) have created and shared, but I have yet to find a routine that does the following:

 

(1) Find the block where BLOCK NAME = "VIFCD_001" AND ATTRIBUTE  [TAG1] = "-M161"

(2) Inside that same block change the ATTRIBUTE [DESC] = "NEW PART NUMBER"

 

I would prefer that "BLOCK NAME"   "TAG NAME"  and "DESC NAME" be arguments in a function.

 

I've been trying to work from this routine (below), that will change attributes of a block. The only LISP routine I know prompts the user to select the block, however, I cannot prompt the user for anything - I need the block name to be passed as an argument

 

How do I use LISP to select the block where BLOCK NAME = "VIFCD_001" and its attribute TAG1="-M161"

 

 

THE CALL

(setq ent (car (entsel)))  ;Prompts the user to select a block
(changeVars "DESC" "NEW PART NUMBER" ent)

 

 

THE FUNCTION

(defun changeVars (tag newvalue ent / alist)
  (if (and (= (type ent) (read "VLA-OBJECT")) newvalue)
    (progn
      (setq alist ( vlax-invoke ent 'GetAttributes))
      (foreach a alist)
         (if (= (vla-get-tagstring a) tag)
             (vlax-put-property a 'TextString newvalue)
         );endif
       );end foreach
     );end progn
     (if (= 'ename (type ent)) 
         (reptag tag newvalue (vlax-ename->vla-object ent))
     );endif
   );endif
(princ)
);end defun

 

 

 

Tags (2)
6 REPLIES 6
Message 2 of 7

Here is one example.

;;Ranjit Singh
;;8/3/17
(defun somefunc (tagname value blockname / etdata) (mapcar '(lambda (x) (while (/= "SEQEND" (cdr (assoc 0 (setq etdata (entget (setq x (entnext x))))))) (and (= (cdr (assoc 0 etdata)) "ATTRIB") (mapcar '(lambda (x y) (and (= x (cdr (assoc 2 etdata))) (entmod (subst (cons 1 y) (assoc 1 etdata) etdata)))) (list tagname) (list value))))) (mapcar 'cadr (ssnamex (ssget "_x" (list '(0 . "insert") (cons 2 blockname) '(66 . 1)))))))

Update_Block_Attribute.gif

EDIT: If you want to pass ent then change this

(mapcar 'cadr (ssnamex (ssget "_x" (list '(0 . "insert") (cons 2 blockname) '(66 . 1)))))

to

(mapcar 'cadr (ssnamex (ssget "_x" (list '(0 . "insert") (assoc 2 (entget blockname)) '(66 . 1)))))

 and call the function like

(somefunc "DESC" "NEW PART NUMBER" ent)

 Update_Block_Attribute_2.gif

Message 3 of 7

Thank you Ranjit. 

 

This is helpful, however, I was hoping to have the user not select the object.

 

This function will need to be purely automated without any prompts for the user to select objects or type inputs.

 

 

 

I need to select the block where BLOCK NAME = VIFCD_001  and its attribute TAG1 = "-M161"

 

 

*this command below is wrong, but my question to you is how do I use LISP to identify a block where BLOCKNAME="VIFCD_001" AND TAG1="-M161"*

(setq ent (entsel <block name>  <tag name>))
(setq ent (entsel "VIFCD_001",  "-M161"))

 

Message 4 of 7

I think I'm getting close, but can someone help? This produces a NIL value, but I believe these are the properties I need to access.

 

(setq ss (ssget "_X" '((0 . "INSERT") (2 . "VIFCD_001") (5 . "1C7F"))))

 

 

Below are the properties for two blocks (both named VIFCD_001)

 

 

 

Properties for Block #1

(
  (-1 . <Entity name: 3aceb1f0>)
  (0 . "INSERT")
  (330 . <Entity name: 35557820>)
  (5 . "1C7F")
  (100 . "AcDbEntity")
  (67 . 0)
  (410 . "Model")
  (8 . "Syms")
  (100 . "AcDbBlockReference")
  (66 . 1)
  (2 . "VIFCD_001")
  (10 0.0867055 5.14515e-06 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)
)

 

Properties for Block #2

(
  (-1 . <Entity name: 3acea5b0>)
  (0 . "INSERT")
  (330 . <Entity name: 35557820>)
  (5 . "1C43")
  (100 . "AcDbEntity")
  (67 . 0)
  (410 . "Model")
  (8 . "Syms")
  (100 . "AcDbBlockReference")
  (66 . 1)
  (2 . "VIFCD_001")
  (10 145.197 0.100673 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)
)

Message 5 of 7


@david.faunce wrote:

Thank you Ranjit. 

 

This is helpful, however, I was hoping to have the user not select the object.

 

This function will need to be purely automated without any prompts for the user to select objects or type inputs.

 

 

 

I need to select the block where BLOCK NAME = VIFCD_001  and its attribute TAG1 = "-M161"

 

 

*this command below is wrong, but my question to you is how do I use LISP to identify a block where BLOCKNAME="VIFCD_001" AND TAG1="-M161"*

(setq ent (entsel <block name>  <tag name>))
(setq ent (entsel "VIFCD_001",  "-M161"))

 



There has to be some way to identify the block. Block name is one. Other could be block insertion point if you are after a particular block. If you want to update a tag in any instance of the block then you just create a selection set of all the blocks and then iterate through them. My example is good for plugging in your overall function? I thought that was the goal since you needed a function with arguments. Something like this

(defun c:somefunc  (/ ctr ss1)
  (setq ctr 0
        ss1 (ssget "_x" '((0 . "insert") (2 . "VIFCD_001"))))
  (repeat (sslength ss1) (somefunc "DESC" "NEW PART NUMBER" (ssname ss1 ctr)) (setq ctr (1+ ctr))))

(defun somefunc  (tagname value blockname / etdata)
  (mapcar '(lambda (x)
             (while (/= "SEQEND" (cdr (assoc 0 (setq etdata (entget (setq x (entnext x)))))))
               (and (= (cdr (assoc 0 etdata)) "ATTRIB")
                    (mapcar '(lambda (x y)
                               (and (= x (cdr (assoc 2 etdata))) (entmod (subst (cons 1 y) (assoc 1 etdata) etdata))))
                            (list tagname)
                            (list value)))))
          (mapcar 'cadr (ssnamex (ssget "_x" (list '(0 . "insert") (assoc 2 (entget blockname)) '(66 . 1)))))))

Update_Block_Attribute_3.gif 

Is there something I am missing?

Message 6 of 7


@david.faunce wrote:

I think I'm getting close, but can someone help? This produces a NIL value, but I believe these are the properties I need to access.

 

(setq ss (ssget "_X" '((0 . "INSERT") (2 . "VIFCD_001") (5 . "1C7F")))) ;

 

.................


You cannot use dxf code 5 in ssget. Read here The ssget function recognizes all group codes except entity names (group code -1), handles (group code 5), and .... If you have the entity handle from some previous data processing and want to select an object with a particular handle, for instance, "1C7F" then call hadnet

(handent "1C7F")

 

Message 7 of 7

This is very helpful...I have not heard about "handent" thank you!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


AutoCAD Beta