samifox Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
rlx Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 5, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 5, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
rlx Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 5, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
Tharwat Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
rlx Posted August 5, 2018 Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 5, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
Tharwat Posted August 5, 2018 Share Posted August 5, 2018 Thanks sir You're welcome and good luck with your coding. Quote Link to comment Share on other sites More sharing options...
samifox Posted August 5, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 5, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
rlx Posted August 6, 2018 Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 6, 2018 Author Share Posted August 6, 2018 ; error: bad argument type: listp "A-DOOR-WINDOW" ... Thanks Shay please help Quote Link to comment Share on other sites More sharing options...
rlx Posted August 6, 2018 Share 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 Link to comment Share on other sites More sharing options...
samifox Posted August 7, 2018 Author Share Posted August 7, 2018 its working Thanks rlx Quote Link to comment Share on other sites More sharing options...
rlx Posted August 8, 2018 Share Posted August 8, 2018 its workingThanks rlx glad to help Quote Link to comment Share on other sites More sharing options...
samifox Posted August 8, 2018 Author Share 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 Link to comment Share on other sites More sharing options...
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.