How Can I Obtain an Attribute's Prompt Message

Hello:

I am just playing around with LISP trying to build a little program for myself and I have run into a problem, I can get to the value and tag of a selected attribute using

[code]
(setq entity (nentsel "\nSELECT AN ATTRIBUTE TO EDIT: ")) ;Select an attribute - no bad selection handling shown.
(setq SelectedAtt (cdr (assoc 2 (entget (car entity))))) ;Get the ID of the selected attribute
(setq Object (vlax-ename->vla-object (car entity))) ;Get the object reference for my selected entity
(setq AttValue (vla-get-textstring Object)) ;Grab the value of the selected attribute
[/code]

So, the one thing I am missing is how to get the prompt for the attribute that the user selected (or hopefully selected as my code won't work if they don't select one). 

Any ideas?

Comments

  • You have to dig a little deeper for the prompt string. It is a property of the corresponding attribute definition. It is one of the few thing that an attribute reference actually references.
  • If you are trying to create a Lisp utility to edit a single attribute you should consider two things:
    1.
    There are mtext attributes which can contain special formatting. You cannot display this properly in a DCL dialog.
    2.
    If you double-clicks on an attribute the BC Attribute Editor will open with the value of that attribute preselected. So if you want to change a single attribute there is no need to scroll and search. Just type the new value and press OK.
  • Hi Roy:

    Thanks for the tip, I am still struggling but I am hoping to make some progress later today...

    Yup, I am building a light weight attribute editor - sometimes I find the supplied dialog cumbersome, mainly that the enter button jumps to the next attribute instead of just accepting the changes.  I did run into the formatting issue this am when attempting to edit an attribute who's value was 3"=1'-0", it will take some interesting programming to write something to parse through the string and escape the characters before putting them into a dialog...
  •  I did a bit more digging this am and realized that ENTNEXT is what I need to get to the ATTDEF, but the next entity is a (0 . "SEQEND") not an (0 . "ATTDEF") as expected.

    [code](setq entity (nentsel "\nSELECT AN ATTRIBUTE TO EDIT: "))[/code]

    Returns: (setq entity (nentsel "\nSELECT AN ATTRIBUTE TO EDIT: "))

    [code](entget (car entity))[/code]

    Returns: ((-1 . ) (0 . "ATTRIB") (5 . "3E2FB") (330 . ) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (6 . "ByBlock") (100 . "AcDbText") (10 11.1683605145269 6.6679508020378 0.0) (40 . 0.09375) (1 . "-") (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . "PGSNotes") (71 . 0) (72 . 1) (11 11.2085390859554 6.7148258020378 0.0) (210 0.0 0.0 1.0) (100 . "AcDbAttribute") (2 . "ID") (70 . 0) (73 . 0) (74 . 2) (280 . 0))

    [code](entget (entnext (car entity)))[/code]
    Returns: ((-1 . ) (0 . "SEQEND") (5 . "3E2FC") (330 . ) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "TEXT") (-2 . ))
    Should this last line of code not return an item that is (0 . "ATTDEF")?
    The block that I am playing with is a simple rectangle with one attribute in it.

  • Have to repost, made a mistake with the output from the first line of code.....

    [code](setq entity (nentsel "\nSELECT AN ATTRIBUTE TO EDIT: "))[/code]

    Returns: ( (11.2454763312328 6.716128962967 0.0))

    [code](entget (car entity))[/code]

    Returns: ((-1 . ) (0 . "ATTRIB") (5 . "3E2FB") (330 . ) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (6 . "ByBlock") (100 . "AcDbText") (10 11.1683605145269 6.6679508020378 0.0) (40 . 0.09375) (1 . "-") (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . "PGSNotes") (71 . 0) (72 . 1) (11 11.2085390859554 6.7148258020378 0.0) (210 0.0 0.0 1.0) (100 . "AcDbAttribute") (2 . "ID") (70 . 0) (73 . 0) (74 . 2) (280 . 0))

    [code](entget (entnext (car entity)))[/code]
    Returns: ((-1 . ) (0 . "SEQEND") (5 . "3E2FC") (330 . ) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "TEXT") (-2 . ))
    Should this last line of code not return an item that is (0 . "ATTDEF")?
    The block that I am playing with is a simple rectangle with one attribute in it.

  • To get to the attribute definition you have to start digging in the block definition.
    You can do this using 'Classic' Lisp but I would use Visual Lisp instead.
    [code]; (PromptStringAttRef (vlax-ename->vla-object (car (nentsel))))
    (defun PromptStringAttRef (obj)
      (cond
        ((= "AcDbAttributeDefinition" (vla-get-objectname obj))
          (prompt "\nError: constant attribute ")
        )
        ((= "AcDbAttribute" (vla-get-objectname obj))
          (PromptStringBlockDef (vla-get-name (_Sys_ObjectOwner obj)) (vla-get-tagstring obj))
        )
      )
    )

    ; (PromptString "TitleBlock_Small" "ClientAddress")
    (defun PromptStringBlockDef (name tag)
      (setq tag (strcase tag))
      (if (tblobjname "block" name)
        (vl-some
          '(lambda (obj)
            (if
              (and
                (= "AcDbAttributeDefinition" (vla-get-objectname obj))
                (= tag (strcase (vla-get-tagstring obj)))
              )
              (vla-get-promptstring obj)
            )
          )
          (vle-collection->list
            (vla-item
              (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
              name
            )
          )
        )
      )
    )

    (defun _Sys_ObjectOwner (obj)
      (vla-objectidtoobject (vla-get-database obj) (vla-get-ownerid obj))
    )[/code]
  • For comparison the 'Classic' approach.
    [code]; (Classic_PromptStringAttRef (car (nentsel)))
    (defun Classic_PromptStringAttRef (enme / elst)
      (cond
        ((= "ATTRIB" (cdr (assoc 0 (setq elst (entget enme)))))
          (Classic_PromptStringBlockDef
            (cdr (assoc 2 (entget (cdr (assoc 330 elst))))) ; Block name from the insert.
            (cdr (assoc 2 elst))                            ; Tag from the attribute.
          )
        )
        ((= "ATTDEF" (cdr (assoc 0 (entget enme))))
          (prompt "\nError: constant attribute ")
        )
      )
    )

    ; (Classic_PromptStringBlockDef "TitleBlock_Small" "ClientAddress")
    (defun Classic_PromptStringBlockDef (name tag / enme elst ret)
      (setq tag (strcase tag))
      (if (setq enme (tblobjname "block" name))
        (while
          (and
            enme ; Will be set to nil if the attribute is found.
            (setq enme (entnext enme))
            (/= "ENDBLK" (cdr (assoc 0 (setq elst (entget enme)))))
          )
          (if
            (and
              (= "ATTDEF" (cdr (assoc 0 elst)))
              (= tag (strcase (cdr (assoc 2 elst))))
            )
            (setq
              ret  (cdr (assoc 3 elst))
              enme nil
            )
          )
        )
      )
      ret
    )[/code]
  •  Interesting, thank you for the tip, it looks like I cannot obtain the prompt directly from the attrib item, instead I need to grab the details of the parent block and go down from there.  I appreciate the help!
This discussion has been closed.