RocketBott Posted March 27, 2009 Posted March 27, 2009 At the moment I have a string of text to represent a wire TB[25] - K201/1.0mm/GY or K201/1.0mm/GY - TB[25] dependant on which side of equipment it's attached to. I need to extract the K201 (wire No.) part to a text file. All text in the string can change dependant on No.,Size,Colour,Destination. The green parts will be constant. I have a few lisp's that extract the text string but need to know if there is a way to filter out the wire No. Idealy the lisp would select all single line text in the dwg, filter out the wire No. then write to a txt file one line per No. in a specified folder with the same file name as the dwg. I have tried using blocks with attributes but they do not expand with different string lengths & dynamic block have too many problems. Sample dwg attached. Thanks 04_ITRTR_FR.dwg Quote
VVA Posted March 27, 2009 Posted March 27, 2009 Try this function. It will be return a list of part text string if you want (I hope). *** ADD Add command GPT ;;Get Part Text (defun C:GPT ( / file ret count) (if (and (setq ret (get-part-text)) (setq file (open (strcat "F:\\ENGINEER\\GENERIC\\Label Schedule\\Extracted Labels\\Ferrule_" (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname"))4)) ".txt") "a")) ) (progn (mapcar '(lambda(x)(write-line x file)) ret) (close file) (princ "\nWritting ") (princ (length ret)) (princ " text string to file") ) ) (princ) ) (defun get-part-text ( / ss lst item lst1 lst2 ret) (vl-load-com) ;;;Usage (get-part-text) (defun str-str-lst (str pat / i) (cond ((= str "") nil) ((setq i (vl-string-search pat str)) (cons (substr str 1 i) (str-str-lst (substr str (+ (strlen pat) 1 i)) pat) ) ;_ cons ) (t (list str)) ) ;_ cond ) (if (setq ss (ssget "_X" (list(cons 0 "TEXT")(cons 410 (getvar "CTAB"))))) (progn (repeat (setq item (sslength ss)) ;_ end setq (setq lst (cons (cdr(assoc 1(entget(ssname ss (setq item (1- item)))))) lst)) ) (foreach txt lst (setq lst1 (str-str-lst txt " ")) (foreach part-txt lst1 (setq lst2 (str-str-lst part-txt "/")) (if (and (> (length lst2) 1) (wcmatch (nth 1 lst2) "*mm") ) (setq ret (cons (nth 0 lst2) ret)) ) ) ) ) ) ret ) Quote
RocketBott Posted March 27, 2009 Author Posted March 27, 2009 That works great, thanks a lot. I'm not getting on very well writng that list to a file. I have created a txt file with (setq file (open (strcat "F:\\ENGINEER\\GENERIC\\Label Schedule\\Extracted Labels\\Ferrule_" (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname"))4)) ".txt") "a")) But can't write the string to the file (write-line ret file) ? I also need each No. on a new line. Sorry but I'm very new to this and have a lot to learn. Thanks again Quote
Lee Mac Posted March 27, 2009 Posted March 27, 2009 Try (mapcar '(lambda (x) (write-line x file)) ret) Also remember to use: (close file) at the end, otherwise the file will remain read-only and the data won't be written. Quote
RocketBott Posted March 27, 2009 Author Posted March 27, 2009 Thanks Lee that's it. I have a long way to go in understand all these different functions. Thank you both again. Quote
VVA Posted March 27, 2009 Posted March 27, 2009 I have a long way to go in understand all these different functions Add command to #2 Quote
Lee Mac Posted March 27, 2009 Posted March 27, 2009 Thanks Lee that's it.I have a long way to go in understand all these different functions. Thank you both again. Most people don't quite understand the mapcar and lambda functions too well - just think of it as doing something iteratively to each member of a list and outputting this as all the results in a list. Quote
RocketBott Posted March 30, 2009 Author Posted March 30, 2009 Nice one Vladimir I like the "Writing xxx text string to file" that will be a good check for the printer. I have sorted the list in alphabetical order with acad_strlsort and it's working great. Cheers Guys. Quote
RocketBott Posted March 31, 2009 Author Posted March 31, 2009 I have hit a problem. There are some drawings with Wire No,s with a / in them i.e. TB[25] - K201/S18/1.0mm/GY need the K201/S18 part. I have made some progress with a solution but have got stuck & I'm sure there will be a better way of solving this. Got the following which gives what I want on the screen but I can't get it to write to a file. This is only for the "double" Wire No's as above but would be need to combine this with the previous "single" Wire No Lisp. This one has the user select the text but I will need both options of selection (User & whole drawing) in seperate Lisp files. (defun c:get-part-text ( / ss lst item lst1 lst2 ret alp) (vl-load-com) ;;;Usage (get-part-text) (defun str-str-lst (str pat / i) (cond ((= str "") nil) ((setq i (vl-string-search pat str)) (cons (substr str 1 i) (str-str-lst (substr str (+ (strlen pat) 1 i)) pat) ) ;_ cons ) (t (list str)) ) ;_ cond ) (if (setq ss (ssget '((-4 . "<OR")(0 . "TEXT")(-4 . "OR>")))) (progn (repeat (setq item (sslength ss)) ;_ end setq (setq lst (cons (cdr(assoc 1(entget(ssname ss (setq item (1- item)))))) lst)) ) (foreach txt lst (setq lst1 (str-str-lst txt " ")) (foreach part-txt lst1 (setq lst2 (str-str-lst part-txt "/")) (if (and (> (length lst2) 1) (wcmatch (nth 2 lst2) "*mm") ) (setq ret (cons (strcat (nth 0 lst2) "/" (nth 1 lst2)) ret)) ) ) ) ) ) (setq alp (acad_strlsort ret)) alp ) Quote
VVA Posted March 31, 2009 Posted March 31, 2009 try it (defun c:get-part-text (/ ss lst item lst1 lst2 ret alp i tmp cnt) (vl-load-com) ;;;Usage (get-part-text) (defun str-str-lst (str pat / i) (cond ((= str "") nil) ((setq i (vl-string-search pat str)) (cons (substr str 1 i) (str-str-lst (substr str (+ (strlen pat) 1 i)) pat) ) ;_ cons ) (t (list str)) ) ;_ cond ) (if (setq ss (ssget '((-4 . "<OR") (0 . "TEXT") (-4 . "OR>")))) (progn (repeat (setq item (sslength ss)) ;_ end setq (setq lst (cons (cdr (assoc 1 (entget (ssname ss (setq item (1- item))))) ) lst ) ) ) (foreach txt lst (setq lst1 (str-str-lst txt " ")) (foreach part-txt lst1 (setq lst2 (str-str-lst part-txt "/")) (if (and (> (length lst2) 1) (setq cnt (vl-member-if '(lambda (x) (wcmatch x "*mm")) lst2) ) ) (progn (setq cnt (- (length lst2) (length cnt))) (setq i '-1 tmp nil ) (while (< (setq i (1+ i)) cnt) (setq tmp (cons (nth i lst2) tmp)) ) (setq tmp (reverse tmp)) (setq tmp (strcat (car tmp) (if (cdr tmp) (apply '(lambda (x) (strcat "/" x)) (cdr tmp)) "" ) ) ) (setq ret (cons tmp ret)) ) ) ) ) ) ) (setq alp (acad_strlsort ret)) alp ) Quote
Lee Mac Posted March 31, 2009 Posted March 31, 2009 Try this: -- provides user with alternative selection methods: ; TB[25] - K201/1.0mm/GY ; K201/1.0mm/GY - TB[25] ; TB[25] - K201/S18/1.0mm/GY (vl-load-com) (defun gettext (Str Pat flag / pos pStr) (if (setq pos (vl-string-search Pat Str)) (if flag (setq pStr (substr Str (+ pos 1 (strlen Pat)))) (setq pStr (substr Str 1 pos)))) pStr) (defun c:SubTxt (/ file ofile choix ss elst t1 t2 2t1 2t2 retlst) (or sub:def (setq sub:def "Auto")) (initget "Select Auto") (if (and (setq file (strcat (getvar "dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".txt")) (setq ofile (open file "a"))) (progn (setq choix (getkword (strcat "\nSelect Text Retrieval Method [select/Auto] <" sub:def ">: "))) (or (not choix) (setq sub:def choix)) (cond ((eq "Auto" sub:def) (setq ss (ssget "X" (list (cons 0 "*TEXT") (if (getvar "CTAB") (cons 410 (getvar "CTAB")) (cons 67 (- 1 (getvar "TILEMODE")))))))) ((eq "Select" sub:def) (setq ss (ssget (list (cons 0 "*TEXT") (if (getvar "CTAB") (cons 410 (getvar "CTAB")) (cons 67 (- 1 (getvar "TILEMODE"))))))))) (if ss (progn (setq elst (mapcar (function (lambda (x) (strcase (cdr (assoc 1 (entget x)))))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))) (foreach txt elst (cond ((wcmatch (setq t1 (gettext txt " - " T)) "*MM*") (setq t2 (vl-string->list (gettext t1 "MM" nil))) (while (/= 47 (last t2)) (setq t2 (reverse (cdr (reverse t2))))) (setq retlst (cons (vl-string-right-trim (chr 47) (vl-list->string t2)) retlst))) ((wcmatch (setq t1 (gettext txt " - " nil)) "*MM*") (setq t2 (vl-string->list (gettext t1 "MM" nil))) (while (/= 47 (last t2)) (setq t2 (reverse (cdr (reverse t2))))) (setq retlst (cons (vl-string-right-trim (chr 47) (vl-list->string t2)) retlst))))) (mapcar '(lambda (x) (write-line x ofile)) retlst) (princ (strcat "\nWriting " (rtos (length retlst)) " lines to file...")) (close ofile)) (princ "\n<!> No Text Found <!>"))) (princ "\n<!> Unable to Make File <!>")) (princ)) Quote
RocketBott Posted March 31, 2009 Author Posted March 31, 2009 Thanks guys I will have a look at those at work tomorrow. I'm off to Open Night at Primary School with the kids now so I might learn something there to help me get my head round this stuff. Cheers. Quote
Lee Mac Posted March 31, 2009 Posted March 31, 2009 Thanks guys I will have a look at those at work tomorrow.I'm off to Open Night at Primary School with the kids now so I might learn something there to help me get my head round this stuff. Cheers. Haha nice one Quote
RocketBott Posted April 1, 2009 Author Posted April 1, 2009 Vladimir that works perfect thanks. Lee your code has a problem when a text string without " - " is selected, it gives the error ; error: bad argument type: stringp nil. It is fine if only selecting the appropriate text. Quote
Lee Mac Posted April 1, 2009 Posted April 1, 2009 Ahh, my mistake - I didn't allow for the case in which the text is not in the correct format silly me: ; TB[25] - K201/1.0mm/GY ; K201/1.0mm/GY - TB[25] ; TB[25] - K201/S18/1.0mm/GY (vl-load-com) (defun gettext (Str Pat flag / pos pStr) (if (setq pos (vl-string-search Pat Str)) (if flag (setq pStr (substr Str (+ pos 1 (strlen Pat)))) (setq pStr (substr Str 1 pos)))) pStr) (defun c:SubTxt (/ file ofile choix ss elst t1 t2 2t1 2t2 retlst) (or sub:def (setq sub:def "Auto")) (initget "Select Auto") (if (and (setq file (strcat (getvar "dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".txt")) (setq ofile (open file "a"))) (progn (setq choix (getkword (strcat "\nSelect Text Retrieval Method [select/Auto] <" sub:def ">: "))) (or (not choix) (setq sub:def choix)) (cond ((eq "Auto" sub:def) (setq ss (ssget "X" (list (cons 0 "*TEXT") (if (getvar "CTAB") (cons 410 (getvar "CTAB")) (cons 67 (- 1 (getvar "TILEMODE")))))))) ((eq "Select" sub:def) (setq ss (ssget (list (cons 0 "*TEXT") (if (getvar "CTAB") (cons 410 (getvar "CTAB")) (cons 67 (- 1 (getvar "TILEMODE"))))))))) (if ss (progn (setq elst (mapcar (function (lambda (x) (strcase (cdr (assoc 1 (entget x)))))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))) (foreach txt elst (cond ((and (setq t1 (gettext txt " - " T)) (wcmatch t1 "*MM*")) (setq t2 (vl-string->list (gettext t1 "MM" nil))) (while (/= 47 (last t2)) (setq t2 (reverse (cdr (reverse t2))))) (setq retlst (cons (vl-string-right-trim (chr 47) (vl-list->string t2)) retlst))) ((and (setq t1 (gettext txt " - " nil)) (wcmatch t1 "*MM*")) (setq t2 (vl-string->list (gettext t1 "MM" nil))) (while (/= 47 (last t2)) (setq t2 (reverse (cdr (reverse t2))))) (setq retlst (cons (vl-string-right-trim (chr 47) (vl-list->string t2)) retlst))) (T nil))) (mapcar '(lambda (x) (write-line x ofile)) retlst) (princ (strcat "\nWriting " (rtos (length retlst)) " lines to file...")) (close ofile)) (princ "\n<!> No Text Found <!>"))) (princ "\n<!> Unable to Make File <!>")) (princ)) Quote
RocketBott Posted April 1, 2009 Author Posted April 1, 2009 Spot on now Lee. I hope that put's it to bed now. So many ways to do the same thing just makes it all the more difficult to know where to start when looking for something like this. I think I will have to stick to more "simple" code for a while yet. Once again thank you both very much for your help. Quote
Lee Mac Posted April 1, 2009 Posted April 1, 2009 Spot on now Lee.I hope that put's it to bed now. So many ways to do the same thing just makes it all the more difficult to know where to start when looking for something like this. I think I will have to stick to more "simple" code for a while yet. Once again thank you both very much for your help. Excellent - glad it works for you now There are so many ways to approach problems in LISP - its unbelievable how many solutions you can find to the same problem... makes things more exciting If you need anything else, or clarification on any aspect of the posted code - just let me know, and I'll be happy to help Cheers Lee Quote
Recommended Posts
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.