FabioSpaghetti
FabioSpaghetti

Reputation: 800

How can I plot a 3D wireframe in Excel?

using Excel interface, how can I plot a 3D wireframe? I have no clue how to do this ! but wanted to do by giving the coordinates of the joints where there are frames between them.

for simplicity of the Example, just immagine a 3D wireframe in the form of a cube.

enter image description here

Upvotes: 1

Views: 537

Answers (1)

S Meaden
S Meaden

Reputation: 8270

Ok, so I previously gave advice as to switch on the macro recorder but this would not give you the 3D mathematics required to draw wireframes. For that you need a library, Philip Rideout's SVG wireframes Python library which is written up here on his blog.

On my blog I have added some code which parses the SVG file generated by Philip Rideout's code and then converts the Polygon directives to Excel free from shapes on the worksheet. This is a screenshot of the output.

3D wireframe on an Excel worksheet

I have added the code here as well

class ScreenUpdatingRAII(object):
    def __init__(self, app, visible:bool=False):
        self.app = app
        self.saved = app.ScreenUpdating
        app.ScreenUpdating = visible

    def restore(self):
        self.app.ScreenUpdating = self.saved
        self.app = None


def convertSvgToExcelShapes(filename):
    import xml.etree.ElementTree as ET
    from win32com.client  import GetObject,Dispatch

    # code below is highly dependent on the child
    # structure because xpath was not working for me (my bad)
    dom = ET.parse(filename)
    rootxml = dom.getroot()
    g = rootxml[1] # second child 
    wb = Dispatch(GetObject(r"C:\Users\Simon\source\repos\WireframeExcelShapes\WireframeExcelShapes\WireframeExcelShapes.xlsx"))
    app = Dispatch(wb.Parent)
    ws = Dispatch(wb.Worksheets.Item("WireFrame"))

    shps = Dispatch(ws.Shapes)

    for x in shps:
        Dispatch(x).Delete()
    idx =0
    scale, xoffset, yoffset = 500, 300,300

    screenUpdates = ScreenUpdatingRAII(app)

    for polygon in g:

        # triple nested list comprehension parsing the points by splitting 
        # first by space then by comma then converting to float
        points = [[float(z[0])*scale+xoffset, float(z[1])*scale+yoffset] for z in [y.split(',') for y in [x for x in polygon.attrib['points'].split()]]]

        #print(points)
        msoEditingAuto,msoSegmentLine, msoFalse, msoTrue = 0,0,0, -1 

        freeformbuilder=shps.BuildFreeform(msoEditingAuto, points[0][0] , points[0][1])
        freeformbuilder.AddNodes(msoSegmentLine, msoEditingAuto, points[1][0] , points[1][1])
        freeformbuilder.AddNodes(msoSegmentLine, msoEditingAuto, points[2][0] , points[2][1])
        freeformbuilder.AddNodes(msoSegmentLine, msoEditingAuto, points[0][0], points[0][1])
        newShp = Dispatch(freeformbuilder.ConvertToShape())

        shpFill = Dispatch(newShp.Fill)

        shpFill.Visible = msoTrue
        shpFill.Transparency = 0.25
        shpFill.Solid
        shpFill.ForeColor.RGB = 0xFFFFFF 
        idx=+1

    screenUpdates.restore()
    pass



filename = "octahedron.svg" 
generate_svg(filename)
convertSvgToExcelShapes(filename)

You still have a little work to do to generate your own shape as the sample shape is an octahedron.

Upvotes: 2

Related Questions