Newbie writing lisp output to a text file

Newbie writing lisp output to a text file

2lispsNbeyond
Explorer Explorer
1,403 Views
7 Replies
Message 1 of 8

Newbie writing lisp output to a text file

2lispsNbeyond
Explorer
Explorer

(defun C:ATTRIB_EXTRACT ( / EXTRACT_e EXTRACT_c EXTRACT_list )
(setq EXTRACT_e (car (entsel)))
;;; Loop through all the entities and...
(while (and EXTRACT_e (/= "SEQEND" (cdr (assoc 0 (entget EXTRACT_e)))))
(setq EXTRACT_c (entget EXTRACT_e))
;;; ...extract the ATTRIB information required
(if (= (cdr (assoc 0 EXTRACT_c)) "ATTRIB")
(setq EXTRACT_list (cons
(list
(cdr (assoc 2 EXTRACT_c)); attribute tag name ;
(cdr (assoc 1 EXTRACT_c)); attribute value ;
)
EXTRACT_list
)
)
)
(setq EXTRACT_e (entnext EXTRACT_e))
)
EXTRACT_list
)

Hello Community,

I found this lisp routine (not sure where but, thanks to whom ever wrote it) that extracts the attribute data from a block.
I simply want to add in a script to write the list to a csv or text file. Any help would be appreciated and thank you in advance.

 

0 Likes
Accepted solutions (4)
1,404 Views
7 Replies
Replies (7)
Message 2 of 8

john.uhden
Mentor
Mentor
Accepted solution

@2lispsNbeyond 

I see that your extract_list consists of lists of each attribute in the form '("TAG" "VALUE").

To create a comma-delimited .CSV you can use this:

(defun list2csv (lst / file fp)

  (setq file (getfiled "Select output file" (getvar "dwgprefix") "csv" 0))

  (setq fp (open file "w"))

  (foreach item lst

    (write-line (strcat (car item) "," (cadr item)) fp)

  )

  (close fp)

)

 

John F. Uhden

0 Likes
Message 3 of 8

john.uhden
Mentor
Mentor
Accepted solution

@2lispsNbeyond ,

You should not have emailed me privately.  This forum is for all to learn from any question, so keep your questions public (unless you want my postal address to send me lots of money).

Anyway, you need not trouble yourself (until you learn  lot more) about the function internals.

The function takes as input your extraction_list in the form '(("tag1" "value1")("tag2" "value2")...)

and adds a comma between the tag and the value and writes the string as one line each to a CSV file of your choice.  Only thing is I assumed that you wanted the path to be the same as the drawing.

If you want a different path or naming convention, then let us know and we'll help you with that.

BTW, the output file doesn't have to have a .CSV extension.  It could just as well be a .TXT file and Excel will recognize the format.  The .CSV extension merely saves a second of your time finding the file to open.

John F. Uhden

0 Likes
Message 4 of 8

2lispsNbeyond
Explorer
Explorer

No problem, I'm new to forums. Hold on to the postal address, I think I'm going to start a tab. I appreciate your help.

0 Likes
Message 5 of 8

Sea-Haven
Mentor
Mentor

Something like this.

 

 

(defun c:list2csv ( / fo obj att atts lst str x)
(setq fo (open "D:\\acadtemp\\output.csv" "W"))
(princ "\nPlease pick block Enter to stop ")
(while (setq ss  (ssget "+E:S" '((0 . "INSERT"))))
(setq obj (vlax-ename->vla-object (ssname ss 0)))
(setq atts (vlax-invoke obj 'Getattributes))
(setq lst '())
(foreach att atts
(setq lst (cons (vla-get-textstring att) lst))
)
(setq lst (reverse lst))
(setq str (nth 0 lst))
(setq x 0)
(repeat (- (length lst) 1)
(setq str (strcat str  "," (nth (setq x (1+ x)) lst)))
)
(write-line str fo)
(princ "\nPlease pick block Enter to stop ")
)
(close fo)
(princ)
)
(c:list2csv)

 

 A more advanced version would check that blocks have attributes etc. The code can be shortened a bit but felt better to show a couple of methods of handling data.

0 Likes
Message 6 of 8

2lispsNbeyond
Explorer
Explorer

Can I by pass the block selection and let it find a named block? Would I do it in this manner,

(setq EXTRACT_e (ssget "_X" '((0 . "INSERT") (2 . "BLOCKNAME")))) instead of (setq EXTRACT_e (car (entsel)))? I keep getting

a bad argument error.

 

 

0 Likes
Message 7 of 8

Kent1Cooper
Consultant
Consultant
Accepted solution

@2lispsNbeyond wrote:

.... I keep getting a bad argument error.


That's probably from this line:

(while (and EXTRACT_e (/= "SEQEND" (cdr (assoc 0 (entget EXTRACT_e)))))

The EXTRACT_e variable holds a selection set, not an entity name that is the only thing (entget) can get entity data from.  Even if you expect there to be only one such Block, you still need to "pull it out of" the selection set:
(while (and EXTRACT_e (/= "SEQEND" (cdr (assoc 0 (entget (ssname EXTRACT_e 0))))))

Kent Cooper, AIA
0 Likes
Message 8 of 8

john.uhden
Mentor
Mentor
Accepted solution

@2lispsNbeyond 

Try this, which wraps it all up (untested)...

(defun C:ATTRIB_EXTRACT ( / ss i extract EXTRACT_e EXTRACT_c EXTRACT_list )
  (defun extract (extract_e)
    ;;; Loop through all the entities and...
    (while (and EXTRACT_e (/= "SEQEND" (cdr (assoc 0 (entget EXTRACT_e)))))
      (setq EXTRACT_c (entget EXTRACT_e))
      ;;; ...extract the ATTRIB information required
      (if (= (cdr (assoc 0 EXTRACT_c)) "ATTRIB")
        (setq EXTRACT_list
	  (cons
            (list
              (cdr (assoc 2 EXTRACT_c)); attribute tag name ;
              (cdr (assoc 1 EXTRACT_c)); attribute value ;
            )
            EXTRACT_list
          )
        )
      )
    )
    (setq EXTRACT_e (entnext EXTRACT_e))
  )
  (defun list2csv (lst / file fp)
    (setq file (getfiled "Select output file" (getvar "dwgprefix") "csv" 0))
    (setq fp (open file "w"))
    (foreach item lst
      (write-line (strcat (car item) "," (cadr item)) fp)
    )
    (close fp)
  )
  (setq ss (ssget "_X" '((0 . "INSERT") (2 . "BLOCKNAME")(66 . 1))))
  (repeat (setq i (sslength ss))
    (extract (ssname ss (setq i (1- i))))
  )
  (list2csv EXTRACT_list)
  (princ)
)

John F. Uhden

0 Likes