Jump to content

File handling : reading text file


samifox

Recommended Posts

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

Link to comment
Share on other sites

  • Replies 25
  • Created
  • Last Reply

Top Posters In This Topic

  • samifox

    13

  • rlx

    9

  • Lee Mac

    2

  • Tharwat

    2

Top Posters In This Topic

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

Link to comment
Share on other sites

(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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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"

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...