Jump to content

Proper Syntax to Split Delimeted Record to Variable


GregGleason

Recommended Posts

I imagine this code needs just a quick fix.

 

I am reading a CSV, split the record to a variable so I can test variables.

 

I am getting an error when I try to invoke: (LM:str->lst fil ",")

 

(defun c:ReadMyCSV ()
;; String to List  -  Lee Mac
;; Separates a string using a given delimiter
;; str - [str] String to process
;; del - [str] Delimiter by which to separate the string
;; Returns: [lst] List of strings

(defun LM:str->lst ( str del / pos )
   (if (setq pos (vl-string-search del str))
       (cons (substr str 1 pos) (LM:str->lst (substr str (+ pos 1 (strlen del))) del))
       (list str)
   )
)

(setq fl (open "C:\\Users\\ggleason\\Documents\\CAD\\AutoCAD\\Lisp\\Book1.csv" "r")
)
(while (setq fil (read-line fl))
(if (not (null fil))
(princ (strcat fil "\n"))
; *****************************************
; *   Problem (LM:str->lst fil ",")
; *****************************************
(setq plt1 (append plt1 (list fil)))
) ;end if
) ;end while
(close fl) 
)

Any suggestions on how I should fix it?

 

Greg

Link to comment
Share on other sites

Try something like this:

'out' will be your list of lists

(defun c:readmycsv (/ fl out)
 ;; String to List  -  Lee Mac
 ;; Separates a string using a given delimiter
 ;; str - [str] String to process
 ;; del - [str] Delimiter by which to separate the string
 ;; Returns: [lst] List of strings
 (defun lm:str->lst (str del / pos)
   (if	(setq pos (vl-string-search del str))
     (cons (substr str 1 pos) (lm:str->lst (substr str (+ pos 1 (strlen del))) del))
     (list str)
   )
 )
 (if (setq fl (open "C:\\Users\\ggleason\\Documents\\CAD\\AutoCAD\\Lisp\\Book1.csv" "r"))
   (progn (while (setq fil (read-line fl)) (setq out (cons (lm:str->lst fil ",") out))) (close fl))
 )
 (reverse out)
)

Link to comment
Share on other sites

  • 2 weeks later...

ronjonp,

 

That works great!

 

The next question is how do I find when a given string matches the first record? The first record contains the .dwg name. I want to focus on the record that matches the file name of the open .dwg file.

 

Greg

Link to comment
Share on other sites

That works great!

 

The last thing I am trying to do is isolate on a field, in this case "DATE", and return that value (see sample .csv file).

 

Do I add another line of code underneath the replacement line of code you provided to do that?

Book1.csv

Link to comment
Share on other sites

Use this instead ( assumes that there is only one record ) will return the last item of the first sublist.

(last
 (car (vl-remove-if-not '(lambda (x) (wcmatch (strcase (car x)) (strcase (getvar 'dwgname)))) out))
)

Link to comment
Share on other sites

That is close to what I was going for, but it picked up "NONE" as the value and not the date value. Also, there could be a situation where the column changes.

Link to comment
Share on other sites

ronjonp,

 

Let me say I appreciate all of the help on getting me on the right track.

 

I revised the code so that it is a little more clear for me:

 

(defun c:readmycsv (/ fl out)
 ;; String to List  -  Lee Mac
 ;; Separates a string using a given delimiter
 ;; str - [str] String to process
 ;; del - [str] Delimiter by which to separate the string
 ;; Returns: [lst] List of strings
 (defun lm:str->lst (str del / pos)
   (if (setq pos (vl-string-search del str))
     (cons (substr str 1 pos) (lm:str->lst (substr str (+ pos 1 (strlen del))) del))
   )
 ); End of lm:str->lst
 (if (setq fl (open "C:\\Users\\ggleason\\Documents\\CAD\\AutoCAD\\Lisp\\Book1.csv" "r"))
   (progn 
      (setq mycount 0)
      (while 
         (setq fil 
            (read-line fl)
         )
         (setq mycount (1+ mycount))
         ; SYNTAX: (princ "\nMy Name is \nJohn")(princ)
         (princ mycount)(princ "\n")
         (setq out 
            (cons (lm:str->lst fil ",") out)
         )
         ; SYNTAX: (if (= 1 3) "YES!!" "no.")
         (if (= 1 mycount) (setq firstrec out))
      ) ; End of "While" loop
      (close fl)
      (princ (strcat (itoa mycount) " records read\n"))
    )
 ); End of "If" statement
 (princ firstrec)(princ "\n")
 (nth 3
   (car (vl-remove-if-not '(lambda (x) (wcmatch (strcase (car x)) (strcase (getvar 'dwgname)))) out))
 )
) ; End of c:readmycsv

