Pbejse Lisp Edit / Guidance

Pbejse Lisp Edit / Guidance

Anonymous
Not applicable
1,658 Views
25 Replies
Message 1 of 26

Pbejse Lisp Edit / Guidance

Anonymous
Not applicable

Hi,

 

I'm not sure if I should have posted in the old thread or created a new one so apologies if I've gone about this the wrong way.

 

I was looking for a LISP routine that sequentially numbers attributes and I noticed one posted by pbejse Here.

 

This is so close to being exactly what I'm looking for but I would like the lisp to sequentially number based on varying text (example below).  The above lisp specifies whether the contained text string should be "ELEVATION" or "ADDRESS" whereas I have many variables.

 

Attribute Tag: NUMBER

Attribute Value: (Varies) - Door, Window, Wall, Chair, Table, etc

Required Output: Door1, Door2, Door3, Window1, Window2, Chair1, Chair2, Chair3, Table1, etc

 

I'm not skilled enough to change this lisp myself, nor do I want to do so without permission from the author.

 

Would anyone be able to assist with this?

 

Thanks in advance!

0 Likes
Accepted solutions (1)
1,659 Views
25 Replies
Replies (25)
Message 2 of 26

Jonathan3891
Advisor
Advisor
Try Lee Mac's Incremental Numbering Suite.
It will work with attributed blocks

http://www.lee-mac.com/numinc.html

Jonathan Norton
Blog | Linkedin
0 Likes
Message 3 of 26

Anonymous
Not applicable

Coincidently I've been looking at that exact same lisp recently. I've made a couple of amendments to the original (one with Pbejse's help)

 

It now defaults to number 1 when starting incrementing attributes (Pbejse)

 

I've added a getstring function so the user can specify their own prefix

 

I hope it's of some use to you


Defun c:ATI (/ startnumber limit nestedobjsectselectionmode entitydata selectedentitytype attributeValuetobereplace prex ) (setq prex (getstring T "Specify Prefix <enter for none>")) (while (not (progn (setq startnumber (getstring "\nEnter Start number:< 1 > "));; added 14/7/15 (setq startnumber (If (eq "" startnumber) "1" startnumber)) (if (and (numberp (setq limit (read startnumber))) (<= 0 limit 100)) limit (and (princ "\n<Invalid number>") nil))))) (while (setq nestedobjsectselectionmode (car (nentsel "\nSelect Attribute/Enter to exit:"))) (setq entitydata (entget nestedobjsectselectionmode)) (setq selectedentitytype (cdr (assoc 0 entitydata))) (if (eq selectedentitytype "ATTRIB") (progn (setq attributeValuetobereplace (assoc 1 entitydata)) (entmod (subst (cons 1 (strcat prex (itoa limit)));; added 14/7/15 attributeValuetobereplace entitydata)) (setq limit (+ 1 limit)) ) (princ "\nNot an attribute definition")) ) (princ) )
0 Likes
Message 4 of 26

Anonymous
Not applicable

Hi both,

 

Thanks for getting back to me and sorry for the delay!  DSM_dude, I had a look at Lee's lisp before and from what I can see, I can't select multiple blocks at once, nor can I use the incrementation based on the current text in an attribute, hence why I loaded Pbejse's lisp.

 

sbanister, the 1 start is definitely better and I'll probably use that bit as well.  I note you have a line in there starting "(setq prex..." which I assume is the variable for setting a prefix.  I don't want the user to have to type in the prefix every time; I would like the current text to remain and the number to be added to the end of the text. 

 

Do you know if there's something I can put in to retain the text?  Maybe (setq prex current) or something...?

 

Hope that makes sense!

0 Likes
Message 5 of 26

Anonymous
Not applicable

A bit beyond me to be honest other than using ordinary text within your block with the attribute just being the suffix

0 Likes
Message 6 of 26

Anonymous
Not applicable

I'm sorry, I clearly hadn't had enough coffee when I replied this morning.


 

The lisp code I have already adds sequential numbering to the end of the current text.  It also already differentiates between different text and numbers appropriately.

 

However, in the lisp, the text is specified (ELEVATION, ADDRESS).  I can obviously add all my text to this lisp but I have over 50 varying items of text (Window, Door, Table, Chair, Bookcase, etc).  I just wondered if there was a neater way of doing it.  Something that would just read that the text was different and number appropriately, rather than numbering based on a predefined list of text.

 

Not sure if that makes much more sense (only on my second cup of coffee!), if anyone can help or if it's possible.

0 Likes
Message 7 of 26

ВeekeeCZ
Consultant
Consultant

Try this verison.

 

