Jump to content

Recommended Posts

Posted

Hey Guys,

Fuccaro was kind enough to help me out on a previous post and wrote a little script for me which basically searches a Drawing for Blocks with two specific attributes.

It looks like this:

(defun c:FindTwo()
;| Searches for blocks having two specific attributes
   Fuccaro Miklos
   2010.12 |;
 (setq ss (ssget "X" (list '(0 . "INSERT") '(66 . 1))))
 (setq a1 (getstring "\n1st attribute to search for ")
   a2 (getstring "\n2nd attribute to search for ")
   found 0
   )
 (repeat (setq i (sslength ss))
   (if (check (ssname ss (setq i (1- i))) a1 a2) (setq found (1+ found)))
   )
 (strcat " ---> " (itoa found) " block(s) found")
 )
(defun check (en a1 a2)
 (setq hit 0 a0 (cdr (assoc 0 (setq el (entget en)))))
 (while (/= a0 "SEQEND")
   (if (= a0 "ATTRIB") (if (member (cdr (assoc 1 el)) (list a1 a2)) (setq hit (1+ hit))))
   (setq a0 (cdr (assoc 0 (setq el (entget (setq en (entnext en)))))))
   )
 (= hit 2)
)

This does EXACTLY what I wanted to do. It is perfect. However it was my intention that once I found a way to find the blocks that I wanted, I would make a LISP which would find the blocks from a list of Data stored in an Excell file, or Text File, or even better Access Database file. (What file type doesnt matter to me though as I can just copy and paste the data from the Database to a new document)

Only problem is changing Fuccaros script to read the values from an external file is proving to be more difficult than I thought.

Any help would be appreciated.

