Jump to content

Recommended Posts

Posted (edited)

I have been working on this LISP routine for a while to edit a multileader with a block and attribute. I am able to select all the similar multileaders, but then the code doesn't do anything when I am trying to actually edit them. Does anyone have any suggestions for what I am doing wrong?

(defun c:editmla
      (/ *error* entlist ent302 ent8 ss ss1 x x1 entlist2 newVal whilestop cnt MLeaderStyle)
 (defun *error* (msg)
   (if (not
         (member msg '("Function cancelled" "quit / exit abort"))
       )
     (princ (strcat "\nError: " msg))
   )
   (princ)
 )
 (setq whilestop t)
 (setvar 'errno 0)
 (while whilestop
   (if (setq ent (car (entsel "\nSelect MLEADER with # to select: ")))
     (progn
       (setq entlist (entget ent))
       (cond
         ((/= (cdr (assoc 0 entlist)) "MULTILEADER")
          (princ "\nSelected object is not a multileader.")
         )
         ((/= acblockcontent (cdr (assoc 172 (reverse entlist))))
          (princ
            "\nSelected multileader does not contain an attributed block."
          )
         )
         (t
          (if (setq newVal (getint "\nNew Attribute Value: "))
            (progn
              (editmla:grab)
              (editmla:tag)
              (setq whilestop nil)
            )
            (setq whilestop nil)
          )
         )
       )
     )
     (if (/= (getvar 'errno) 52)
       (princ "\nYou missed. Try again.")
       (setq whilestop nil)
     )
   )
 )
 (princ)
)
;;;This portion of the code is what grabs the mleaders
(defun editmla:grab ()
 (setq ent8 (cdr (assoc 8 entlist)))
 (foreach x entlist
   (if
     (and
       (eq 302 (car x))
       (not
         (or (wcmatch "LEADER{" (cdr x)) (wcmatch "" (cdr x)))
       )
     )
      (setq ent302 (cdr x))
   )
 )
 (if (/= ent302 nil)
   (progn
     (setq ss (ssget "_A"
                     (list '(0 . "MULTILEADER")
                           (cons 8 ent8)
                           (cons 302 ent302)
                     )
              )
     )
     (setq MLeaderStyle
            (vla-get-stylename (vlax-ename->vla-object ent))
           cnt 0
           ss1 (ssadd)
     )
     (repeat (sslength ss)
       (if (= (vla-get-stylename (vlax-ename->vla-object (ssname ss cnt))) MLeaderStyle)
         (ssadd (ssname ss cnt) ss1)
       )
       (setq cnt (+ cnt 1))
     )
     (if (sslength ss1)
       (sssetfirst nil ss1)
     )
     (setq whilestop nil)
   )
   (princ "\nMultileader attribute is blank.")
 )
)
;;;This is what actually edits the attribute
(defun editmla:tag ()
 (if ss1
   (progn
     (setq cnt2 0)
     (repeat (sslength ss1)
       (setq entlist2 (ssname ss1 cnt2))
       (foreach x1 entlist2
         (if
           (and
             (eq 302 (car x1))
             (not
               (or (wcmatch "LEADER{" (cdr x1)) (wcmatch "" (cdr x1)))
             )
           )
            (setq entlist2 (subst (cons 302 newVal) (assoc 302 entlist2) entlist2))
            (entmod entlist2)
         )
       )
     )
   )
 )
)

Edited by broncos15
Posted

So I have been researching it some more and I feel like my issue has to do with my entmod portion. Am I incorrectly handling the selection set with the entmod?

Posted

I have continued to mess with this and I have tried 2 different solutions, but I can't get either to work. The first solution using textedit is:

(defun editmla:tag ()
 (if ss1
   (progn
     (setq cnt2 0)
     (repeat (sslength ss1)
       (setq ent2 (ssname ss1 cnt2))
       (command "._tedit" ent2 "" newVal "")  
     )
   )
 )
)

I am confused why this doesn't work because I am following exactly how text edit works. My other solution was using a slight variant with entmod, but it still isn't doing anything. My code is

(defun editmla:tag ()
 (if ss1
   (progn
     (setq cnt2 0)
     (repeat (sslength ss1)
       (setq ent2 (ssname ss1 cnt2))
       (foreach x1 ent2
         (if
           (and
             (eq 302 (car x1))
             (not
               (or (wcmatch "LEADER{" (cdr x1)) (wcmatch "" (cdr x1)))
             )
           )
            (setq ent2 (subst (cons 302 newVal) (assoc 302 ent2) ent2))
            (entmod (reverse ent2)
            )
         )
       )
     )
   )
 )
)

I am confused why this doesn't do anything because I am making use of entmod.

Posted

I have now tried to do it using the vla-SetBlockAttributeValue function, but this doesn't work either. I know it has to do with me not using the function correctly, but can anyone point out my error?

(defun editmla:tag ()
 (if ss1
   (progn
     (setq cnt2 0)
     (repeat (sslength ss1)
       (setq ent2 (vlax-ename->vla-object (ssname ss1 cnt2)))
       (vla-SetBlockAttributeValue ent2 (vla-get-ObjectId ent2) newVal) 
     )
   )
 )
)

Posted

So after looking into this more, I realize that my issue has to do with the fact that I am using the setblockattributevalue method, but I am not getting the attribute definition. Is there an easy way to do this for Multileaders. I have seen Lee's example here at the link below, but I can't figure out how to do this with multileaders https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/vla-setblockattributevalue-please-help/td-p/4758691.

Posted (edited)

Here's a function for you to consider:

;; Set MLeader Block Attribute Value  -  Lee Mac
;; mld - [vla] MLeader object with attributed block content
;; tag - [str] Attribute tag whose value will be modified
;; val - [str] New attribute value

(defun LM:setmleaderblockattributevalue ( mld tag val )
   (if (= acblockcontent (vla-get-contenttype mld))
       (vl-catch-all-error-p
           (vl-catch-all-apply
              '(lambda ( / oid )
                   (vlax-for obj
                       (vla-item
                           (vla-get-blocks (vla-get-document mld))
                           (vla-get-contentblockname mld)
                       )
                       (if (and (= "AcDbAttributeDefinition" (vla-get-objectname obj))
                                (= :vlax-false (vla-get-constant obj))
                                (= (strcase tag) (strcase (vla-get-tagstring obj)))
                           )
                           (progn
                               (if (vlax-property-available-p obj 'objectid32)
                                   (setq oid (vla-get-objectid32 obj))
                                   (setq oid (vla-get-objectid   obj))
                               )
                               (if (vlax-method-applicable-p mld 'setblockattributevalue32)
                                   (vla-setblockattributevalue32 mld oid val)
                                   (vla-setblockattributevalue   mld oid val)
                               )
                               (exit)
                           )
                       )
                   )
               )
           )
       )
   )
)

Call the above with an MLeader vla-object, attribute tag and attribute value.

 

Various performance improvements could be incorporated based on the methods I used in my Auto Label Attributes program.

Edited by Lee Mac
Posted
Here's a function for you to consider:
[color=green];; Set MLeader Block Attribute Value  -  Lee Mac[/color]
[color=green];; mld - [vla] MLeader object with attributed block content[/color]
[color=green];; tag - [str] Attribute tag whose value will be modified[/color]
[color=green];; val - [str] New attribute value[/color]

([color=blue]defun[/color] LM:setmleaderblockattributevalue ( mld tag val )
   ([color=blue]if[/color] ([color=blue]=[/color] [color=blue]acblockcontent[/color] ([color=blue]vla-get-contenttype[/color] mld))
       ([color=blue]vl-catch-all-error-p[/color]
           ([color=blue]vl-catch-all-apply[/color]
              '([color=blue]lambda[/color] ( [color=blue]/[/color] oid )
                   ([color=blue]vlax-for[/color] obj
                       ([color=blue]vla-item[/color]
                           ([color=blue]vla-get-blocks[/color] ([color=blue]vla-get-document[/color] mld))
                           ([color=blue]vla-get-contentblockname[/color] mld)
                       )
                       ([color=blue]if[/color] ([color=blue]and[/color] ([color=blue]=[/color] [color=maroon]"AcDbAttributeDefinition"[/color] ([color=blue]vla-get-objectname[/color] obj))
                                ([color=blue]=[/color] [color=blue]:vlax-false[/color] ([color=blue]vla-get-constant[/color] obj))
                                ([color=blue]=[/color] ([color=blue]strcase[/color] tag) ([color=blue]strcase[/color] ([color=blue]vla-get-tagstring[/color] obj)))
                           )
                           ([color=blue]progn[/color]
                               ([color=blue]if[/color] ([color=blue]vlax-property-available-p[/color] obj 'objectid32)
                                   ([color=blue]setq[/color] oid ([color=blue]vla-get-objectid32[/color] obj))
                                   ([color=blue]setq[/color] oid ([color=blue]vla-get-objectid[/color]   obj))
                               )
                               ([color=blue]if[/color] ([color=blue]vlax-method-applicable-p[/color] mld 'setblockattributevalue32)
                                   ([color=blue]vla-setblockattributevalue32[/color] mld oid val)
                                   ([color=blue]vla-setblockattributevalue[/color]   mld oid val)
                               )
                               ([color=blue]exit[/color])
                           )
                       )
                   )
               )
           )
       )
   )
)

Call the above with an MLeader vla-object, attribute tag and attribute value.

 

Various performance improvements could be incorporated based on the methods I used in my Auto Label Attributes program.

Thanks Lee, that worked perfectly! I want to make sure that I understand it all correctly. I haven't ever seen those 32 functions before, are those for 32 bit systems?
Posted
Thanks Lee, that worked perfectly!

 

You're most welcome :)

 

I want to make sure that I understand it all correctly. I haven't ever seen those 32 functions before, are those for 32 bit systems?

 

Actually, the *32 functions are for compatibility with 64-bit architecture.

Posted

Oh interesting. I'll have to look into them so more, I haven't seen any documentation for those functions. Thanks again for the help!

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...