Connect to Excel using VB Component in Rhino 8

Clement,

I guess I’m a little mixed up then. At the top of the thread the following line of code throws an error:

I have a macro crashing here in Rhino 8. Looking for a solution to this.

Eric

Hi @ebunn3, i can repeat that if you read my posts at the beginning of the thread. So you’re using Office 365 and IronPython in Rhino 8 using NETCore on Windows right ? What happens if you run this:

#! python 2
import System
progType = System.Type.GetTypeFromProgID("Excel.Application")
excelApp = System.Activator.CreateInstance(progType)
excelApp.Visible = True

does it open Excel ? If not what error do you get ? Did you try out referencing by path as shown above ?

_
c.

Clement

I’ve gone back and read though the entire thread again and did see that I missed this. When I run the following code that you supplied along with GetActiveObject I so now see that Excel opens. I can potentially use this now and start to check out my other scripts that employ Excel. Thank you again for being so patient.

#! python 2
import System
progType = System.Type.GetTypeFromProgID("Excel.Application")
excelApp = System.Activator.CreateInstance(progType)
excelApp.Visible = True

import os
user = os.environ["USERPROFILE"]
#C:\Users\ebunn\SEE RhinoScript
path = user + "/SEE RhinoScript/Utils/bin/Release/net48/Utils.dll"
print (path)

#! python 2
import clr
clr.AddReferenceToFileAndPath(path)

from Utils import *

app = Marshal2.GetActiveObject("Excel.Application")
print(app)

Eric

Clement,

Just an update on the last reply. I have tested this successfully with my other scripts and can now interact with Excel. I distribute all of my scripts to a group in my organization and have put the Utils directory in the master directory that I distribute and this seems to be solving my issues with Excel. I use Excel primarily as a database and need to read and write to it. Thanks again for all of your help.

Eric

Thought I would post the whole module that I’m using to read and write to Excel with the changes for Rhino 8. Also, the Utils folder that is used by the function “getRunnngXL”. Thanks to all for all the help with this.

Eric

#! python 2

#globals 
increment = 0
xlDown = -4121
xlToLeft = -4159
xlToRight = -4161
xlUp = -4162
xlWindowState = -4143
xlApp = None
Excel = None  

import System
import os
import clr
import Rhino

class Excel_Transfer:
    """Transfer UF Info to Excel"""
    def __init__(self,xlName,vals,wks_Name,XL_Close):
        self._xlName = xlName#path to workbook
        self._vals = vals#values to write to workbook
        self._wks_Name = wks_Name#worksheet name
        self._XL_Close = XL_Close#close Excel, True or False

    def getXL(self):
        """Gets the Excel Object"""
        #Set the Excel Object
        excel = None
        #Try to get running instance of Excel
        try:
            #Attempt to get running instance of Excel
            excel = getRunnngXL()
            if excel: 
                #Set the Excel Object
                self.Excel = excel
                return excel
            excel = None
        except:
            excel = None

        if excel == None:
            try:
                #Start Excel if there is no running instance
                #! python 2
                progType = System.Type.GetTypeFromProgID("Excel.Application")
                excelApp = System.Activator.CreateInstance(progType)
                excelApp.Visible = True
                #Set Excel Size
                excelApp.WindowState=xlWindowState # XlWindowState.xlNormal
                #Set the Excel Object
                self.Excel = excelApp
                excel = excelApp
                if excel: return excel
            except:
                if excel: return excel
                
                
    def XL_Close(self,workbook,worksheet):
        """Saves and Closes the Excel Workbook"""
        #Save Workbook
        workbook.Save()

        #Close Workbook
        if self._XL_Close == True:
            ct=0
            wbkName = workbook.name
            for i in self.Excel.Workbooks:
                #print(i.name)
                if i.name == wbkName:
                    workbook.Close()
                ct+=1
        if ct == 1:
            os.system('taskkill /f /im Excel.exe')#This kills all open instances of Excel
            #self.Excel.Quit()

    def updateXL(self):
        """Update Excel with New Values"""
        #Get the XL Object
        xlApp = self.getXL()
        
        fpeDir = self._xlName
        System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo("en-US")
        workbook = xlApp.Workbooks.Open(r"" + fpeDir + "")
        #print("" + fpeDir + "")

        #Get the Active Sheet
        worksheet = workbook.Worksheets[self._wks_Name]
#        print(worksheet.Name)
        if worksheet.Name != self._wks_Name:
            return
        
        #Loop through vals
        count = 1
        
        lLastRow = worksheet.Cells(worksheet.Rows.Count, 1).End(xlUp).Row
        lLastCol = worksheet.Cells(lLastRow ,worksheet.Columns.Count).End(xlToLeft).Column
        
        self._vals[0]=lLastRow+increment
        
        for i in self._vals:
            worksheet.Cells[lLastRow+increment,count].value = i
            count += 1

        #Save Workbook
        workbook.Save()
        
        #Close Workbook
        self.XL_Close(workbook,worksheet)

    def GetValsXL(self):
        """Get values from Excel Worksheet"""
        #Get the XL Object
        xlApp = self.getXL()

        fpeDir = self._xlName
        System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo("en-US")
        workbook = xlApp.Workbooks.Open(r"" + fpeDir + "")
        #        print("" + fpeDir + "")

        #Get the Active Sheet
        worksheet = workbook.Worksheets[self._wks_Name]
        print(worksheet.Name,self._wks_Name)
        if worksheet.Name != self._wks_Name:
            return

        #Loop through vals
        count = 1
        
        lLastRow = worksheet.Cells(worksheet.Rows.Count, 1).End(xlUp).Row
        lLastCol = worksheet.Cells(lLastRow ,worksheet.Columns.Count).End(xlToLeft).Column
         
        xlRange = worksheet.Range[worksheet.Cells[lLastRow,1],worksheet.Cells[lLastRow,lLastCol]]
        self._vals = xlRange.value2
        
        #Close Workbook
        self.XL_Close(workbook,worksheet)

        retVals = list(self._vals)
        #print(retVals)

        return retVals

def getRunnngXL():
    """Try to get a running instance of Excel."""
    try:
        user = os.environ["USERPROFILE"]
        #C:\Users\ebunn\SEE RhinoScript 
        #THIS IS THE PATH TO THE XL_Utils DIRECTORY THAT CONTAINS Utils.dll
        path = user + "/SEE RhinoScript/XL_Utils/bin/Release/net48/Utils.dll"
        #add reference to path
        clr.AddReferenceToFileAndPath(path)
        #Import Marshal2
        from Utils import Marshal2
        #get running instance of Excel
        excel = Marshal2.GetActiveObject("Excel.Application")
        print(excel,"Excel Running GetUtils")    
        return excel
    except:
        print("No Running Instance of Excel Get Utils")  
        return None
        
        
        
        

XL_Utils.zip (5.5 KB)