(I decided to post a new Thread as my question isn't really related to the question that the Thread Fuccaro helped me on, and also I feel bad about pestering Fuccaro all the time to help me. :()

Thanks Guys!

-Craig

Posted

Note: I have been trying to read everything I can on how to do this, such as: http://www.pixelgraphicsinc.com/AutoLisp_File_Handling.html

That does help me, although I cannot find any tutorials/guides which are specific enough to what I am trying to do.

I hope I have explained what I am trying to do well enough. Basically, the part of the code that Fuccaro wrote:

(setq a1 (getstring "\n1st attribute to search for ") .,:*Search in Excell Spreadsheet, Collom 1*:,.

a2 (getstring "\n2nd attribute to search for ") .,:*Search in Excell Spreadsheet, Collom 2*:,.

 

Hope that makes sense.

Posted

Thans for the reply.

That program looks really good, but what I am trying to do is no doubt alot simpler.

My last post should explain more clearly.

Thanks!

-Craig

Posted

I have been working on this all day and I feel like I have got my head round it quite a bit.

All I really need to know now is how to read from a CSV file, and store the data as a variable.

I can do that bit, only I want to store the first bit of data before the ',' (comma) as a variable, then save the second bit of data after the ',' (comma) as a variable and so on and so forth till it reaches the end of the file.

I think I have all the rest of the code worked out (by that I mean I know what to do with the variables once I get them).

I have this so far:

(setq k 1)
(setq a "")
(setq lst nil)
(repeat (strlen st)
(if (= (substr st k 1) ",")
(progn
(setq lst (append lst (list (atof a))))
(setq a "")
)
(setq a (strcat a (substr st k 1)))
)
(setq k (+ k 1))
)
(setq lst (append lst (list (atof a))))
)

(defun c:rects ()
(setq f (open "C:/Documents and Settings/Marek_AU_Automation/Desktop/test.csv" "r")) ;-Opens the 

file to read
(setq dataline (read-line f))                ;-Reads the header
(setq dataline (read-line f))                ;-Reads the 1st data line
(while (/= dataline "THEEND")                ;-Loop until the end of the file
(setq dataline (parse_nums dataline))        ;-Parse the data line variable value
(princ dataline)
; ---ALL THE CODE TO SEARCH ETC SHOULD GO HERE---

(setq dataline (read-line f))              ;-Read the next data line
) 
                                         
(close f)                                    ;-Close the file
)

But I feel that I am going in the wrong direction, (parsing the data etc)

Thanks alot guys.

-Craig

Posted

Lee mac wrote a good CSV read program need to search here

 

Re many variables you need to keep reading a single character till end of line, once you find the first , save as var1 then delete from linevariable re search again find , save var2 delete from linevariable keep repeating OR find the position of , and then use substr

 

(while (setq new_line (read-line fopen))

(setq easting (substr new_line 1 8)

(setq northing (substr new_line 10 9))

(setq height (substr new_line 20 5))

Posted

If you want to interface directly with the Access MDB file, you could use ADOLisp. There is a PDF manual and an example for linking to a MDB file.

Posted

Thanks for the help man.

I will have a look for the program you mentioned just now.

I understand what you mean about how to do it (store var1, clear dataline, store var2...)

But I just thought that there must be an easier way to read some data from a CSV file. I could go through character by character, but the legnth of each string in the CSV file may varie, so I couldn't hard code the variables into the script (like store character 1 in 'var1' store character two in 'var2'...)

I mean I could just put an if statement before every variable being defined, like 'if character /= "," then store the next variable'

But I just think that would be messy, and I would have alot of un required lines of code. One string may only consit of 2 characters, then another consists of 10.

I hope I made sense.

I will look for the script you suggested though.

Thanks alot for your help!

-Craig

Posted
If you want to interface directly with the Access MDB file, you could use ADOLisp. There is a PDF manual and an example for linking to a MDB file.

Thanks so much dude!

I will have a look for that script right now.

I would just copy the code from the script and put it in my Search Attributes script. So the search criteria can be defined by what is in the Access Database.

Thanks!

-Craig

Posted (edited)

I downloaded the program to connect to an Access Database.

It may be possible somehow to acheive what I want using it, although it would be very difficult and im sure it must be easier than what I am making out.

This should explain:

PROGRAM.jpg

That is what the program I have just now looks like running, it prompts for two values, and I look up a CSV file myself, and copy the values.

CSVfile.JPG

That is what the CSV file that has the datas that I want to search for in it.

CODE.jpg

That is the code that I have for the program to search in CAD.

 

What I want to do, is rather than me look up the CSV file and type the value in Collum A into the command line, then the same for Collum B, thousands of times, add some code to the Script which looks up the values automatically from the CSV file.

This is however proving to be much more confusing than I first thought.

Hope that I explained it clearly enough now.

Thanks alot for all your help guys!

-Craig

Edited by lifeis
Posted

I think you really need to pick one method at the moment we have 3, read from excel, access database and a csv txt file personally I would do more searching re excel link there is lots of posts about how to read cell a1 & b1 then a2&b2 and so on much simpler and every one can generally use a spreadsheet.

Posted
But I just thought that there must be an easier way to read some data from a CSV file. I could go through character by character, but the legnth of each string in the CSV file may varie, so I couldn't hard code the variables into the script (like store character 1 in 'var1' store character two in 'var2'...)

I mean I could just put an if statement before every variable being defined, like 'if character /= "," then store the next variable'

But I just think that would be messy, and I would have alot of un required lines of code. One string may only consit of 2 characters, then another consists of 10.

In all but the Excel method, you work with lists of data. The excel method could use lists as well, but it would be possible to work directly with each cell in turn. The ADOLisp basically extracts a SQL query into a nested list, 1st item in the list is a list of column names, following items are lists of field values in the same order as the column names.

 

To get a similar representation from a CSV file, you need to read the file one line at a time (use read-line) into a string variable. Then you need to tokenize that string. There are various methods, you could do a search here for CSV tokenize. However, I do it slightly differently. I read all the lines into one single string variable, then send it to the RX:CSV-Token function in my RegExp.LSP file. This simply tokenizes the entire file to produce the exact same type of list as the ADOLisp does. Here's a sample of reading an entire CSV file using my code:

;;; -------------------------------------------------------------------------------------
;;; Sample use to tokenize a CSV file
;;; -------------------------------------------------------------------------------------
(defun RX:CSV-File-tokenize (fn / f fullstr str)
 (if (and (setq fn (findfile fn))
          (setq f (open fn "r"))
          (setq fullstr "")
     ) ;_ end of and
   (progn (while (setq str (read-line f))
            (setq fullstr (strcat fullstr "\n" str))
          ) ;_ end of while
          (close f)
   ) ;_ end of progn
 ) ;_ end of if
 (if fullstr (RX:CSV-Token (vl-string-trim "\n\r" fullstr)))
) ;_ end of defun

Or alternatively (may be a bit more efficient):

;;; -------------------------------------------------------------------------------------
;;; Sample use to tokenize a CSV file - list based
;;; -------------------------------------------------------------------------------------
(defun RX:CSV-File-tokenize-list (fn / f lst str)
 (if (and (setq fn (findfile fn))
          (setq f (open fn "r"))
     ) ;_ end of and
   (progn
     (while (setq str (read-line f))
       (setq lst (cons (car (RX:CSV-Token str)) lst))
     ) ;_ end of while
     (close f)
   ) ;_ end of progn
 ) ;_ end of if
 (reverse lst)
) ;_ end of defun

As BIGAL's stated I'd also advise you to go one of the 3 methods at first. You can later work on providing an option to read from any of the 3, once you've got one of them working. Usually it's a good idea to start off with the CSV, since that's much more of a universal storage.

 

The "normal" Excel method (i.e. through ActiveX) requires that the user has Excel installed. The ADOLisp allows for the use of MDB files with only the Access ODBC/ADO driver - no need for the entire Access program. BTW, the ADOLisp allows for reading (and probably writing) to XLS files as well - since it can use the Excel ODBC driver - no need for the Excel program.

 

In any case, I'd advise you obtain something like this nested list. The good point about it is that the 1st field in each row can be used as a "key". So that if the user types in the value, you can search for the relevant row by using assoc. E.g. say the data (as read from the CSV through my above routines) is stored in a variable called data, you can do the following:

(if (and (setq key (getstring "\nEnter the key: "))
        (setq row (assoc key data))
        )
 (progn
   (princ "\nThe values are:\n")
   (princ row)
 )
)

So as long as your 1st column is unique, you'll get the "correct" row. If it's not unique you'll only get the 1st one found this way. Otherwise search for a routine called massoc which will extract all the rows with the key as its 1st field.

 

Then later all you need to do to extend to MDB/XLS/AnythingElse as well is to write some code which extracts the data into a similar list. This means you've made your routine expendable - helps a lot in the long run.

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