Spoiler
(Defun c:ATI (/ startnumber limit
                nestedobjsectselectionmode
                entitydata
                selectedentitytype
                attributeValuetobereplace
		prex
                )
  (while (not (progn
		(setq startnumber (getstring "\nEnter Start number <1>: "));; added 14/7/15
		(setq startnumber (If (eq "" startnumber) "1" startnumber))
		(if (and (numberp (setq limit (read startnumber)))
			 (<= 0 limit 100))
		  limit
		  (and (princ "\n<Invalid number>")
		       nil)))))
  (while (setq nestedobjsectselectionmode (car (nentsel "\nSelect Attribute/Enter to exit:")))
    (setq entitydata (entget nestedobjsectselectionmode))
    (setq selectedentitytype (cdr (assoc 0 entitydata)))
    (if (eq selectedentitytype "ATTRIB")
      (progn
	(setq attributeValuetobereplace (assoc 1 entitydata))
	(entmod (subst (cons 1 (strcat (cdr attributeValuetobereplace) (itoa limit)));; added 14/7/15
		       attributeValuetobereplace
		       entitydata))
	(setq limit (+ 1 limit)))
      (princ "\nNot an attribute definition")))
  (princ)
)
Message 8 of 26

Anonymous
Not applicable

Sorry, I'm not sure how that lisp is any better than the one I have.  I maybe haven't explained myself properly so please see attached drawing and bullet list of what the lisp currently does and what I am trying to see if I can put in to it.

 

Currently:

  • Choose a starting number
  • Select multiple blocks
  • Sequentially number all stated attributes (Tag "ID") based on two varying default texts (ELEVATION and ADDRESS)

           -e.g. If I select 14 blocks, 6 of which contain the text "ELEVATION" in the "ID" tag, and 8 of which contain "ADDRESS", the lisp will number the blocks as Elevation 1 - 6 and Address 1 - 8

 

What I'd like:

  • For the lisp to be able to differentiate that there is varying text as a default in the attribute (e.g. Window, Table, Chair, Door, Bookcase) and number them as per this text whilst retaining this text

       -e.g. As per the attached file, I would get attributes with the contents as: Window1, Window2, Door1, Door2, Door3, Table1, Table2

 

I know from the previous lisp that I can add in more varying texts as a list (so I could add in Window, Door, Table, etc), but I have over 50 different pieces of text and I was hoping there might be a "cleaner" option; someone may add more blocks at some point with other text (e.g. sofa) which wouldn't be included in the lisp selection set.

 

I hope that makes more sense and sorry to be such a pest!

0 Likes
Message 9 of 26

pbejse
Mentor
Mentor

@Anonymous wrote:

Sorry, I'm not sure how that lisp is any better than the one I have.  I maybe haven't explained myself properly so please see attached drawing and bullet list of what the lisp currently does and what I am trying to see if I can put in to it.

 

Currently:

  • Choose a starting number
  • Select multiple blocks
  • Sequentially number all stated attributes (Tag "ID") based on two varying default texts (ELEVATION and ADDRESS)

           -e.g. If I select 14 blocks, 6 of which contain the text "ELEVATION" in the "ID" tag, and 8 of which contain "ADDRESS", the lisp will number the blocks as Elevation 1 - 6 and Address 1 - 8

 

What I'd like:

  • For the lisp to be able to differentiate that there is varying text as a default in the attribute (e.g. Window, Table, Chair, Door, Bookcase) and number them as per this text whilst retaining this text

       -e.g. As per the attached file, I would get attributes with the contents as: Window1, Window2, Door1, Door2, Door3, Table1, Table2

 

I know from the previous lisp that I can add in more varying texts as a list (so I could add in Window, Door, Table, etc), but I have over 50 different pieces of text and I was hoping there might be a "cleaner" option; someone may add more blocks at some point with other text (e.g. sofa) which wouldn't be included in the lisp selection set.

 

I hope that makes more sense and sorry to be such a pest!


Sounds easy enough and NO you are not being a pest. 🙂 

 

Perhaps I'll have a look tomorrow and we'll probably do a re-wrte to accomodate your request. but then again maybe not 😄

 

Be patient...

 

pBe

 

0 Likes
Message 10 of 26

Anonymous
Not applicable

Total pest, asking other people to do my dirty work for me 😉

 

If you get a chance that would be amazing.  Even a nudge towards the line I might need and then I can google like crazy.

 

Thank you so much 🙂

0 Likes
Message 11 of 26

pbejse
Mentor
Mentor
Accepted solution

@Anonymous wrote:

Even a nudge towards the line I might need and then I can google like crazy.

 

Thank you so much 🙂


