samifox Posted August 5, 2018 Posted August 5, 2018 Hi, Its been a while since I lisp, trying to go back to track The lisp should acquire the drawing database for specific layers and ones they are found it should set a specific color to them. The lisp should read an external txt file containing the layer name and color to set, in this format (layerName,11). Ive saved the text file, lisp,dwg at the same folder, and use this code (setq file (open "map.txt" "r")) (read-line file) (close file) ; error: bad argument type: FILE nil it seems like lisp cannot find the file , even if i use absolute file path it wont be found Help please shay Quote
rlx Posted August 5, 2018 Posted August 5, 2018 (if (and (setq fn (findfile "map.txt")) (setq fp (open fn "r")) ) (progn (setq data (read-line fp))(close fp)) (princ "\nUnable to find or open map.txt") ) Quote
samifox Posted August 5, 2018 Author Posted August 5, 2018 (if (and (setq fn (findfile "map.txt")) (setq fp (open fn "r")) ) (progn (setq data (read-line fp))(close fp)) (princ "\nUnable to find or open map.txt") ) it return nil Quote
Lee Mac Posted August 5, 2018 Posted August 5, 2018 What does this return for you? (defun c:test ( / des str txt ) (cond ( (not (setq txt (findfile "map.txt"))) (princ "\nmap.txt not found.") ) ( (not (setq des (open txt "r"))) (princ "\nmap.txt could not be opened for reading.") ) ( (princ "\nmap.txt found and opened for reading.") (setq str (read-line des)) (princ "\nRead 1 line from map.txt: ") (princ str) (close des) (princ "\nmap.txt closed.") ) ) (textpage) (princ) ) Quote
samifox Posted August 5, 2018 Author Posted August 5, 2018 Hi Im writing a program that manipulate layers by a given text file The text file might look something like : window,11 wall,144 my program will do the following: 1. Open the file 2. Read until it get to “,” (as ) 3. Read after the “,”(as ) 4. Look layers for 5. Set as the layer color 6. Loop til the end of file how do i perform number 2 and 3? Quote
Lee Mac Posted August 5, 2018 Posted August 5, 2018 2. Read until it get to “,” (as )3. Read after the “,”(as ) how do i perform number 2 and 3? Typically, you might use a function such as vl-string-position or vl-string-search to determine the position of the comma within the string, and then use substr with the appropriate index arguments to obtain the string either side of the comma; or alternatively, use list functions such as nth/car/cadr on the list returned by a function such as my String to List function. However, since you are using comma delimiters, you could also use DIESEL to obtain the data either side of the comma: _$ (setq str "MyLayer,MyColour") "MyLayer,MyColour" _$ (menucmd (strcat "m=$(index,0,\"" str "\")")) "MyLayer" _$ (menucmd (strcat "m=$(index,1,\"" str "\")")) "MyColour" Quote
rlx Posted August 5, 2018 Posted August 5, 2018 it return nil Does your file actually exist and has it the data you describe? If so (princ data) should return the first line in the file. Quote
samifox Posted August 5, 2018 Author Posted August 5, 2018 this is the code ive come to so far, its trow an error please help (defun tst (/ txt des str layer color l) ;; reading... (setq txt (findfile "map.txt")) (setq des (open txt "r")) (setq str (read-line des)) (close des) ;; divide string by comma (setq layer (menucmd (strcat "m=$(index,0,\"" str "\")"))) (setq color (menucmd (strcat "m=$(index,1,\"" str "\")"))) ;;set layer color (setq l (tblobjname "LAYER" layer)) (setq l (vlax-ename->vla-object l)) (vlax-put-property l 'Color color) (vl-load-com) ) Quote
Tharwat Posted August 5, 2018 Posted August 5, 2018 Hi, You can use my function below to separate a string with delimiter. (defun _peelstring (string del / str pos lst) ;; Tharwat - 03.Mar.2015 ;; (while (setq pos (vl-string-search del string 0)) (setq str (substr string 1 pos) string (substr string (+ pos (1+ (strlen del)))) ) (and str (/= str "") (setq lst (cons str lst))) ) (and string (/= string "") (setq lst (cons string lst))) (reverse lst) ) usage f the above function: _$ (_PEELSTRING "Layer1,Color,Ltype,LineWeight" ",") ("Layer1" "Color" "Ltype" "LineWeight") Quote
rlx Posted August 5, 2018 Posted August 5, 2018 just quickly written , change path to match and make sure names and colors in your data file are correct (defun c:samifox ( / actDoc fn-data-file fp-data-file data-list ) (vl-load-com) (setq actDoc (vla-get-activedocument (vlax-get-acad-object)) fn-data-file (findfile "d:\\Temp\\Lisp\\Cad-tutor\\samifox\\map.txt")) (cond ((null fn-data-file) (princ "\nData file map.txt not found")) ((not (setq fp-data-file (open fn-data-file "r"))) (princ "\nUnable to read from map.txt")) (t (while (setq data (read-line fp-data-file)) (if (setq pos (vl-string-position (ascii ",") data)) (setq data-list (cons (cons (substr data 1 pos) (substr data (+ 2 pos))) data-list)) ) ) ) ) ; data integrity test (cond ((not (vl-consp data-list)) (princ "\nNo usable layer data was found")) (t (mapcar 'fox-it data-list)) ) (princ) ) (defun _AddLayer ($lay) (if (vl-catch-all-error-p (setq $lay (vl-catch-all-apply 'vla-add (list (vla-get-layers actDoc) $lay)))) nil $lay)) (defun fox-it ( x / lay col l) (setq lay (car x) col (cdr x)) (if (not (tblsearch "layer" lay)) (_AddLayer lay)) (if (setq l (tblobjname "LAYER" lay)) (progn (setq l (vlax-ename->vla-object l)) (vlax-put-property l 'Color col)) ) ) Quote
samifox Posted August 5, 2018 Author Posted August 5, 2018 Hi, You can use my function below to separate a string with delimiter. (defun _peelstring (string del / str pos lst) ;; Tharwat - 03.Mar.2015 ;; (while (setq pos (vl-string-search del string 0)) (setq str (substr string 1 pos) string (substr string (+ pos (1+ (strlen del)))) ) (and str (/= str "") (setq lst (cons str lst))) ) (and string (/= string "") (setq lst (cons string lst))) (reverse lst) ) usage f the above function: _$ (_PEELSTRING "Layer1,Color,Ltype,LineWeight" ",") ("Layer1" "Color" "Ltype" "LineWeight") Thanks sir Quote
Tharwat Posted August 5, 2018 Posted August 5, 2018 Thanks sir You're welcome and good luck with your coding. Quote
samifox Posted August 5, 2018 Author Posted August 5, 2018 What does this return for you? (defun c:test ( / des str txt ) (cond ( (not (setq txt (findfile "map.txt"))) (princ "\nmap.txt not found.") ) ( (not (setq des (open txt "r"))) (princ "\nmap.txt could not be opened for reading.") ) ( (princ "\nmap.txt found and opened for reading.") (setq str (read-line des)) (princ "\nRead 1 line from map.txt: ") (princ str) (close des) (princ "\nmap.txt closed.") ) ) (textpage) (princ) ) Thanks LEE Quote
samifox Posted August 5, 2018 Author Posted August 5, 2018 just quickly written , change path to match and make sure names and colors in your data file are correct... (defun c:samifox ( / actDoc fn-data-file fp-data-file data-list )... you code had no compile error but it add new layer while i ask to set different color to existing layer that match the name. i modify your code (defun c:samifox ( / actDoc fn-data-file fp-data-file data-list ) (vl-load-com) (setq actDoc (vla-get-activedocument (vlax-get-acad-object));; get acad refernce fn-data-file (findfile "map.txt"));; look for file (cond ((null fn-data-file);;if file return nil (princ "\nData file map.txt not found")) ((not (setq fp-data-file (open fn-data-file "r"))) (princ "\nUnable to read from map.txt")) (t (while (setq data (read-line fp-data-file)) (if (setq pos (vl-string-position (ascii ",") data)) (setq data-list (cons (cons (substr data 1 pos) (substr data (+ 2 pos))) data-list)) ) ) ) ) ; data integrity test (cond ((not (vl-consp data-list)) (princ "\nNo usable layer data was found")) (t (mapcar 'setLayColor (caar data-list) [color="red"][b](cdar data-list)[/b][/color])) ) (princ) ) (defun setLayColor(lay col / l) (if (setq lay (tblsearch "layer" lay)) (if (setq l (tblobjname "LAYER" lay)) (progn (setq l (vlax-ename->vla-object l)) (vlax-put-property l 'Color col)) ) ) (princ) ) ; error: bad argument type: listp "A-DOOR-WINDOW" i also need it to seach in wildcard pattern, for example *wall*. how it would work?? Thanks Shay Quote
rlx Posted August 6, 2018 Posted August 6, 2018 (defun c:t1 ( / lst lay-name col) ; just a little test list (setq lst '(("25" . "10") ("35" . "50"))) ; get all layernames (vlax-for lay (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))) (setq lay-name (vla-get-name lay)) (if (vl-some '(lambda (x) (if (wcmatch lay-name (strcat "*" (car x) "*"))(setq col (cdr x)))) lst) (vl-catch-all-apply 'vla-put-color (list lay col))) ) (princ) ) this will give all layers that contain "25" color 10 and all layers that contain "35" color 50. You would use "wall" etc. In its present form it doesn't add a layer but I have very little time now .. real work... Quote
samifox Posted August 6, 2018 Author Posted August 6, 2018 ; error: bad argument type: listp "A-DOOR-WINDOW" ... Thanks Shay please help Quote
rlx Posted August 6, 2018 Posted August 6, 2018 try this (defun c:samifox ( / doc fn fp s l o n p c) (vl-load-com) (setq doc (vla-get-activedocument (vlax-get-acad-object)) fn (findfile "map.txt")) (cond ((null fn)(princ "\nData file map.txt not found")) ((not (setq fp (open fn "r")))(princ "\nUnable to read from map.txt")) (t (while (setq s (read-line fp)) (if (setq p (vl-string-position (ascii ",") s)) (setq l (cons (cons (substr s 1 p) (substr s (+ 2 p))) l)))) (if (vl-consp l) (vlax-for o (vla-get-layers doc) (setq n (vla-get-name o)) (if (vl-some '(lambda (x) (if (wcmatch n (strcat "*" (car x) "*"))(setq c (cdr x)))) l) (vl-catch-all-apply 'vla-put-color (list o c)))))) ) (princ) ) Quote
samifox Posted August 8, 2018 Author Posted August 8, 2018 I notice that wildcart search is not always the ultimate way to go since it call unrelevant layers. I need a toggle to be able to search the whole word or wildcard. How can it be done? 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.