The following is data in the list window:

 

Command: READMYCSV

1

2

3

4

5

5 records read

((FileName VEC# PLANT DRAWINGTITLE1 DRAWINGTITLE2 DRAWINGTITLE3 DRAWINGTITLE4 SCALE))

"OLEFINS RV MITIGATIONS - BATCH B"

What I discovered is that the last column is omitted from the data. The first record of the .csv is as follows:

 

FileName,VEC#,PLANT,DRAWINGTITLE1,DRAWINGTITLE2,DRAWINGTITLE3,DRAWINGTITLE4,SCALE,DATE

So the "DATE" column is being omitted by the code and it has "SCALE" as the last column.

 

What do you suggest to change the code so that the last column of values are included?

Link to comment
Share on other sites

Try:

(defun lm:str->lst (str del / pos) ; Modified version of Lee's code.
 (if (setq pos (vl-string-search del str))
   (cons (substr str 1 pos) (lm:str->lst (substr str (+ pos 1 (strlen del))) del))
   (list str)
 )
)

Edited by Roy_043
Link to comment
Share on other sites

As Roy pointed out .. the code you have has been modified from Lee's original .. not sure where you got it from?

 

Here's some commented changes to account for the 'DATE' column index changing.

(defun c:readmycsv (/ fil firstrec fl i mycount out rec)
 ;; String to List  -  Lee Mac
 ;; Separates a string using a given delimiter
 ;; str - [str] String to process
 ;; del - [str] Delimiter by which to separate the string
 ;; Returns: [lst] List of strings
 (defun lm:str->lst (str del / pos)
   (if	(setq pos (vl-string-search del str))
     (cons (substr str 1 pos) (lm:str->lst (substr str (+ pos 1 (strlen del))) del))
     (list str)
   )
 )					; End of lm:str->lst
 (if (setq fl (open "C:\\Users\\ggleason\\Documents\\CAD\\AutoCAD\\Lisp\\Book1.csv" "r"))
   (progn (setq mycount 0)
   (while (setq fil (read-line fl))
     (setq mycount (1+ mycount)) ; SYNTAX: (princ "\nMy Name is \nJohn")(princ)
     (princ mycount)
     (princ "\n")
     (setq out (cons (lm:str->lst fil ",") out)) ; SYNTAX: (if (= 1 3) "YES!!" "no.")
     (if (= 1 mycount)
       (setq firstrec out)
     )
   )				; End of "While" loop
   (close fl)
   (princ (strcat (itoa mycount) " records read\n"))
   )
 )					; End of "If" statement
 (princ firstrec)
 (princ "\n")
 ;; RJP - 11.28.2017
 ;; Reverse results to put them in correct order
 (setq out (reverse out))
 ;; Try to find index for 'DATE' column
 (if (and (setq
     i (vl-some '(lambda (x) (cond ((setq i (vl-position "DATE" (mapcar 'strcase x))) i))) out)
   )
   ;; Check if we have a record that matches the current drawing name, changed to vl-some for speed
   (setq rec
	  (vl-some '(lambda (x) (cond ((wcmatch (strcase (car x)) (strcase (getvar 'dwgname))) x)))
		   out
	  )
   )
     )
   ;; Return date
   (nth i rec)
 )
)					; End of c:readmycsv

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