Spline XYZ Points to Excel

Spline XYZ Points to Excel

caddude
Advocate Advocate
3,119 Views
24 Replies
Message 1 of 25

Spline XYZ Points to Excel

caddude
Advocate
Advocate

Hello all,

 

I'm looking for a way to pull the XYZ coordinates of a 3D spline fit points and place them in an excel file.  I found this forum post but this was for creating a txt file which I tried to adjust to creating an excel file but didn't work.   Do you know of any lisp routines that can do this?  Thank you for any assistance.

0 Likes
Accepted solutions (1)
3,120 Views
24 Replies
Replies (24)
Message 2 of 25

Anonymous
Not applicable

Hi @caddude 
You can convert spline to polyline and then extract.


Convert spline to polyline: https://cadtips.cadalyst.com/curved-objects/splines-plines?q=curved-objects/splines-plines 

 

Extract polyline entities: http://www.lee-mac.com/polyinfo.html 

0 Likes
Message 3 of 25

Kent1Cooper
Consultant
Consultant

If you just want the Spline's fit points, that's a lot easier than the process in that other topic of placing Point objects along it and getting their insertion points.  For example, if the Spline is the last thing drawn:

 

Command: (setq fitpoints (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 11)) (entget (entlast)))))
((1.0 23.0 0.0) (3.0 23.0 0.0) (2.0 26.0 2.0) (0.0 26.0 4.0))

 

That list in the fitpoints variable list can be stepped through and each location written off to a .xls or .csv file, rather than .txt as in that other topic.  What would you want as a result?  The X, Y and Z coordinates each in separate cells in the same row for each fit point?  Or XYZ together somehow in a single cell for each one?  Something else?

 

The one thing I'm unsure of is how to determine what points are in its entity data list.  Certain things you can do will change the entity data from including (assoc 11) fit points to using (assoc 10) control vertices, and I don't see a way to get the list back to having the fit points.  If that's a possible problem, it looks like the fit points can still be obtained from VLA properties, in a raw list that would need to be subdivided into XYZ point lists, although with a quirk:

(-1.0 23.0 0.0 3.0 23.0 -5.55112e-17 2.0 26.0 2.0 6.34489e-17 26.0 4.0)

Those are "really" zero, and should be fixed before writing off to a file.

Kent Cooper, AIA
0 Likes
Message 4 of 25

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....
You can convert spline to polyline and then extract.

.... 