HYG, if i understood it correclty, it would look something like this. a nudge right?

 

(defun c:demo (/ mlst blocks evl attval id f)
  (initget 7)
  (setq startnumber (getint "\nEnter Start Number: "))
  (if
    (setq mlst	 nil
	  blocks (ssget "_:L" '((66 . 1)))
    )
     (repeat (sslength blocks)
       (setq evl (vlax-ename->vla-object (ssname blocks 0)))
       (setq attval
	      (mapcar '(lambda (at)
			 (list (vla-get-tagstring at)
			       (vl-string-right-trim " 0123456789" (vla-get-textstring at))
			       at
			 )
		       )
		      (vlax-invoke evl 'Getattributes)
	      )
       )
       (cond
	 ((not (setq id (assoc "ID" attval))))
	 ((setq f (assoc (strcase (cadr id)) mlst))
	  (vla-put-textstring
	    (caddr id)
	    (strcat (cadr id) (itoa (setq cnum (1+ (cdr f)))))
	  )
	  (setq mlst (subst (cons (car f) cnum) f mlst))
	 )
	 (T
	  (vla-put-textstring
	    (caddr id)
	    (strcat (cadr id) (itoa startnumber))
	  )
	  (setq mlst (cons (cons (strcase (cadr id)) startnumber) mlst))
	 )
       )
       (ssdel (ssname blocks 0) blocks)
     )
  )
  (princ)
)

 

Hope this helps.

 

pBe

Message 12 of 26

Anonymous
Not applicable

Oh wow, way, way more than a nudge, thank you so much!! Heart

 

Sorry for the delay in getting back to you; I've been googling most of the morning to try and understand the relevant parts of that lisp.  Not much luck but I swear I'll get there one day and then I won't need to pester you lovely people 🙂

 

Thank you again, greatly appreciated.

 

0 Likes
Message 13 of 26

pbejse
Mentor
Mentor

@Anonymous wrote:

 

...Thank you again, greatly appreciated.

 


You are welcome cmasonslb, hope you'll learn from it.

 

Happy to  help.

 

Cheers

 

pBe

0 Likes
Message 14 of 26

Anonymous
Not applicable

You're going to be super upset I ever found your lisp in the first place.

 

I have a weird question.  I'm slowly breaking apart both lisps to understand what you've written, and I notice there's a few differences in the way you've done them both.  To make this a quick response for you, I have some multiple choice reasons below... 🙂

 

  1. The "demo" (most recent) lisp was written in a rush
  2. The "TagID" (older) lisp is fine, but the way I write lisps has changed
  3. You(cmasonslb) have completely misunderstood what I've written and both lisps are superb
  4. Stop asking me questions before I cry
  5. Other

The only reason I'm asking is because I'm wondering which is the... "better" lisp if you like; if I want to write my own some day, I don't want to be pulling apart inappropriate lisps.

 

I'm sorry if this is really cheeky...! :S

0 Likes
Message 15 of 26

pbejse
Mentor
Mentor

@Anonymous wrote:

You're going to be super upset I ever found your lisp in the first place.

 

I have a weird question.  I'm slowly breaking apart both lisps to understand what you've written, and I notice there's a few differences in the way you've done them both.  To make this a quick response for you, I have some multiple choice reasons below... 🙂

 

  1. The "demo" (most recent) lisp was written in a rush
  2. The "TagID" (older) lisp is fine, but the way I write lisps has changed
  3. You(cmasonslb) have completely misunderstood what I've written and both lisps are superb
  4. Stop asking me questions before I cry
  5. Other

The only reason I'm asking is because I'm wondering which is the... "better" lisp if you like; if I want to write my own some day, I don't want to be pulling apart inappropriate lisps.

 

I'm sorry if this is really cheeky...! :S


Not at all, upset is not on my vocabulary, "confuse" now thats the word you should have use.

 

I'm not sure if there's any question on your post at all?

 

It surely is, hence it is called "Demo" > 1

Indeed it is different, i opted to write a code from scracth instead of trying to figure out what the other code was all about. it uses the same approac though > 2

Not sure what you meant by those >  3

As far as i can tell the only question i ask was "what do you mean by default?" > thru PM

Another > 5

 

I always say "there is always a better way" in about everything in this universe. My goal here is to guide/advise and to give suggestions to all those who are willing to learn.

 

Dont be sorry, at least you have the willingness the learn. Keep it up cmasonslb.

 

NOW what is the question?

 

pBe

 

 

 

0 Likes
Message 16 of 26

Anonymous
Not applicable

I'm so sorry, I dreamt I had replied to this (along with being a master lisp-er; should have realised it was a dream!).

 

I think I've confused the whole thing by changing from 1st person to 3rd person in that last post, so ignore it.  It's confusing me reading it back.

 

Ok, so basically the question is that there are a few differences between the two lisps.  I just wonder which is better or if there is a particular reason they are different.  From my understanding (read: googling), the TagID lisp uses nested "IF" statements for getting the attributes, text string, etc.  The demo lisp uses a "COND" statement for the same thing.

 

Is there a reason one would be preferred over the other?  Does it matter in the grand scheme of things which is used?  Alternatively, have I misunderstood both sections of the lisp and they both do different tasks altogether?

 

My other question revolves around a total lack of knowledge; I can't wrap my head round car/cdr/cddr/cadr.  It's probably a bit much to ask you to explain that to me, so would you mind if I posted an excerpt of some of your code to use as an example for someone to explain?  I can change all the variables, etc but it's still blatantly your code.  Obviously I'd reference you.

 

Thank you again

Cmaso

0 Likes
Message 17 of 26

Anonymous
Not applicable
car/cdr/cddr/cadr are all well explained in the Autolisp Refence Guide 2013
It's downloadable from Autodesk

http://docs.autodesk.com/ACDMAC/2013/ENU/PDFs/PDF%20Documentation.htm

Message 18 of 26

Anonymous
Not applicable

Ahhh, there's a whole reference guide!!  I'm so excited!! Thank you 🙂 🙂 🙂

 

The thing I (still) don't understand; if the LISP is required to return all parts of a text string, could you just use car and cdr?  Is there a particular reason you'd need to use cadr and caddr?  Maybe because it is an attribute and there is a defunct value at the start (e.g. it starts with ATTRIBUTE so CAD can recognise it as an attribute)?

 

Thank you,

cmaso

0 Likes
Message 19 of 26

pbejse
Mentor
Mentor

@Anonymous wrote:

 

.....The thing I (still) don't understand; if the LISP is required to return all parts of a text string, could you just use car and cdr?  Is there a particular reason you'd need to use cadr and caddr?  

 

Thank you,

cmaso


There are separate functions for string  and list manipulation

 

String handling functions -Substr, strcase, wcmatch...

 

List Manipulation Functions <--- where you use car, cadr, cdr.....

 


@Anonymous wrote:

so would you mind if I posted an excerpt of some of your code to use as an example for someone to explain? 


It would be better if you did posts an excerpt and pinpoint what part of the code you need explaining to. We aer more than happy to guide you cmaso

 

pBe

0 Likes
Message 20 of 26

Anonymous
Not applicable

That explains some parts slightly better than what I'd found previously, thank you.  The bit I'm confused about is below.  I've put in notes next to each line as to what I *think* it does; this could be where I'm going wrong (obviously any misunderstanding on my part will result in this question being totally silly).  From the section below, the code should pull the "ID" attributes from "mlst", add 1 to the initial "startnumber" entered (giving "cnum"), add all the strings together.

 

But the bit I don't get is with regards to car/cdr/cadr for "id" and "f".

 

Say my ID string is "Big Beige Bay Window", and my startnumber is 1.

The 2nd line of code would return "Big Beige Bay Window" for "id".

Then, (confused), the 3rd line of code would return "Big Beige Bay Window" because it is one list.  If "id" was 4 individual lists, then it would return "Beige Bay Window".  Right...?

So, what I don't understand is, why couldn't you use car in place of cdr for all of the below (i.e. lines 2, 5, 6, 12, 13, 15)?

 

1.(cond
2.((not (setq id (assoc "ID" attval)))) ; Set "id" equal to the "ID" attribute value
3.((setq f (assoc (strcase (cadr id)) mlst)) ; Set "f" equal to the 2nd element of "id" and the value of mlst
4.(vla-put-textstring
5.(caddr id) ; 3rd element of "id"
6.(strcat (cadr id) (itoa (setq cnum (1+ (cdr f))))) ; join 2nd element "id", set "cnum" equal to 2nd element f + 1, join cnum
7.)
8.(setq mlst (subst (cons (car f) cnum) f mlst)); substitute 1st element of "f" with "cnum".  Set "mlst" equal to "cnum" + "f" + "mlst"
9.)
10.(T
11.(vla-put-textstring
12.(caddr id) ; return 3rd element of "id"
13.(strcat (cadr id) (itoa startnumber)); join 2nd element of "id" with "startnumber"
14.)
15.(setq mlst (cons (cons (strcase (cadr id)) startnumber) mlst)): set mlst equal to 2nd element "id" + "startnumber" + "mlst"

 

 

 

0 Likes