Jump to content

Table + attributes (for BOM, bill of material)


daveacad

Recommended Posts

hi evrb!

i need a big help.

i'm working to make quiet easier and faster my activity of measurment for BOM with autocad. i'm not a programmer, so viva all autocad forums!

 

what i'm looking for has two order of problem to solve

 

1.

i'm looking for a lisp or something like, to put values of a block with attributes in a table (acad 2007): if i have in the block 5 attributes, i need to write in a table the values of them.

in the first column should be write the first attribute value, in the second, the value of the second attribute, and so on.

 

2.

the second part of the problem is something like "dynamic blocks". if one or more value(s) of attribute(s) in a block(s) are changed, the same value should be automatically updated (in the table).

 

 

can someone give a help? maybe with the possibility to select more than one block at time (not one by one) and then pick the table where to write in.

 

 

hope i've been clear with my request.

 

dave.

Link to comment
Share on other sites

Why Dont you Use Data extraction In Autocad this Will Give you both Of Your answers in 1 hit

 

...

becouse Data extraction (both, normal and via express tools) is the last step of the work, when you need to export data to excel or openofiice or anithing like.

 

what i need i a tool easy to use to connect data stored in a block with a table.

 

and also, before someone else suggest to use the table creation wizard, that way is not useful for the work.

 

cheers,

dave

Link to comment
Share on other sites

Here is some code that I use to do almost the exact same thing.

 

Gathers blocks by name

Changes layer of block to an attribute in the block

Filters out duplicates

Clears out existing schedule if it exists

Inserts lines into the schedule with info from the blocks

;THE FUNCTION BELOW SAVES THE USER SETTINGS

;SSETUP

(defun ssetup ()

(setq atdia (getvar "attdia"))

(setvar "attdia" 0)

(setq scmde (getvar "cmdecho"))

(setvar "cmdecho" 0)

(setq curlay (getvar "clayer"))

(setvar "clayer" "Schedule")

(setq snap (getvar "osmode"))

(setvar "osmode" 16567)

);DEFUN END

;THE FUNCTION BELOW CHANGES THE LAYER NAME TO THE PARTNUMBER OF THE BLOCK.

;LAY2ATT

(DEFUN LAY2ATT (/ SSID I THISEN ENTLYST THISLAY )

(SETQ SSID(SSGET "X" (LIST(CONS 0 "INSERT")(CONS 2 "PARTID")(CONS 66 1))))

(IF (/= SSID NIL)

(PROGN

(SETQ I (SSLENGTH SSID))

(WHILE (NOT(MINUSP(setq I (1- I))))

(PROGN

(SETQ THISEN(SSNAME SSID I))

(SETQ ENTLYST (ENTGET THISEN))

(SETQ THISLAY(DXF 8 ENTLYST))

(NAVALUE THISEN "PARTNUMBER" THISLAY)

);PROGN END

);WHILE END

);PROGN END

(PROGN

(ALERT "THERE ARE NO PART ID'S IN YOUR DRAWING")

(PRINC)

);PROGN END

);IF END

);DEFUN END

;THE FUNCTION BELOW COLLECTS THE PART ID'S TO USE IN THE SCHEDULE

;GETPART

(defun getpart (/ i2 bEnt ent elist aval attLst)

(if (setq ssid (ssget "X" (list (cons 0 "INSERT") (cons 2 "PARTID") (cons 66 1))))

(progn

(setq i2 (sslength ssid))

(while (not (minusp (setq i2 (1- i2))))

(setq bEnt (ssname ssid i2))

(setq ent (entnext bEnt))

(while (/= "SEQEND" (cdadr (setq elist (entget ent))))

(if (equal (cdr (assoc 2 elist)) "PARTNUMBER")

(setq aval (cdr (assoc 1 elist)));ELSE

)

(setq ent (entnext ent))

)

(if (member aval attLst)

(ssdel bEnt ssid);ELSE

(setq attLst (cons aval attLst))

)

)

)

(alert "No Blocks Found.")

)

(princ)

);DEFUN END

;THE FUNCTION BELOW DELETES THE CURRENT CONTENTS OF THE SCHEDULE AND SETS THE OFFSET TO 0

;DELETE SCHEDULE

