Jump to content

How to Extract the 4th Attribute Value


Recommended Posts

Posted

Yes, you're welcome AlaskaChick.

 

...

As far as Visual LISP goes, as in Renderman's examples - although it immediately looks quite intuitive as the functions are in English and not DXF mumbo jumbo

 

 

Lee is absolutely correct... my examples only 'look' intuitive. lmao :P

 

I wouldn't disregard Vanilla AutoLISP methods completely. They are definitely worth knowing. Some situations are better coded in VL, some have far more concision (take Dictionary manipulation) and far quicker executed in Vanilla (take entity creation for example), whereas VL can strive outside the AutoCAD 'box' into other apps that support OLE Automation.

 

 

Being serious for a moment, Lee has given sound advice (as usual).

 

I hope I have not deterred you from AutoLISP. Each language has it's strengths, and while I have yet to master AutoLISP (or any other language for that matter!), I have found Visual LISP easier to use (for my needs), and my limited understanding (Ha, ha!).

 

Edit: An effective developer will know more than one language, and utilize them for all for maximum gain.

 

I am reminded daily, how many ways there are, to accomplish one's goal (usually by Alan, and Lee - those brilliant... never mind o:)).

  • Replies 32
  • Created
  • Last Reply

Top Posters In This Topic

  • BlackBox

    14

  • Alaskachick

    9

  • Lee Mac

    5

  • David Bethel

    3

Posted
I hope I have not deterred you from AutoLISP.

 

I am not deterred at all. I am definitely seeing the advantages of knowing more than one way to skin the cat. Little by little, I will get it. Thank you all for your help.

Posted
I am not deterred at all. I am definitely seeing the advantages of knowing more than one way to skin the cat. Little by little, I will get it. Thank you all for your help.

 

You're welcome. :)

Posted

Just another track I found VBA was the simplest to get at an attribute so long as you know its position number, once you retrive a blocks attributes you can just go straight to what ever one you want no need to step through etc.

 

FilterDXFCode(0) = 0

FilterDXFVal(0) = "INSERT"

Set SS = ThisDrawing.SelectionSets.Add("my1sel")

SS.Select acSelectionSetAll, , , FilterDXFCode, FilterDXFVal

For Cntr = 0 To SS.Count - 1

If SS.Item(Cntr).Name = BLOCK_NAME Then

attribs = SS.Item(Cntr).GetAttributes

If attribs(0).TextString = someuservalue Then

and so on

 

or mynewanswer = attribs(0).TextString the attribs(3) = fourth attribute, attrib(1) is second and so on etc

  • 4 weeks later...
Posted

I thought I would follow up on this thread and show what I came up with. This lisp works really well if you have attributes named "Photo_x" and they contain a path as the value. The program prompts the user to select a block and then a picture number. After the user selects a Photo number, it opens the picture in a separate browser window. I am still trying to perfect two things. I would like to ignore upper/lower case in the attribute tag and value so any one of Photo_x, photo_x and/or PHOTO_x would return the same value. And I would like it to open in a photo manager window, not internet explorer. I can get the photo manager program (acdsee11) to open from the command line in autocad, but I can't get it to open through the lisp to the specific picture called out in the attribute value path.

 

 

;***ATTLINK***
; Opens any Attribute link titled "Photo_x" in a separate browser after prompting user 
; for number of photo.
; Original code by Lee Mac, Remaining Code written by T. Ehmann
;
;
(defun c:attlink (/ bEnt photo_1 photo_2 photo_3 photo_4)
 (setvar "cmdecho" 0)
(if
 (and
   (setq bEnt (car (entsel "\nSelect Block: ")))
   (eq "INSERT" (cdr (assoc 0 (entget bEnt))))
   (= 1 (cdr (assoc 66 (entget bEnt))))
 );end and statement
 (while
 (not
   (eq "SEQEND"
     (cdr
       (assoc 0
         (entget
           (setq bEnt
             (entnext bEnt)
           );end setq
         );end entget
       );end assoc
     );end cdr
   );end eq
 );end not
 (if (eq "Photo_1" (cdr (assoc 2 (entget bEnt))))
     (setq photo_1 (cdr (assoc 1 (entget bEnt))))
  );end if statement
 (if (eq "Photo_2" (cdr (assoc 2 (entget bEnt))))
   (setq photo_2 (cdr (assoc 1 (entget bEnt))))
 );end if statement
 (if (eq "Photo_3" (cdr (assoc 2 (entget bEnt))))
   (setq photo_3 (cdr (assoc 1 (entget bEnt))))
 );end if statement
 (if (eq "Photo_4" (cdr (assoc 2 (entget bEnt))))
   (setq photo_4 (cdr (assoc 1 (entget bEnt))))
 );end if statement
 );end while
);end if statement
(setq PHLINK (getstring "\nEnter Photo Number (1-4): ")); sets which link value to use.
 (cond ((= phlink "1")(command ".browser" photo_1))
       ((= phlink "2")(command ".browser" photo_2))
       ((= phlink "3")(command ".browser" photo_3))
       ((= phlink "4")(command ".browser" photo_4))
);end if statement
(princ);exit quietly
);end defun statement
 

 

