У меня есть два класса python, оба из которых доступны для сценариев независимо от VBA с использованием механизмов взаимодействия COM. Но я хочу, чтобы кто-то контролировал создание другого, в шаблоне родительского ребенка или в шаблоне Factory.
Я экспериментировал, но не могу работать, я перешел на MCRE ниже. Я новичок в Python. Мне было интересно, возможно ли каким-то образом наследовать mixin, который даст классу необходимые методы взаимодействия COM.
Итак, я создал MCRE, вот код Python, который должен быть запущен хотя бы один из командной строки с правами администратора, чтобы получить регистрацию COM (после этого администратор не требуется).
import win32com.client
class MyParent(object):
_reg_clsid_ = "{C61A7C6E-B657-4D55-AD36-8850B2E501AC}"
_reg_progid_ = 'PythonInVBA.MyParent'
_public_methods_ = ['Greet', 'GetChild']
def __init__(self): # Rules of Com say paramerless constructors
self.child = MyChild()
self.child.SetName("foo")
def Greet(self):
return "Hello world"
def GetChild(self):
return self.child
class MyChild(object):
_reg_clsid_ = "{15DAAEE2-3A37-4DE1-9973-CCD011DF4888}"
_reg_progid_ = 'PythonInVBA.MyChild'
_public_methods_ = ['Initialize', 'GetName', 'SetName']
def __init__(self): # Rules of Com say paramerless constructors
pass
def GetName(self):
return self.name
def SetName(self, sName):
self.name = sName
if __name__ == '__main__':
print ("Registering COM servers...")
import win32com.server.register
win32com.server.register.UseCommandLine(MyParent)
win32com.server.register.UseCommandLine(MyChild)
И вот код VBA, первые две процедуры Sub Procedures, но третий не удался.
Option Explicit
Sub Test_MyParent_OnItsOwn()
On Error GoTo ErrHand:
Dim objMyParent As Object
Set objMyParent = VBA.CreateObject("PythonInVBA.MyParent")
Debug.Assert objMyParent.Greet = "Hello world"
Exit Sub
ErrHand:
Debug.Print Err.Description
End Sub
Sub Test_MyChild_OnItsOwn()
On Error GoTo ErrHand:
Dim objMyChild As Object
Set objMyChild = VBA.CreateObject("PythonInVBA.MyChild")
objMyChild.SetName "Kevin"
Debug.Assert objMyChild.GetName = "Kevin"
''' success MyChild is scriptable
Exit Sub
ErrHand:
Debug.Print Err.Description
End Sub
Sub Test_MyParent_Returning_MyChild()
On Error GoTo ErrHand:
Dim objMyParent As Object
Set objMyParent = VBA.CreateObject("PythonInVBA.MyParent")
Dim objMyChild As Object
'* errors with Unexpected Python Error: TypeError: Objects of type 'MyChild' can not be converted to a COM VARIANT (but obtaining the buffer() of this object could)
Set objMyChild = objMyParent.GetChild()
Exit Sub
ErrHand:
Debug.Print Err.Description
End Sub
Я преобразовал содержимое комментария в ответ.
Это связано с тем, что MyChild не создается как COM-объект в MyParent.
Он будет работать, если вы измените его следующим образом.
оригинал:
def __init__(self): # Rules of Com say paramerless constructors
self.child = MyChild()
self.child.SetName("foo")
изменение:
def __init__(self): # Rules of Com say paramerless constructors
self.child = win32com.client.Dispatch("PythonInVBA.MyChild")
self.child.SetName("foo")
DISPID
изменился.