Help with export list to excel

Help with export list to excel

DC-MWA
Collaborator Collaborator
2,727 Views
22 Replies
Message 1 of 23

Help with export list to excel

DC-MWA
Collaborator
Collaborator

Hello,

I have a program that generates a master list of lists.

I'm looking to export the list to an excel file named CODE ANALYSIS on sheet DATA line 20

the list looks like this

((1_2 50.0 10.0 10.0) (2_3 50.0 20.0 20.0) (3_4 50.0 20.0 20.0) (4_5 50.0 10.0 10.0))

 

something like this:

 

Capture1.JPG

 

I've seen others but they are way more complex than this and I'm having a hard time "reverse engineering" the code found. As you all know my lisp skills are limited.

Thanks.

0 Likes
Accepted solutions (2)
2,728 Views
22 Replies
Replies (22)
Message 2 of 23

_gile
Consultant
Consultant

Hi,

 

Here's a quite old one (but I hope still relevant) which seems to reply to your request.

 

 

;;-------------------------------------------------------------------------------
;; gc:WriteExcel
;; Writes in an Excel file
;;
;; Arguments : 4
;;   filename   : complete path of the file
;;   sheet      : name of the sheet (or nil for the current sheet)
;;   startRange : name of the start cell (or nil for "A1")
;;   dataList   : list of sub-lists containing the data (one sub-list per row)
;;-------------------------------------------------------------------------------
(defun gc:WriteExcel (filename sheet    startRange        dataList /        *error*  xlApp
                      wBook    save     sheets   active   start    row      col      cells
                      n        cell
                     )
  (vl-load-com)

  (defun *error* (msg)
    (and msg
         (/= msg "Function cancelled")
         (princ (strcat "\nError: " msg))
    )
    (and wBook (vlax-invoke-method wBook 'Close :vlax-False))
    (and xlApp (vlax-invoke-method xlApp 'Quit))
    (and reg (vlax-release-object reg))
    (mapcar (function (lambda (obj) (and obj (vlax-release-object obj))))
            (list cell cells wBook xlApp)
    )
    (gc)
  )

  (setq xlapp (vlax-get-or-create-object "Excel.Application"))

  (if (findfile filename)
    (setq wBook (vlax-invoke-method (vlax-get-property xlapp 'WorkBooks) 'Open filename)
          save  T
    )
    (setq wBook (vlax-invoke-method (vlax-get-property xlapp 'WorkBooks) 'Add))
  )

  (if sheet
    (progn
      (setq sheets (vlax-get-property xlApp 'Sheets))
      (vlax-for s sheets
        (if (= (strcase (vlax-get-property s 'Name)) (strcase sheet))
          (progn
            (vlax-invoke-method s 'Activate)
            (setq active T)
          )
        )
      )
      (or active
          (vlax-put-property (vlax-invoke-method sheets 'Add) 'Name sheet)
      )
    )
  )

  (if startRange
    (setq start (gc:ColumnRow startRange)
          col   (car start)
          row   (cadr start)
    )
    (setq col 1
          row 1
    )
  )

  (setq cells (vlax-get-property xlApp 'Cells))
  (or startRange (vlax-invoke-method cells 'Clear))
  (foreach sub dataList
    (setq n col)
    (foreach data sub
      (setq cell (vlax-variant-value (vlax-get-property cells 'Item row n)))
      (if (= (type data) 'STR)
        (vlax-put-property cell 'NumberFormat "@")
      )
      (vlax-put-property cell 'Value2 data)
      (setq n (1+ n))
    )
    (setq row (1+ row))
  )

  (vlax-invoke-method
    (vlax-get-property
      (vlax-get-property xlApp 'ActiveSheet)
      'Columns
    )
    'AutoFit
  )

  (if save
    (vlax-invoke-method wBook 'Save)
    (if (and
          (< "11.0" (vlax-get-property xlapp "Version"))
          (= (strcase (vl-filename-extension filename) T) ".xlsx")
        )
      (vlax-invoke-method wBook 'SaveAs filename 51 "" "" :vlax-false :vlax-false 1 1)
      (vlax-invoke-method wBook 'SaveAs filename -4143 "" "" :vlax-false :vlax-false 1 1)
    )
  )

  (*error* nil)
)

;;-------------------------------------------------------------------------------
;; gc:ReadExcel
;; Returns a list of sub-lists containing the data of an Excel file (one sub-list per row)
;;
;; Arguments : 4
;;   filename   : complete path of the file
;;   sheet      : name of the sheet (or nil for the current sheet)
;;   startRange : name of the start cell (or nil for "A1")
;;   maxRange   : name of the cell where the reading have to stop,
;;                or "*" for the whole sheet, or nil or "" for the current range
;;-------------------------------------------------------------------------------
(defun gc:ReadExcel (filename  sheet     startRange          maxRange  /         *error*
                     xlApp     wBook wSheet      startCell startCol  startRow  maxCell   maxCol
                     maxRow    reg       cells     col       row       data      sub
                     lst
                    )

  (defun *error* (msg)
    (and msg
         (/= msg "Fonction annulée")
         (princ (strcat "\nErreur: " msg))
    )
    (and wBook (vlax-invoke-method wBook 'Close :vlax-False))
    (and xlApp (vlax-invoke-method xlApp 'Quit))
    (mapcar (function (lambda (obj) (and obj (vlax-release-object obj))))
            (list reg cells wSheet wBook xlApp)
    )
    (gc)
  )

  (setq xlapp (vlax-get-or-create-object "Excel.Application")
        wBook (vlax-invoke-method (vlax-get-property xlApp 'WorkBooks) 'Open filename)
  )

  (if sheet
    (vlax-for ws (vlax-get-property xlapp 'Sheets)
      (if (= (vlax-get-property ws 'Name) sheet)
        (vlax-invoke-method (setq wSheet ws) 'Activate)
      )
    )
    (setq wSheet (vlax-get-property wBook 'ActiveSheet))
  )

  (if startRange
    (setq startCell (gc:ColumnRow startRange)
          startCol  (car startCell)
          startRow  (cadr startCell)
    )
    (setq startRange
           "A1"
          startCol 1
          startRow 1
    )
  )

  (if (and maxRange (setq maxCell (gc:ColumnRow maxRange)))
    (setq maxCol (1+ (car MaxCell))
          maxRow (1+ (cadr MaxCell))
    )
    (setq reg    (if (= maxRange "*")
                   (vlax-get-property wSheet 'UsedRange)
                   (vlax-get-property
                     (vlax-get-property wSheet 'Range startRange)
                     'CurrentRegion
                   )
                 )
          maxRow (+ (vlax-get-property reg 'Row)
                    (vlax-get-property (vlax-get-property reg 'Rows) 'Count)
                 )
          maxCol (+ (vlax-get-property reg 'Column)
                    (vlax-get-property (vlax-get-property reg 'Columns) 'Count)
                 )
    )
  )

  (setq cells (vlax-get-property xlApp 'Cells)
        row maxRow
  )
  (while (< startRow row)
    (setq sub nil
          col maxCol
          row (1- row)
    )
    (while (< startCol col)
      (setq col (1- col)
            sub (cons
                  (vlax-variant-value
                    (vlax-get-Property
                      (vlax-variant-value (vlax-get-property cells 'Item row col))
                      'Value2
                    )
                  )
                  sub
                )
      )
    )
    (setq lst (cons sub lst))
  )

  (*error* nil)

  lst
)

;;-------------------------------------------------------------------------------
;; gc:ColumnRow 
;; Returns a list of the column row indices 
;; Argument: 1
;;   cell = name of the cell
;; Using example : (gc:ColumnRow "IV987") -> (256 987)
;;-------------------------------------------------------------------------------
(defun gc:ColumnRow (cell / col char row)
  (setq col "")
  (while (< 64 (ascii (setq char (strcase (substr cell 1 1)))) 91)
    (setq col  (strcat col char)
          cell (substr cell 2)
    )
  )
  (if (and (/= col "") (numberp (setq row (read Cell))))
    (list (gc:Alpha2Number col) row)
  )
)

;;-------------------------------------------------------------------------------
;; gc:Alpha2Number 
;; Converts a string into an integer
;; Arguments: 1
;;   str = string to convert
;; Using example : (gc:Alpha2Number "BU") = 73
;;-------------------------------------------------------------------------------
(defun gc:Alpha2Number (str / num)
  (if (= 0 (setq num (strlen str)))
    0
    (+ (* (- (ascii (strcase (substr str 1 1))) 64)
          (expt 26 (1- num))
       )
       (gc:Alpha2Number (substr str 2))
    )
  )
)

;;-------------------------------------------------------------------------------
;; gc:Number2Alpha - Convertit un nombre entier en chaîne alphabétique
;; Converts an integer into a string
;; Arguments: 1
;;   num = integer to convert
;; Using example : (gc:Number2Alpha 73) = "BU"
;;-------------------------------------------------------------------------------
(defun gc:Number2Alpha (num / val)
  (if (< num 27)
    (chr (+ 64 num))
    (if (= 0 (setq val (rem num 26)))
      (strcat (gc:Number2Alpha (1- (/ num 26))) "Z")
      (strcat (gc:Number2Alpha (/ num 26)) (chr (+ 64 val)))
    )
  )
)

 

 

In your case, simply do:

 

(gc:WriteExcel 
  (findfile "CODE ANALYSIS.xlsx")
  "DATA" 
  "A20" 
  (apply 
    'append 
	'((1_2 50.0 10.0 10.0) (2_3 50.0 20.0 20.0) (3_4 50.0 20.0 20.0) (4_5 50.0 10.0 10.0))
  )
)

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 23

DC-MWA
Collaborator
Collaborator

This looks like the ticket.

I test it and I get an error...

Error: bad argument type: consp 1_2

any ideas?

0 Likes
Message 4 of 23

_gile
Consultant
Consultant

Oops!... my mistake. the last argument have to be a list of lists.

And also, 1_2, 2_3, ... should be strings ("1_2",  "2_3", ...) instead of symbols.

 

Try like this:

 

 

 

(gc:WriteExcel
  (findfile "CODE ANALYSIS.xlsx")
  "DATA"
  "A20"
  (list
    (apply
      'append
      '(("1_2" 50.0 10.0 10.0)
	("2_3" 50.0 20.0 20.0)
	("3_4" 50.0 20.0 20.0)
	("4_5" 50.0 10.0 10.0)
       )
    )
  )
)

 

 

 

or simply like this (you only need a single sub-lists if you want to write on a single line).

 

 

(gc:WriteExcel 
  (findfile "CODE ANALYSIS.xlsx")
  "DATA" 
  "A20"
  '(("1_2" 50.0 10.0 10.0 "2_3" 50.0 20.0 20.0 "3_4" 50.0 20.0 20.0 "4_5" 50.0 10.0 10.0))
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 23

DC-MWA
Collaborator
Collaborator

That worked.

Question:

If I have a variable that contains this

((1_2 50.0 10.0 10.0)(2_3 50.0 20.0 20.0)(3_4 50.0 20.0 20.0)(4_5 50.0 10.0 20.0))

 

how do i get it to read like this?

(("1_2" 50.0 10.0 10.0 "2_3" 50.0 20.0 20.0 "3_4" 50.0 20.0 20.0 "4_5" 50.0 10.0 20.0))

 

Also, after the above, how do i make the program use the variable instead of an actual list as shown above?

0 Likes
Message 6 of 23

_gile
Consultant
Consultant
Accepted solution

@DC-MWA wrote:

If I have a variable that contains this

((1_2 50.0 10.0 10.0)(2_3 50.0 20.0 20.0)(3_4 50.0 20.0 20.0)(4_5 50.0 10.0 20.0))


1. How did you get it?

 

 


@DC-MWA wrote:

how do i get it to read like this?

(("1_2" 50.0 10.0 10.0 "2_3" 50.0 20.0 20.0 "3_4" 50.0 20.0 20.0 "4_5" 50.0 10.0 20.0))


2. Here's a way:

(list
  (apply
    'append
    (mapcar '(lambda (l) (cons (vl-symbol-name (car l)) (cdr l)))
	    '((1_2 150.0 30.0 25.0)
	      (2_3 150.0 30.0 30.0)
	      (3_4 50.0 15.0 15.0)
	      (4_5 80.0 160.0 160.0)
	      (5_6 100.0 95.0 95.0)
	      (6_7 70.0 60.0 60.0)
	     )
    )
  )
)

but it would be much more simple to directly build the correct list format (see 1.)

 


@DC-MWA wrote:

Also, after the above, how do i make the program use the variable instead of an actual list as shown above?


3. Which variable?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 23

DC-MWA
Collaborator
Collaborator

Lists created:

;;; code by Dlanorh

(while (setq sel (entsel "\nSelect Building Polyline on Frontage : "))
(setq d_ent (car sel)
elen (vlax-curve-getdistatparam d_ent (vlax-curve-getendparam d_ent))
v_lst (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget d_ent)))
vlen (length v_lst)
p_pt (cadr sel)
v_p (fix (vlax-curve-getparamatpoint d_ent (vlax-curve-getclosestpointto d_ent p_pt)))
pt1 (reverse (cons 0.0 (reverse (nth v_p v_lst))))
pt2 (if (= v_p (1- vlen)) (reverse (cons 0.0 (reverse (nth 0 v_lst)))) (reverse (cons 0.0 (reverse (nth (1+ v_p) v_lst)))))
);end_setq

(if (rh:cwpl (vlax-ename->vla-object d_ent))
(setq ang (+ (angle '(0.0 0.0 0.0) (vlax-curve-getfirstderiv d_ent v_p)) (* pi 0.5)) chk T)
(setq ang (- (angle '(0.0 0.0 0.0) (vlax-curve-getfirstderiv d_ent v_p)) (* pi 0.5)) chk nil)
);end_if

(setq slen (distance pt1 pt2)
x_obj (vlax-invoke c_spc 'addray pt1 (polar pt1 ang 10.0))
pt3 (vlax-invoke x_obj 'intersectwith b_obj acextendnone)
);end_setq

(vlax-invoke x_obj 'move pt1 pt2)
(setq pt4 (vlax-invoke x_obj 'intersectwith b_obj acextendnone))
(vla-delete x_obj)

(if chk (setq d1 (distance pt1 pt3) d2 (distance pt2 pt4)) (setq d1 (distance pt2 pt4) d2 (distance pt1 pt3)))
(setq wav (/ (+ d1 d2) 2.0))

(cond ( (< wav (* 20.0 uf)) (setq wav 0.0 yard 0.0))
( (> wav (* 30.0 uf)) (setq wav (* 30.0 uf) yard (* wav slen) tyard (+ tyard yard) tslen (+ tslen slen))
)
(t (setq yard (* wav slen) tyard (+ tyard yard) tslen (+ tslen slen))
)
);end_cond

 

;;;make lists for excel added by dc
(setq bt-n (1+ bt-n))<-- Increment variable in loop
(setq bt-n2 (1+ bt-n2))<-- Increment variable in loop
(setq x_list (list (strcat (itoa bt-n) "_" (itoa bt-n2)) (/ slen 12) (/ d1 12) (/ d2 12)))
(princ x_list)
(setq master_list (append (list x_list) master_list))
(setq master_list_rev (reverse master_list))
);end_while

0 Likes
Message 8 of 23

dlanorh
Advisor
Advisor

Look Here

I am not one of the robots you're looking for

0 Likes
Message 9 of 23

CodeDing
Advisor
Advisor

 

*Ignore - I think this is progressing without my redundant input*

 

0 Likes
Message 10 of 23

_gile
Consultant
Consultant

@DC-MWA

It's very difficult to follow you. it looks like you started many post for the same task and now you try to put the different replies you got together. IMO, this is not the good way to process.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 23

DC-MWA
Collaborator
Collaborator

Well, dlanorh got me to where the program worked great. I realized after the fact that feeding this into excel would be a handy way to put the data straight into our code analysis spreadsheet.

Also, I like to learn and try to figure things out.

No disrespect to anyone, just a rooky trying to learn and make things more efficient for my projects.

-dc

0 Likes
Message 12 of 23

DC-MWA
Collaborator
Collaborator

I know my lisp skills are limited. And my methods bug you true programmers to no end.

I got the program to make the list,  the export to excel works.

I know my methods are not good from a programmers perspective, but is it possible to take my list and utilize it with gc:WriteExcel ?

0 Likes
Message 13 of 23

doaiena
Collaborator
Collaborator

It is actually quite the oposite. The fact that you are trying to write code on your own is a great thing and bugs nobody. I tried to glance through the thread but saw that your question is split up into 2 different threads, so its hard to follow what your exact problem is, what is already working and what is left to do. If you can clearly state what the current problem is, i'll be glad to help you as well as the other participants.

As far as i can tell, you want to export data /a list of lists/ to excel. Is the problem in creating the list structure in the way you want, or the export to excel?

0 Likes
Message 14 of 23

CodeDing
Advisor
Advisor

@DC-MWA ,

 

I do not believe anybody feels disrespected here. I hope not at least.

I feel like a common disconnect that happens when experienced programmers interact with less experienced ones is one of utter confusion. This mostly happens when the less experienced person implies or asks about something that causes the more experienced person to say to themselves: "Wait, how did we get here?". They will then begin to ask the person with less experience how they got to their current question. Most of the time this involves dissecting their overall code, and of course mentioning the majority of things that are either: wrong or 'not how that person would do it'.

 

In your particular case, I have a question that needs clarified.

This particular line of code...

(setq x_list (list (strcat (itoa bt-n) "_" (itoa bt-n2)) (/ slen 12) (/ d1 12) (/ d2 12)))

...hints to me that your particular lists should be returned in the following format...

(("1_2" 150.0 30.0 25.0) ("2_3" 150.0 30.0 30.0) ...)

 ...yet, when you include code in your post, you say it's in this format...

((1_2 150.0 30.0 25.0) (2_3 150.0 30.0 30.0) ...)

...The IMPORTANT difference here is that Without the quotes, this implies to us that those are symbols (not strings). This means that we will approach how to handle your data differently. Perhaps this is just a disconnect between the more-experienced and the less-experienced because I know that if you use the (princ ...) function to print your list to the command history, it will not include the quotes "", when in actuality, there will be quotes around your strings.

 

Can you begin by telling us if those items being created are strings, or symbols?

You can also use the (type ...) function to help us.. in your case, feed the first item in your first list to it and it should return either "STR" or "SYM"...

(type (caar x_list))

...I believe this will return a STR, but I think we need to be sure.

Best,

~DD

0 Likes
Message 15 of 23

DC-MWA
Collaborator
Collaborator

Thank you for your patience.

I tried type i got an error, but

I used print and it got:

(print master_list_rev)

=

(("1_2" 150.0 30.0 30.0) ("2_3" 150.0 30.0 25.0) ("3_4" 70.0 60.0 60.0) ("4_5" 100.0 95.0 95.0) ("5_6" 80.0 160.0 160.0) ("6_7" 50.0 15.0 15.0))

Message 16 of 23

DC-MWA
Collaborator
Collaborator

Forgive my ignorance here...

 

if this exports to excel:

(defun c:testxl ()
(gc:WriteExcel
(findfile "CODE ANALYSIS.xlsx")
"DATA"
"A20"
'(("1_2" "50.0" "10.0" "10.0" "2_3" 50.0 20.0 20.0 "3_4" 50.0 20.0 20.0 "4_5" 50.0 10.0 20.0))
)
(princ)
)

 

Then it seems to me all i need to do is modify this code to use my master_list_rev variable instead of

(("1_2" "50.0" "10.0" "10.0" "2_3" 50.0 20.0 20.0 "3_4" 50.0 20.0 20.0 "4_5" 50.0 10.0 20.0)).

Could this work?

again I know this is full "frankenlisp" but could it work?

0 Likes
Message 17 of 23

CodeDing
Advisor
Advisor
Accepted solution

@DC-MWA ,

 

I don't know your full code, but I think as long as you include @_gile 's code, you should be able to implement with his method, something like this:

(setq master_list '())
(while ...
.....
(setq x_list (list (strcat (itoa bt-n) "_" (itoa bt-n2)) (/ slen 12) (/ d1 12) (/ d2 12)))
(setq master_list (cons x_list master_list))
);while
(setq master_list (apply 'append (reverse master_list)))
.....
(gc:WriteExcel 
  (findfile "CODE ANALYSIS.xlsx")
  "DATA" 
  "A20" 
  (list master_list)
)
0 Likes
Message 18 of 23

DC-MWA
Collaborator
Collaborator

Ok I got it to go to excel.

 

Capture.JPG

Frankenlisp... lol

0 Likes
Message 19 of 23

DC-MWA
Collaborator
Collaborator

ty.

Let me incorporate into lisp...

0 Likes
Message 20 of 23

DC-MWA
Collaborator
Collaborator

Alright, thank you.

I've used up enough of your weekend.

You've been very patient with me and I appreciate it.

0 Likes