Either that routine, or the convert-to-Polyline option in the SPLINEDIT command [which wasn't available when that routine was written], results in more [potentially hugely more] Polyline vertices than the source Spline's fit points.  Maybe that's acceptable....

Kent Cooper, AIA
Message 5 of 25

caddude
Advocate
Advocate

hello @Kent1Cooper Thank you for the quick reply.  It would be great if it was a pick object (spline) as I'm not sure if it would be the last created object and then have each point, X Y Z, in a separate column.  This is what I'm going for.

Hopefully it will stay fit points and not be changed over to control points.

 

I was able to use a lisp routine for a 3D polyline, 3DPoly2File__GC, but the reason why I want to keep it a spline is that it's coming from a .iges file and I'd rather not changed it over to a polyline which could possibly add more points to the line.

0 Likes
Message 6 of 25

caddude
Advocate
Advocate
Hi @Anonymous
I was able to use a lisp routine for a 3D polyline, 3DPoly2File__GC, but the reason why I want to keep it a spline is that it's coming from a .iges file and I'd rather not change it over to a polyline which could possibly add more points to the line.
0 Likes
Message 7 of 25

Anonymous
Not applicable

Try this

it's just a test has no error function.
it will generate a file similar to this:

 

Frjuniornogueira_0-1641928254679.png

[code]

(defun c:exspline (/ fil sel fit coo)
  ;;set error
  ;;author - lee-mac
  (defun lst->str ( lst del ) (if (cdr lst) (strcat (car lst) del (lst->str (cdr lst) del)) (car lst)))
  
  (setq fil (open (strcat (getvar 'dwgprefix) (vl-filename-base (getvar 'dwgname)) ".csv" ) "w"));;creat file
  (write-line "SPLINE;COORDINATES" fil)
  (if (setq sel  (ssget '((0 . "SPLINE"))))
    (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex sel)))
      (setq fit (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 11)) (entget ent))))
      (setq coo (mapcar '(lambda (i) (list (rtos (car i)) (rtos (cadr i)) (rtos (caddr i)))) fit))
      (write-line
        (strcat 
          "SPLINE" ";" (lst->str (mapcar '(lambda (x) (strcat (car x) " " (cadr x) " " (caddr x))) coo) ", ")
        )
        fil
      )
    )
  )
  (close fil)
  (princ)
)

 

 

Message 8 of 25

hosneyalaa
Advisor
Advisor

hi

Attached example drawing and excel files 

 

 

0 Likes
Message 9 of 25

caddude
Advocate
Advocate

Hi @Anonymous ,

I just tried it and received an error: AutoLISP Error: bad argument type: stringp nil

 

This is the lisp that I created attached.  Any ideas what went wrong?

0 Likes
Message 10 of 25

caddude
Advocate
Advocate
HI @hosneyalaa, sorry but I don't see any attachments. I'm not sure they went through.
0 Likes
Message 11 of 25

Anonymous
Not applicable

Add an example of your .dwg

0 Likes
Message 12 of 25

caddude
Advocate
Advocate

Sure, I just created a simple spline with XYZ coords to test on and I also created a 2D spline to test.  Both had the same error result.  Which Spline did you test it out on?  WAs it open ended or closed?

0 Likes
Message 13 of 25

Anonymous
Not applicable

your spline is closed. Try now.

(defun c:exspline ( / fil sel fit coo)
  ;;set error
  ;;author - lee-mac
  (defun lst->str ( lst del ) (if (cdr lst) (strcat (car lst) del (lst->str (cdr lst) del)) (car lst)))
  
  (setq fil (open (strcat (getvar 'dwgprefix) (vl-filename-base (getvar 'dwgname)) ".csv" ) "w"));;creat file
  (write-line "SPLINE;COORDINATES" fil)
  (if (setq sel  (ssget '((0 . "SPLINE"))))
    (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex sel)))
      (setq fit (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent))))
      (setq coo (mapcar '(lambda (i) (list (rtos (car i)) (rtos (cadr i)) (rtos (caddr i))) ) fit))
      (write-line
        (strcat 
          "SPLINE" ";" (lst->str (mapcar '(lambda (x) (strcat (car x) " " (cadr x) " " (caddr x))) coo) ", ")
        )
        fil
      )
    )
  )
  (close fil)
  (princ)
)

 

Message 14 of 25

caddude
Advocate
Advocate

Hi @Anonymous ,

Thankyou very much for you help, I feel like it's almost there.  I tested it on the dwg that I sent earlier and I'm getting different numbers than the list tool.  The first point is the same but the rest are not.  Any idea why?Screenshot 2022-01-11 150105.png

0 Likes
Message 15 of 25

CADaSchtroumpf
Advisor
Advisor
Accepted solution

Answered to your ask?

(vl-load-com)
(defun c:SPLINE_DATA_OUT ( / sel output doc xls wks column nb ename obj l_pt k_list count)
  (defun l-coor2l-pt (lst flag / )
    (if lst
      (cons
        (list
          (car lst)
          (cadr lst)
          (if flag
            (+ (if (vlax-property-available-p obj 'Elevation) (vlax-get obj 'Elevation) 0.0) (caddr lst))
            (if (vlax-property-available-p obj 'Elevation) (vlax-get obj 'Elevation) 0.0)
          )
        )
        (l-coor2l-pt (if flag (cdddr lst) (cddr lst)) flag)
      )
    )
  )
  (setq
    sel (ssget '((0 . "SPLINE")))
    file_output (strcat (getvar "DWGPREFIX") (substr (getvar "DWGNAME") 1 (- (strlen (getvar "DWGNAME")) 4)) ".xlsm")
  )
  (cond
    ((and sel file_output)
      (setq doc (vla-get-activedocument (vlax-get-acad-object)))
      (vla-startundomark doc)
      (setq xls (vlax-get-or-create-object "Excel.Application"))
      (vlax-invoke (vlax-get xls 'workbooks) 'Add)
      (vlax-put xls 'Visible :vlax-true)
      (setq
        wks (vlax-get xls 'ActiveSheet)
        column 65
        count 1
      )
      (vlax-put (vlax-get-property wks 'range (strcat "A1:E" (itoa (sslength sel)))) 'Cells "")
      (foreach el '("HANDLE" "X" "Y" "Z")
        (vlax-put (vlax-get-property wks 'range (strcat (chr column) (itoa count))) 'value el)
        (setq column (1+ column))
      )
      (repeat (setq nb (sslength sel))
        (setq
          ename (ssname sel (setq nb (1- nb)))
          obj (vlax-ename->vla-object ename)
          l_pt (l-coor2l-pt (vlax-get obj 'FitPoints) T)
          k_list nil
        )
        (foreach el l_pt
          (setq k_list (cons (caddr el) (cons (cadr el) (cons (car el) (list (strcat "'" (cdr (assoc 5 (entget ename)))))))))
          (setq
            count (1+ count)
            column 65
          )
          (foreach el (reverse k_list)
            (vlax-put (vlax-get-property wks 'range (strcat (chr column) (itoa count))) 'value el)
            (setq
              column (1+ column)
            )
          )
        )
      )
      (mapcar 'vlax-release-object (list wks xls))
      (gc)
      (vla-endundomark doc)
    )
  )
  (prin1)
)
Message 16 of 25

caddude
Advocate
Advocate

Good Morning @CADaSchtroumpf ,

 

Thank you for your time on this code.  This one looks much closer to what I was trying to get and thank you for separating out the XYZ into separate columns.  My only question is for the Z axis, it shows in the excel file a different number than the AutoCAD List but only for the 0 axis ones.  Even for the last repeated point which should be the same as #2 and #7 in the excel list.   They should be on the 0 axis in the CAD file but when the lisp is run, it shows odd numbers.  Any idea why?  If this last thing is fixed, this would be the perfect code for what I'm looking for.Screenshot 2022-01-12 085353.png

Message 17 of 25

caddude
Advocate
Advocate
Weirdly enough, when I move the 3D spline from my test_spline.dwg file off of the 0 axis, I get all the correct numbers. But when there is a 0 point on the Z axis, I get an odd number. Any idea why that happens? Also, again, awesome job on this!
0 Likes
Message 18 of 25

CADaSchtroumpf
Advisor
Advisor

Try to change in the code the line 47

(setq k_list (cons (caddr el) (cons (cadr el) (cons (car el) (list (strcat "'" (cdr (assoc 5 (entget ename)))))))))

by

(setq k_list (cons (read (rtos (caddr el) 2 3)) (cons (read (rtos (cadr el) 2 3)) (cons (read (rtos (car el) 2 3)) (list (strcat "'" (cdr (assoc 5 (entget ename)))))))))

 

You can change precision of (rtos xxx 2 3) by 4 or more

0 Likes
Message 19 of 25

caddude
Advocate
Advocate
Hmm, nothing showed up when it generated the excel file. Is the updated code all on 1 line of code or should it be separated on the next line down?
When you mean change the precision, I'm guessing you mean the amount of numbers shown in the excel file? I'm ok with the more numbers as I can adjust that in excel. Sometimes it's best to have more precision and then you can cut it down later. 🙂
0 Likes
Message 20 of 25

CADaSchtroumpf
Advisor
Advisor

So keep and execute the first given code and in excel select the columns containing the XY and Z to with a right click change the format of the cells to affect the display of the numbers to the desired precision (you do not lose the real precision of the cells. numbers however)