Jump to content

Autonumber LISP with loop and/or range


niccoleleaf

Recommended Posts

Hopefully I can explain this well enough, I've been pounding my head on this for weeks. I have created an autonumbering lisp routine for block attributes that has a start value, increment, insertion order-forward or reverse, so I can autonumber blocks with a specific scheme. I work with wiring and electrical systems. My problem now is I have new blocks I've created for devices that need to be autonumbered, but they need to have a scheme like X3-1, where X3 is an alias and -1 is a wire location. I can have #1-24 on the wire location, then the next block needs to start at X4-1 and go through 24 again. How can I add a loop and range to my lisp to accomplish this or does someone have another idea? We work with hundreds of devices so it is not practical to number by hand like I have been. Any input would be appreciated. Thanks

Link to comment
Share on other sites

Welcome to CADTutor niccoleleaf :)

 

Would my Incremental Numbering Suite be of any help to you?

Lee Mac, thanks for the reply, I'm a big fan by the way. I did try that but unfortunately it doesn't allow me to edit the existing attribute I have or allow me to create a range. Let me post an example of what I'm looking to do, see attachment. Imagine the blocks at the top, there are 23 of them, numbered C3-1 thru C3-24, then below would be another string of blocks, needing numbers C4-1 thru C4-24. The block contains the attribute/block that has the C3-1 number already in it but it can be edited, so I can't place a piece of text, I need to be able to edit the attribute and number according to insertion order. Referring to the white text at the top of the block. Hope this helps.

block att.jpg

Link to comment
Share on other sites

Many thanks niccoleleaf, I'm delighted that you are a fan of my work!

My Incremental Numbering Suite program does offer a replacement option, accessible by pressing 'R' at the command-line during text placement; though if this isn't suitable, a dedicated custom program may be required for the task.

Link to comment
Share on other sites

Many thanks niccoleleaf, I'm delighted that you are a fan of my work!

My Incremental Numbering Suite program does offer a replacement option, accessible by pressing 'R' at the command-line during text placement; though if this isn't suitable, a dedicated custom program may be required for the task.

I played around with it some more and I see what you mean, however, I need the ability to mass edit them in later revisions, to renumber all the blocks in the same format instead of having to do it on insertion. What do you think?

Link to comment
Share on other sites

This is what I am using currently to number one of the other attributes, I can put in a prefix plus -001 and it numbers infinitely according to insertion order, or reverse insertion order. My ultimate goal is to copy and modify this to make another routine the would have the range/loop function in it, so I can run the command, select the attribute and it would mass number per my requirements.

 

 

