Jump to content
samifox

File handling : reading text file

Recommended Posts

samifox

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

Share this post


Link to post
Share on other sites
rlx
(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")
)

Share this post


Link to post
Share on other sites
samifox
(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

Share this post


Link to post
Share on other sites
Lee Mac

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

Share this post


Link to post
Share on other sites
samifox

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?

Share this post


Link to post
Share on other sites
Lee Mac
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"

Share this post


Link to post
Share on other sites
rlx
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.

Share this post


Link to post
Share on other sites
samifox

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

Share this post


Link to post
Share on other sites
Tharwat

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")

Share this post


Link to post
Share on other sites
rlx

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

Share this post


Link to post
Share on other sites
samifox
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

Share this post


Link to post
Share on other sites
Tharwat
Thanks sir

 

You're welcome and good luck with your coding.

Share this post


Link to post
Share on other sites
samifox
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

Share this post


Link to post
Share on other sites
samifox
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

Share this post


Link to post
Share on other sites
rlx

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

Share this post


Link to post
Share on other sites
samifox

; error: bad argument type: listp "A-DOOR-WINDOW"

...

Thanks

Shay

 

please help

Share this post


Link to post
Share on other sites
rlx

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

Share this post


Link to post
Share on other sites
samifox

its working

Thanks rlx

Share this post


Link to post
Share on other sites
rlx
its working

Thanks rlx

 

 

glad to help :beer:

Share this post


Link to post
Share on other sites
samifox

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?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×