I would love more input, but here's the catch--I gotta write my own code! So, don't tell me the answers, just gently point in their general direction. lol

Posted (edited)

(if (eq "Photo_1" (cdr (assoc 2 (entget bEnt))))

(setq photo_1 (cdr (assoc 1 (entget bEnt))))

 

You can include all of these tests into a single call

 

if the tagname is a member of a preset list of strings, then bind the tagname to the attribute value

 

I would also make all tagname values upper case for comparisons

 

 

(setq PHLINK (getstring "\nEnter Photo Number (1-4): ")); sets which link value to use.

(cond ((= phlink "1")(command ".browser" photo_1))

 

I would make the getstring into a getkword.

 

You can strcat together variable name "photo_" and PHLINK, and evaluate the string as a variable. This will make a single command call without any conditions.

 

-David

 

PS It is easier to write the code than to give hints.

Edited by David Bethel
Posted

David, thanks for the ideas. My code is a little clunky still. I'll work on slimming it down.

 

I would make the getstring into a getkword.

I went back and forth on that one. I forget why I picked getstring. Why would you pick getkword? Is it to better limit the possible user inputs?

 

PS It is easier to write the code than to give hints.

I appreciate the work put into hints versus code. I don't want to be a one hit wonder, so the theory behind all the lisp choices is important to me.

Posted
My code is a little clunky still. I'll work on slimming it down.

 

 

No worries... everyone starts somewhere. :)

 

Understanding that the question was directed at David (Hope he doesn't mind), I'd like to jump in to second his advice, and point out a some items that jumped out to me...

 

:: From top to bottom ::

 

If you're going to set the cmdecho variable to zero, it is considered best practice to first store the initial value, then reapply upon successful completion. This requires error handling.

 

If you're going to call entget multiple times, then consider storing the entity list to a variable (the first time), instead of repeating the same call on the same entity.

 

I would ask you to consider converting your numerous if statements into a single cond statement.

 

Why would you pick getkword? Is it to better limit the possible user inputs?

 

 

 

In lieu of getstring place an initget with the appropriate "1 2 3 4" string, and a getkword [1/2/3/4] call, in order to limit the user input to those options.

 

Consider including your PHLINK segment within the initial if statement.

 

Consider converting your cond statement containing your "browser" calls into a single function,

 

Place the PHLINK line at the beginning on your routine.

 

 

I appreciate the work put into hints versus code. I don't want to be a one hit wonder, so the theory behind all the lisp choices is important to me.

 

 

 

It really is harder to write this out, then to show you... there are other changes I would make, but I don't want you to feel like I am being too harsh. I'm not, and you'll thank me (us?) for it later. I promise. :wink:

 

Hope this helps!

Posted

Why would you pick getkword? Is it to better limit the possible user inputs?

 

(getkword) used in conjunction with (initget), gives you total control of inputs. There is no need to error check any inputs such as (snvalid) or (= input "") etc

 

(initget 1 "Yes No")
(setq input (getkword "\n Is it Yes or No:  "))

 

This limits the input to 2 options available and one of them must chosen. Also the mnemonic format in the ( initget ) parameter allows for a single character ( Y or N ) input to be viable

 

 

(initget "Yes No")
(setq input (getkword "\n Is it Yes or No <N>:  "))
(if (not input)
   (setq input "No"))

 

This makes "No" the default. Only a "Y" or a "Yes" will change the value.

 

If you just press enter, input is nil and null, therefore the ( not ) tests is T and input is then set to "No"

 

My code is a little clunky still

 

I enjoy the challenge of making code as compact as possible with brevity and still have it easily readable to the human eye. -David

Posted

I enjoy the challenge of making code as compact as possible with brevity and still have it easily readable to the human eye. -David

 

 

While brevity is the soul of wit, when it comes to code maintenance readability is king. :wink:

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...