(defun C:ATTINC()


;;;--- Get an attributes value

(defun getAttData(en / enlist blkType group66 attData)


 ;;;--- Get the DXF group codes of the entity
 (setq enlist(entget en))

 (setq attData (list))

 ;;;--- Check to see if the block's attribute flag is there
 (if(cdr(assoc 66 enlist))
   (progn
        
     ;;;--- Get the entity name
     (setq en(entnext en))

     ;;;--- Get the entity dxf group codes
     (setq enlist(entget en))

     ;;;--- Get the type of block
     (setq blkType (cdr(assoc 0 enlist)))

     ;;;--- If group 66 then there are attributes nested inside this block
     (setq group66(cdr(assoc 66 enlist)))

     ;;;--- Loop while the type is an attribute or a nested attribute exist
     (while(or (= blkType "ATTRIB")(= group66 1))
          
       ;;;--- Get the block type 
       (setq blkType (cdr(assoc 0 enlist)))

       ;;;--- Check to see if this is an attribute
       (if(= blkType "ATTRIB")

         ;;;--- Save the tag of the attribute
         (setq attData(append attData(list (cdr(assoc 2 enlist)))))

       )

       ;;;--- Get the next sub-entity
       (setq en(entnext en))

       ;;;--- Get the dxf group codes of the next sub-entity
       (setq enlist(entget en))

       ;;;--- Get the block type of the next sub-entity
       (setq blkType (cdr(assoc 0 enlist)))

       ;;;--- See if the dxf group code 66 exist.  if so, there are more nested attributes
       (setq group66(cdr(assoc 66 enlist)))

     )
   )
 )
 attData
)







;;;--- Get an attributes value

(defun replaceAtt(en tagName str / enlist blkType group66)


 ;;;--- Get the DXF group codes of the entity
 (setq enlist(entget en))

 ;;;--- Check to see if the block's attribute flag is there
 (if(cdr(assoc 66 enlist))
   (progn
        
     ;;;--- Get the entity name
     (setq en(entnext en))

     ;;;--- Get the entity dxf group codes
     (setq enlist(entget en))

     ;;;--- Get the type of block
     (setq blkType (cdr(assoc 0 enlist)))

     ;;;--- If group 66 then there are attributes nested inside this block
     (setq group66(cdr(assoc 66 enlist)))

     ;;;--- Loop while the type is an attribute or a nested attribute exist
     (while(or (= blkType "ATTRIB")(= group66 1))
          
       ;;;--- Get the block type 
       (setq blkType (cdr(assoc 0 enlist)))

       ;;;--- Check to see if this is an attribute
       (if(= blkType "ATTRIB")

         ;;;--- If the attribute value matches....
         (if(= tagName (cdr(assoc 2 enlist)))
           (progn

             ;;;--- Substitute the dxf group codes
             (setq enlist(subst (cons 1 str)(assoc 1 enlist)enlist))
             (entmod enlist)
             (entupd en)
           )
         )
       )

       ;;;--- Get the next sub-entity
       (setq en(entnext en))

       ;;;--- Get the dxf group codes of the next sub-entity
       (setq enlist(entget en))

       ;;;--- Get the block type of the next sub-entity
       (setq blkType (cdr(assoc 0 enlist)))

       ;;;--- See if the dxf group code 66 exist.  if so, there are more nested attributes
       (setq group66(cdr(assoc 66 enlist)))

     )
   )
 )
)









;;;--- Function to save the dialog box settings

(defun saveVars(/ index retList readlist count item)


 ;;;--- Save the input from the SELECTPLOTTER.dcl file
 (setq retList(list))
 (setq readlist(get_tile "attdata"))  
 (setq count 1)
 (while (setq item (read readlist))
   (setq retlist(append retList (list (nth item attData))))
   (while (and (/= " " (substr readlist count 1))
     (/= "" (substr readlist count 1)))
     (setq count (1+ count))
   )
   (setq readlist (substr readlist count))
 )
 
 (if(= retList nil)
   (setq tagName nil)
   (setq tagName (car retList))
 )

 (setq str(get_tile "startstr"))
 (setq inc(atoi(get_tile "increment")))
 (setq order1(atoi(get_tile "order1")))
 (setq order2(atoi(get_tile "order2")))
)




;;;--- Function to increment a string
;;;    str = a string
;;;    inc = an integer
;;;
;;;    Examples (incStr "A100") would return "A101" if inc is set to 1
;;;             (incStr "A01")  would return "A11"  if inc is set to 10           

(defun incStr(str inc)

 ;;;--- Set up some variable defaults
 (setq strPart "" numPart "" chkStr str flag T)

 ;;;--- While there are characters left in the string to check
 (while(/= chkStr "") 

   ;;;--- Get the last character in the string
   (setq ch(substr chkStr (strlen chkStr)))

   ;;;--- If the flag is clear continue on...
   (if(= flag T)
     (progn

       ;;;--- If the character to check matches a numerical string value....
       (if(member ch (list "1" "2" "3" "4" "5" "6" "7" "8" "9" "0" "."))

         ;;;--- Add the numerical string value to the number portion
         (setq numPart(strcat ch numPart))

         ;;;--- Else set the flag to nil because the rest of the string is letters
         (setq flag nil strPart chkStr)
       )
     )
   )

   ;;;--- Drop the last character off the string
   (setq chkStr(substr chkStr 1 (- (strlen chkStr) 1)))
 )

 ;;;--- See how many characters make up the numerical string portion
 (setq numLen(strlen numPart))

 ;;;--- Convert the numerical to a string, add the increment, and convert back to a string
 (setq numStr (itoa(+ (atoi numPart) inc)))

 ;;;--- If the converted string is less characters than the original, prefix with zeros
 (while(< (strlen numStr) numLen)
   (setq numStr(strcat "0" numStr))
 )

 ;;;--- Put the string back together
 (setq str(strcat strPart numStr))
)






 ;;;--- Main application


 ;;;--- Let the user select the block
 (if(setq ent(entsel "\n Select Block: "))
   (progn

     ;;;--- Get the entity name from the entity selection
     (setq en(car ent))

     ;;;--- Get the dxf group codes of the entity
     (setq enlist(entget en))

     ;;;--- Make sure this is a block entity
     (if(= "INSERT" (cdr(assoc 0 enlist)))
       (progn

         ;;;--- Get the name of the block
         (setq blkName(cdr(assoc 2 enlist)))

         ;;;--- If attribute information is found in the block
         (if(setq attData(getAttData en))
           (progn

             ;;;--- Put up the dialog box
             (setq dcl_id (load_dialog "ATTINC.dcl"))

             ;;;--- Make sure the DCL file loaded
             (if (not (new_dialog "ATTINC" dcl_id))
               (progn
                 (alert "Could not find the ATTINC.DCL file!")
                 (exit)
               )
             )

             ;;;--- Add the list to the dialog box
             (start_list "attdata" 3)
             (mapcar 'add_list attData)
             (end_list)

             ;;;--- Set a default selection
             (set_tile "attdata" "0")

             ;;;--- If an action event occurs, do this...
             (action_tile "okay"  "(saveVars)(setq ddiag 1)(done_dialog)")
             (action_tile "cancel"  "(setq ddiag 2)(done_dialog)")

             ;;;--- Display the dialog box
             (start_dialog)

             ;;;-- Unload the dialog box
             (unload_dialog dcl_id)

             ;;;--- Start the routine
             (if(= ddiag 1)
               (progn

                 ;;;--- Display a message
                 (princ "\n Gathering all blocks named ")(princ blkName) (princ " .....")

                 ;;;--- Get the blocks
                 (if(setq eset(ssget "X" (list (cons 0 "INSERT")(cons 2 blkName))))
                   (progn

                     (princ "\n Manipulating data .....")

                     ;;;--- While entities exist in the selection set...
                     (while (> (sslength eset) 0)

                       ;;;--- If insertion order is to be used...
                       (if(= order1 1)

                         ;;;--- Get the first entity in the selection set
                         (setq en(ssname eset 0))

                         ;;;--- Else use reverse order and get the last entity in the selection set
                         (setq en(ssname eset (- (sslength eset)1)))
                       )

                       ;;;--- Replace the value of the tag
                       (replaceAtt en tagName str)

                       ;;;--- Increment the value for the next attribute                  
                       (setq str(incStr str inc))                        
                        
                       ;;;--- Remove the entity from the selection set
                       (ssdel en eset)

                     )
                   )
                 )
               )
             )
           )
           (alert "The block selected does not contain attributes!")
         )
       )
       (alert "The entity selected is not a block!")
     )     
     
   )
   (alert "No block selected!")
 )

 (princ)
)

_____________________________________

 

ATTINC:

ATTINC : dialog {
        label = "AttInc";
        : column {
          : column {
            : list_box{
              label ="Select Tag Name";
              key = "attdata";
              height = 15;
              width = 45;
              multiple_select = false;
              fixed_width_font = false;
            }
          }
          : column {
            : edit_box  {
              key = "startstr";
              label = "Start Value:";
              edit_width = 8;
              value  = "A001";
            }
            : edit_box  {
              key = "increment";
              label = "Increment:";
              edit_width = 8;
              value  = "1";
            }
            : radio_button {
              label = "Insertion order";
              key = "order1";
              value  = "0";
            }
            : radio_button {
              label = "Reverse insertion order";
              key = "order2";
              value = "1";
            } 
          }
          : column {
            : boxed_row {
              : button { 
                key = "okay";
                label = "Okay";
                is_default = true;
              }
              : button { 
                key = "cancel";
                label = "Exit";
                is_default = false;
                is_cancel = true;
              }
            }
          }
        }
}

 

 

Thanks again

Edited by niccoleleaf
Link to comment
Share on other sites

Hopefully I can explain this well enough, I've been pounding my head on this for weeks. I have created an autonumbering lisp routine for block attributes that has a start value, increment, insertion order-forward or reverse, so I can autonumber blocks with a specific scheme. I work with wiring and electrical systems. My problem now is I have new blocks I've created for devices that need to be autonumbered, but they need to have a scheme like X3-1, where X3 is an alias and -1 is a wire location. I can have #1-24 on the wire location, then the next block needs to start at X4-1 and go through 24 again. How can I add a loop and range to my lisp to accomplish this or does someone have another idea? We work with hundreds of devices so it is not practical to number by hand like I have been. Any input would be appreciated. Thanks

 

What comes before X1-1, and if I understood, you can have alias X25-1 after X24-24, or I am wrong it should be Y1-1 after X24-24 and before X1-1, W24-24... And to go to start, what comes before A1-1 (I suppose nothing - this is starting string)...

Link to comment
Share on other sites

What comes before X1-1, and if I understood, you can have alias X25-1 after X24-24, or I am wrong it should be Y1-1 after X24-24 and before X1-1, W24-24... And to go to start, what comes before A1-1 (I suppose nothing - this is starting string)...

 

You are correct, X25-1 would come after X24-24, the suffix is the only thing that has the range restriction up to 24. And nothing would come before A1-1, A1 would signify the first device

Link to comment
Share on other sites

I think you didn't understood me completely... When do you change alias letter - after what number X???-24 comes Y1-1?

Link to comment
Share on other sites

Actually you don't have to change the letter at all, the convention for the devices is made up ahead of time and will be used all the way through, so if it starts with B1-1, every convention will be Bx-xx

Link to comment
Share on other sites

See if this algorithm can help you - it's basically string incrementation code based on your demands...

 

(defun incrstr ( str / schr k n nstr nolst lno no nno )
 (setq schr (substr str 1 1))
 (setq k 0)
 (while (and (<= (setq k (1+ k)) (strlen str)) (= 0 (setq n (atoi (substr str k (+ (- (strlen str) k) 1)))))))
 (setq nstr (itoa n))
 (setq nolst '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24))
 (setq lno (substr str (+ (strlen nstr) 3) (- (strlen str) (strlen nstr))))
 (setq no (atoi lno))
 (if (eq no 24) (setq nno 1) (setq nno (cadr (member no nolst))))
 (if (eq nno 1) (setq nstr (itoa (+ n 1))))
 (strcat schr nstr "-" (itoa nno))
)
 
(defun decrstr ( str / schr k n nstr nolst lno no nno )
 (setq schr (substr str 1 1))
 (setq k 0)
 (while (and (<= (setq k (1+ k)) (strlen str)) (= 0 (setq n (atoi (substr str k (+ (- (strlen str) k) 1)))))))
 (setq nstr (itoa n))
 (setq nolst '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24))
 (setq lno (substr str (+ (strlen nstr) 3) (- (strlen str) (strlen nstr))))
 (setq no (atoi lno))
 (if (eq no 1) (setq nno 24) (setq nno (cadr (member no (reverse nolst)))))
 (if (and (< 1 n) (eq nno 24)) (setq nstr (itoa (- n 1))) (setq nstr (itoa n)))
 (strcat schr nstr "-" (itoa nno))
)

(defun c:strincr-X1-24 ( / s )
 (if (null ch)
   (progn
     (initget 1 "Increment + Decrement -")
     (setq ch (getkword "\nIncrement / Decrement [ + / - ] : "))
   )
 )
 (if (null str) (setq str (getstring "\nStart alias string in form : X1-24 : ")))
 (prompt "\nENTER to continue, or any other key + ENTER to restart, or SPACE + ENTER to change choice")
 (while (eq "" (setq s (getstring t)))
   (progn
     (cond
            ( (or (eq ch "Increment") (eq ch "+"))
              (setq str (incrstr str))
            )
            ( (or (eq ch "Decrement") (eq ch "-"))
              (setq str (decrstr str))
            )
     )
     (princ str)
     (terpri)
   )
 )
 (if (and (eq s " ") (or (eq ch "Increment") (eq ch "+"))) (progn (setq ch "-") (c:strincr-X1-24)))
 (if (and (eq s " ") (or (eq ch "Decrement") (eq ch "-"))) (progn (setq ch "+") (c:strincr-X1-24)))
 (setq ch nil str nil)
 (c:strincr-X1-24)
 (princ)
)

Link to comment
Share on other sites

See if this algorithm can help you - it's basically string incrementation code based on your demands...

 

(defun incrstr ( str / schr k n nstr nolst lno no nno )
 (setq schr (substr str 1 1))
 (setq k 0)
 (while (and (<= (setq k (1+ k)) (strlen str)) (= 0 (setq n (atoi (substr str k (+ (- (strlen str) k) 1)))))))
 (setq nstr (itoa n))
 (setq nolst '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24))
 (setq lno (substr str (+ (strlen nstr) 3) (- (strlen str) (strlen nstr))))
 (setq no (atoi lno))
 (if (eq no 24) (setq nno 1) (setq nno (cadr (member no nolst))))
 (if (eq nno 1) (setq nstr (itoa (+ n 1))))
 (strcat schr nstr "-" (itoa nno))
)
 
(defun decrstr ( str / schr k n nstr nolst lno no nno )
 (setq schr (substr str 1 1))
 (setq k 0)
 (while (and (<= (setq k (1+ k)) (strlen str)) (= 0 (setq n (atoi (substr str k (+ (- (strlen str) k) 1)))))))
 (setq nstr (itoa n))
 (setq nolst '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24))
 (setq lno (substr str (+ (strlen nstr) 3) (- (strlen str) (strlen nstr))))
 (setq no (atoi lno))
 (if (eq no 1) (setq nno 24) (setq nno (cadr (member no (reverse nolst)))))
 (if (and (< 1 n) (eq nno 24)) (setq nstr (itoa (- n 1))) (setq nstr (itoa n)))
 (strcat schr nstr "-" (itoa nno))
)

(defun c:strincr-X1-24 ( / s )
 (if (null ch)
   (progn
     (initget 1 "Increment + Decrement -")
     (setq ch (getkword "\nIncrement / Decrement [ + / - ] : "))
   )
 )
 (if (null str) (setq str (getstring "\nStart alias string in form : X1-24 : ")))
 (prompt "\nENTER to continue, or any other key + ENTER to restart, or SPACE + ENTER to change choice")
 (while (eq "" (setq s (getstring t)))
   (progn
     (cond
            ( (or (eq ch "Increment") (eq ch "+"))
              (setq str (incrstr str))
            )
            ( (or (eq ch "Decrement") (eq ch "-"))
              (setq str (decrstr str))
            )
     )
     (princ str)
     (terpri)
   )
 )
 (if (and (eq s " ") (or (eq ch "Increment") (eq ch "+"))) (progn (setq ch "-") (c:strincr-X1-24)))
 (if (and (eq s " ") (or (eq ch "Decrement") (eq ch "-"))) (progn (setq ch "+") (c:strincr-X1-24)))
 (setq ch nil str nil)
 (c:strincr-X1-24)
 (princ)
)

 

You are a genius, that is really close, I ran it and it's getting closer, but it runs over 24, and continues past X1-24. But that's closer than I was

Link to comment
Share on other sites

Hi niccoleleaf,

 

I would be more than happy to write the described application tailored specifically to your requirements; if you are interested, please contact me through my site here.

 

Cheers,

 

Lee

Link to comment
Share on other sites

  • 2 weeks later...

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