(defun DeleteSchedule (/ SSSCHEDULE SCHDCNT SCHEDULEENTID)

;Delete the truss line blocks

(setq ssSchedule (ssget "X" (list (cons 0 "INSERT") (cons 2 "BOMLINE") (CONS 66 1))))

(if (/= ssSchedule nil)

(progn

(setq Schdcnt (sslength ssSchedule))

(while (not (minusp (setq Schdcnt (1- Schdcnt))))

(entdel (ssname ssSchedule Schdcnt))

);WHILE END

);PROGN END

);IF END

(setq ssSchedule (ssget "X" (list (cons 0 "INSERT") (cons 2 "BOMSCHD") (cons 66 1))))

(if (/= ssSchedule nil)

(progn

(setq ScheduleEntId (ssname ssSchedule 0))

(navalue ScheduleEntId "OFFSET" "0")

);PROGN END

(Alert "\nYou must have a Bill of Materials Schedule block inserted to use this application.")

);IF END

);DEFUN END

;THE FUNCTION BELOW SORTS THE SELECTION SET BY THE PARTNUMBERS TO USE IN THE SCHEDULE

;SORTSSID

(defun SortSSid ()

; Sorts the selection set according to Part Number

; Copy ssid entity names to SortList

(setq SortList (list ""))

(setq slong (sslength ssid))

(while (not (minusp (setq SLONG (1- SLONG))))

(setq SortList (cons (cons (avalue (ssname ssid SLONG) "PARTNUMBER") (ssname ssid SLONG)) SortList))

);WHILE END

; Get rid of the space at the end of the list

(setq sortlist2 (reverse SortList))

(setq sortlist (cdr sortlist2))

(setq SortList (bsort SortList))

; Now that we've sorted the list, go through the original ssid and copy the sorted version

(setq ssidSorted (ssadd))

(setq mcnt 0)

(setq slong (length SortList))

(while (

(setq CurrentEntity (cdr (nth mcnt SortList)))

; For each of the entities in SortList, copy that entity

; in ssid to ssidSorted

(ssadd CurrentEntity ssidSorted)

(setq mcnt (1+ mcnt))

);WHILE END

);DEFUN END

;THE FUNCTION BELOW INSERTS THE LINE INTO THE SCHEDULE WITH COLLECTED INFORMATION

;BOMLINE

(defun bomline ()

(setq idcnt 0);SETS IDCNT COUNTER TO 0

(setq MARK 1);SETS MARK NUMBER TO THE FIRST TO BE USED (1)

(setq sidlong (sslength ssidSorted));SETS SIDLONG TO THE LENGTH OF SSIDSORTED

(while (

(setq ssmark (ssadd))

(setq pid (ssname ssidSorted 0))

(setq pmark (avalue pid "PARTNUMBER"))

; Copy ssidSorted to tempss

(setq tempss (ssadd))

(setq mcnt 0)

(setq slong (sslength ssidSorted))

(while (

(ssadd (ssname ssidSorted mcnt) tempss)

(setq mcnt (1+ mcnt))

)

(setq mcnt 0)

(while (

(setq pid (ssname tempss mcnt))

(setq curmark (avalue pid "PARTNUMBER"))

(if (equal curmark pmark)

(progn

(ssadd pid ssmark)

(ssdel pid ssidSorted)

(setq idcnt (1+ idcnt))

)

)

(setq mcnt (1+ mcnt))

)

(setq tmp2ss (ssadd))

(setq clong (sslength ssmark))

(setq mcnt2 0)

(while (

(ssadd (ssname ssmark mcnt2) tmp2ss)

(setq mcnt2 (1+ mcnt2))

);WHILE

(setq tcnt (sslength TMP2SS))

(setq rcnt 0)

(setq totcnt 0)

(while (

(setq pid (ssname ssmark 0))

(setq PNUM (avalue pid "PARTNUMBER"))

;Copy ssmark to tmp3ss

(setq tmp3ss (ssadd))

(setq clong (sslength ssmark))

(setq mcnt3 0)

(while (

(ssadd (ssname ssmark mcnt3) tmp3ss)

(setq mcnt3 (1+ mcnt3))

)

(setq schdss (ssadd))

(setq schdss (ssget "X" (list (cons 0 "INSERT") (cons 2 "BOMSCHD"))))

(setq blkid (ssname schdss 0))

(setq ents (entget blkid))

(setq spoint (cdr (assoc 10 ents)))

(setq soffset (distof (avalue blkid "OFFSET") 2))

(setq spoint (polar spoint (dtr 270) soffset))

;in here is where we are going to get the part descripion informaitn from the db

(setq ConnectString "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=m:\\CADRef.mdb;Jet OLEDB:System Database=m:\\Workgroups\\MerDBSecure.mdw")

(if (not (setq ConnectionObject (ADOLISP_ConnectToDB ConnectString "USER" "PASSWORD"))

)

(progn

(prompt "\nConnection failed!")

(ADOLISP_ErrorPrinter)

);progn end

(prompt "\nResult: succeeded!")

);if end

(setq SQLStatement (strcat "SELECT * FROM CADParts WHERE ProductNumber ="" ""'"pnum"'"))

(prompt

(strcat"\n\nExecuting a SELECT statement to retrieve some data:\n\""SQLStatement"\"")

)

(if (setq Result (ADOLISP_DoSQL ConnectionObject SQLStatement))

(progn

(setq desclist (cadr result))

(if (= desclist nil)

(setq descr "Please enter part description.");else

(setq descr (cadr desclist))

);if end

);progn end

(progn

(prompt "\nFailed!")

(ADOLISP_ErrorPrinter)

);progn end

);if end

(prompt "\n\nDisconnecting from the database\n")

(ADOLISP_DisconnectFromDB ConnectionObject)

(setq ConnectionObject nil)

(setq Curquan (getstring (strcat "\nEnter quantity for part number " PNUM " : ")))

 

(if (= 0 totcnt)

(command "insert" "BOMLINE" spoint "1" "1" "0" descr PNUM curquan mark 0 )

)

(setq totcnt (1+ totcnt))

(navalue blkid "OFFSET" (rtos (+ soffset 0.75) 2))

(setq rcnt (1+ rcnt))

(SETQ CURLAY PNUM)

(SETQ CURSS (ssget "X" (list (cons 0 "INSERT")(cons 2 "PARTID")(cons 66 1)(CONS 8 CURLAY))))

(setq CURcnt 0)

(setq CURlng (sslength CURSS))

(while (

(setq curid (ssname CURSS CURcnt))

(navalue curid "ID" (ITOA MARK))

(NAVALUE CURID "DESCRIPTION" DESCR)

(setq CURcnt (1+ CURcnt))

(ENTUPD CURID))

(SETQ MARK (1+ MARK))

); THIS ENDS THE SSMARK USE LOOP

); end of main loop

); end of BOMLINE

;THE FUNCTION BELOW RESTORES THE USER SETTINGS

;RSETUP

(defun rsetup ()

(setvar "attdia" atdia)

(setvar "cmdecho" scmde)

(setvar "clayer" curlay)

(SETVAR "OSMODE" SNAP)

(princ)

);DEFUN END

;MAIN PROGRAM

(DEFUN C:BOM ()

(SSETUP)

(LAY2ATT)

(GETPART)

(DELETESCHEDULE)

(SORTSSID)

(BOMLINE)

(RSETUP)

);DEFUN END

Link to comment
Share on other sites

I also use some subroutines in this that automatically extract and insert info into the blocks.

 

AVALUE

;THE FUNCTION BELOW - Returns the value of an attribute

;SYNTAX (SETQ VARIABLENAME (AVALUE BLOCKNAME "ATTRIBUTENAME"))

(defun avalue (bname aname)

(setq cnt 0)

(setq ent bname)

(while (= cnt 0)

(setq ent (entnext ent))

(setq entl (entget ent))

(setq entn (cdr (assoc 2 entl)))

(if (equal entn aname)

(progn

(setq cnt 1)

(setq aval (cdr (assoc 1 entl)))

);progn

); if

); while

); avalue

NAVALUE
;THE FUNCTION BELOW - Changes value of an attribute to a new value

; SYNTAX (NAVALUE BLOCKNAME "ATTRIBUTETAG" NEWVALUE)

(defun navalue (bname aname naval)

(setq cnt 0)

(setq ent bname)

(while (= cnt 0)

(setq ent (entnext ent))

(setq entl (entget ent))

(setq entn (cdr (assoc 2 entl)))

(if (equal entn aname)

(progn

(setq cnt 1)

(setq entl (subst (cons 1 naval) (assoc 1 entl) entl))

(entmod entl)

);progn

); if

); while

); navalue

And also a sort routine

BSORT

;THE FUNCTION BELOW - SORTS LISTS BY THE SLECTED VARIABLE.

;Bsort

(defun BSORT (data-list / rslt item1 item2 collector)

(while ; main loop

(progn

(setq ; intialize variables

item1 nil

item2 nil

rslt nil ; recursion control: while loop

)

; EXECUTE ONE BUBBLE-SORT CYCLE

(repeat (length data-list)

(if (= nil item1) ; first cycle - initalize item1

(setq

item1 (car data-list)

data-list (cdr data-list)

)

)

(if (= nil item2)

(setq

item2 (car data-list)

data-list (cdr data-list)

)

)

(cond

( (= nil item1)) ; defensive programming

( (= nil item2) ; almost at the end of the list

(setq collector (append collector (list item1)))

)

; * the comparison functions are here *

; this could be modified to sort by CADR, etc...

( (cond

( (atom item1) (

( T (

)

(setq ; if the above returned T

collector (append collector (list item1))

item1 item2 ; shuffle item2 over to item1 for simplicity

item2 nil

)

)

( T ; otherwise the first item was larger than the second

(setq

collector (append collector (list item2))

item2 nil

)

; force another recursion - when all item1's are

; then the sort is complete & the initialized nil value in RSLT

; stops the higher-level while loop

(setq rslt T)

)

)

);repeat

(setq

data-list collector

collector nil

)

rslt

)

)

data-list

)

Also, not sure if you will need it or not but I use ADOLisp Subroutines to access a MSACESS Database and get info from it. You can search for ADOLisp to find all of those codes.

 

As far as the dynamic thing, I'm not even sure if it can be done. You might have to write a separate code to make changes to your table and upon completion it refreshes the data. Maybe Someone else will have some ideas on that one.

Hope this helps.

Link to comment
Share on other sites

Here is some code that I use to do almost the exact same thing.

 

Gathers blocks by name

Changes layer of block to an attribute in the block

Filters out duplicates

Clears out existing schedule if it exists

Inserts lines into the schedule with info from the blocks

 

This looks fantastic! Just to reinterate a minute. This will build a BOM from the blocks that you add to your drawing, correct?

 

I am a pretty big newb to the AutoCAD world and received a need to have something similar. I have a drawing set with multiple blocks of several PID configurations we for multiple layouts in the same drawing. I had a question on how to change this to ask me what is being shown in the layout tab? Or is there a way to assign a tag to the properties of the items being displayed and have it update a table with the reference tag. So I assign part xyz1 and then in the table I make it into variable text of IF xyz1 exists then TRUE, True = string "xyz1 part #" if FALSE then "". And finally if xyz1 > 2 = "new part #"

 

Thoughts?

 

Thanks in advance, I hope I was somewhat clear.

Link to comment
Share on other sites

This looks fantastic! Just to reinterate a minute. This will build a BOM from the blocks that you add to your drawing, correct?

 

I am a pretty big newb to the AutoCAD world and received a need to have something similar. I have a drawing set with multiple blocks of several PID configurations we for multiple layouts in the same drawing. I had a question on how to change this to ask me what is being shown in the layout tab? Or is there a way to assign a tag to the properties of the items being displayed and have it update a table with the reference tag. So I assign part xyz1 and then in the table I make it into variable text of IF xyz1 exists then TRUE, True = string "xyz1 part #" if FALSE then "". And finally if xyz1 > 2 = "new part #"

 

Thoughts?

 

Thanks in advance, I hope I was somewhat clear.

 

Yes you could change the info being put into the table with an if or cond statement. They might be kinda lenghty But it wouldn't be a problem. Just do search for the values and depending on what was in them insert a different block with different info slots. This is kind of a long routine for a beginner but hey we all started some place right? My best advice is dont be afraid to get in there and get your hands dirty with some data. learn how to fully use your VLIDE and set some breakpoints and keep an eye on what kind of data your code is coming back with. Work on one routine at a time . That was what helped me the most. And the good fellas at the forum.

Link to comment
Share on other sites

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