Skip to content

Commit 495639c

Browse files
Added $(WorkbookDir) macro in config parser
Added @xlsub decorator Added vba keyword for @Xlarg decorator, allowing you to pass Application, ActiveWorkbook, etc. Now FromVariant automatically wraps objects using win32com.client.Dispatch
1 parent ad8724a commit 495639c

File tree

7 files changed

+54
-31
lines changed

7 files changed

+54
-31
lines changed

addin/xlpython.xlam

-1.86 KB
Binary file not shown.

addin/xlpython/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
__all__ = [
22
"xlfunc",
33
"xlret",
4-
"xlarg"
4+
"xlarg",
5+
"xlsub"
56
]
67

78
def xlfunc(f):
89
if not hasattr(f, "__xlfunc__"):
910
xlf = f.__xlfunc__ = {}
1011
xlf = f.__xlfunc__ = {}
1112
xlf["name"] = f.__name__
13+
xlf["sub"] = False
1214
xlargs = xlf["args"] = []
1315
xlargmap = xlf["argmap"] = {}
1416
for vpos, vname in enumerate(f.__code__.co_varnames[:f.__code__.co_argcount]):
1517
xlargs.append({
1618
"name": vname,
1719
"pos": vpos,
1820
"marshal": "var",
21+
"vba": None,
1922
"range": False,
2023
"dtype": None,
2124
"dims": -1,
@@ -28,6 +31,11 @@ def xlfunc(f):
2831
"doc": f.__doc__ if f.__doc__ is not None else "Python function '" + f.__name__ + "' defined in '" + str(f.func_code.co_filename) + "'."
2932
}
3033
return f
34+
35+
def xlsub(f):
36+
f = xlfunc(f)
37+
f.__xlfunc__["sub"] = True
38+
return f
3139

3240
xlretparams = set(("marshal", "lax", "doc"))
3341
def xlret(marshal=None, **kwargs):
@@ -44,7 +52,7 @@ def inner(f):
4452
return f
4553
return inner
4654

47-
xlargparams = set(("marshal", "dims", "dtype", "range", "doc"))
55+
xlargparams = set(("marshal", "dims", "dtype", "range", "doc", "vba"))
4856
def xlarg(arg, marshal=None, dims=None, **kwargs):
4957
if marshal is not None:
5058
kwargs["marshal"] = marshal
@@ -75,4 +83,4 @@ def udf_script(filename):
7583
vars = {}
7684
execfile(filename, vars)
7785
udf_scripts[filename] = (mtime, vars)
78-
return vars
86+
return vars

addin/xlpython/xlpyserver.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sys
2+
import types
23
import pythoncom
34
import pywintypes
45
import win32com.client
@@ -62,17 +63,21 @@ def Reset(self):
6263
def Clone(self):
6364
raise win32com.server.exception.COMException(scode = 0x80004001) # E_NOTIMPL
6465

66+
PyIDispatch = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
6567
def FromVariant(var):
6668
try:
67-
return win32com.server.util.unwrap(var).obj
69+
obj = win32com.server.util.unwrap(var).obj
6870
except:
69-
return var
71+
obj = var
72+
if type(obj) is PyIDispatch:
73+
obj = win32com.client.Dispatch(obj)
74+
return obj
7075

7176
def ToVariant(obj):
7277
return win32com.server.util.wrap(XLPythonObject(obj))
7378

7479
class XLPython(object):
75-
_public_methods_ = [ 'Module', 'Tuple', 'TupleFromArray', 'Dict', 'DictFromArray', 'List', 'ListFromArray', 'Obj', 'Str', 'Var', 'Call', 'GetItem', 'SetItem', 'DelItem', 'Contains', 'GetAttr', 'SetAttr', 'DelAttr', 'HasAttr', 'Eval', 'Exec', 'ShowConsole', 'Builtin', 'Len']
80+
_public_methods_ = [ 'Module', 'Tuple', 'TupleFromArray', 'Dict', 'DictFromArray', 'List', 'ListFromArray', 'Obj', 'Str', 'Var', 'Call', 'GetItem', 'SetItem', 'DelItem', 'Contains', 'GetAttr', 'SetAttr', 'DelAttr', 'HasAttr', 'Eval', 'Exec', 'ShowConsole', 'Builtin', 'Len', 'Bool' ]
7681

7782
def ShowConsole(self):
7883
import ctypes
@@ -123,8 +128,8 @@ def ListFromArray(self, elements):
123128
def List(self, *elements):
124129
return ToVariant(list((FromVariant(e) for e in elements)))
125130

126-
def Obj(self, var):
127-
return ToVariant(FromVariant(var))
131+
def Obj(self, var, dispatch=True):
132+
return ToVariant(FromVariant(var, dispatch))
128133

129134
def Str(self, obj):
130135
return str(FromVariant(obj))
@@ -139,6 +144,8 @@ def Var(self, obj, lax=False):
139144
value = value.tolist()
140145
if type(value) is tuple:
141146
return (value,)
147+
# elif isinstance(value, types.InstanceType) and value.__class__ is win32com.client.CDispatch:
148+
# return value._oleobj_
142149
else:
143150
return value
144151

@@ -164,6 +171,13 @@ def Len(self, obj):
164171
obj = FromVariant(obj)
165172
return len(obj)
166173

174+
def Bool(self, obj):
175+
obj = FromVariant(obj)
176+
if obj:
177+
return True
178+
else:
179+
return False
180+
167181
def Builtin(self):
168182
import __builtin__
169183
return ToVariant(__builtin__)

addin/xlpython/xlpython.bas

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ Option Private Module
33
Option Explicit
44

55
#If win64 Then
6-
Const XLPyDLLName As String = "xlpython64-2.0.2.dll"
7-
Declare Function XLPyDLLActivate Lib "xlpython64-2.0.2.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
8-
Declare Function XLPyDLLNDims Lib "xlpython64-2.0.2.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long
6+
Const XLPyDLLName As String = "xlpython64-2.0.3.dll"
7+
Declare Function XLPyDLLActivate Lib "xlpython64-2.0.3.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
8+
Declare Function XLPyDLLNDims Lib "xlpython64-2.0.3.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long
99
#Else
10-
Private Const XLPyDLLName As String = "xlpython32-2.0.2.dll"
11-
Private Declare Function XLPyDLLActivate Lib "xlpython32-2.0.2.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
12-
Private Declare Function XLPyDLLNDims Lib "xlpython32-2.0.2.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long
10+
Private Const XLPyDLLName As String = "xlpython32-2.0.3.dll"
11+
Private Declare Function XLPyDLLActivate Lib "xlpython32-2.0.3.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
12+
Private Declare Function XLPyDLLNDims Lib "xlpython32-2.0.3.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long
1313
#End If
1414
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
1515

addin/xlpython/xlpython.cfg

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
# Predefined macros
22
#
3-
# $(ConfigPath)
43
# $(ConfigDir)
5-
# $(ConfigFileName)
6-
# $(ConfigName)
7-
# $(ConfigExt)
8-
# The path, containing folder, filename with extension, filename without extension and extension of this configuration file
4+
# The folder containing this configuration file
95
#
10-
# $(DllPath)
11-
# $(DllDir)
12-
# $(DllFileName)
13-
# $(DllName)
14-
# $(DllExt)
15-
# The path, containing folder, filename with extension, filename without extension and extension of the xlpython DLL
6+
# $(WorkbookDir)
7+
# The parent folder of the folder containing this configuration file - where it is assumed the workbooks reside.
168
#
179
# $(RandomGUID)
1810
# A new random GUID - note that the macro will always resolve to the *same* GUID, not a new one each time
@@ -36,11 +28,11 @@ Command = pythonw.exe -u "$(ConfigDir)\xlpyserver.py" $(CLSID)
3628
RedirectOutput = $(ConfigDir)\$(ConfigName).log
3729

3830
# The working directory the COM server will be launched in
39-
WorkingDir = $(ConfigDir)\..
31+
WorkingDir = $(WorkbookDir)
4032

4133
# Optionally manipulate the environment variables.
4234
# Only variables listed in EnvironmentInclude will reach the process, if set.
4335
# Alternatively, all variables except those listed in EnvironmentExclude wll reach the process, if set.
4436
#EnvironmentInclude = PATH, PYTHONPATH, SYSTEMDRIVE, SYSTEMROOT
4537
#EnvironmentExclude = EXCLUDE, THESE, VARIABLES
46-
Environment:PYTHONPATH = $(ConfigDir)\..;$(?Environment:PYTHONPATH)
38+
Environment:PYTHONPATH = $(WorkbookDir);$(?Environment:PYTHONPATH)

xlpython/config.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ Config::Config(const std::string& filename)
6464

6565
SplitPath(filename, values, "Config");
6666
SplitPath(GetDLLPath(), values, "Dll");
67+
std::string configDir;
68+
if(TryGetValue("ConfigDir", configDir))
69+
{
70+
std::string workbookDir = configDir + "\\..";
71+
char workbookDirOut[MAX_PATH];
72+
if(0 == GetFullPathNameA(workbookDir.c_str(), MAX_PATH, workbookDirOut, NULL))
73+
throw formatted_exception() << "GetFullPathNameA failed: " << GetLastErrorMessage() << "\n" << "Argument: " << workbookDir;
74+
values["WorkbookDir"] = workbookDirOut;
75+
}
6776
AddEnvironmentVariables(values);
6877

6978
GUID guid;

xlpython/xlpython.vcxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,25 @@
6666
<LinkIncremental>true</LinkIncremental>
6767
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
6868
<IntDir>$(Platform)\$(Configuration)\</IntDir>
69-
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.2</TargetName>
69+
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.3</TargetName>
7070
</PropertyGroup>
7171
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
7272
<LinkIncremental>true</LinkIncremental>
7373
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
7474
<IntDir>$(Platform)\$(Configuration)\</IntDir>
75-
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.2</TargetName>
75+
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.3</TargetName>
7676
</PropertyGroup>
7777
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
7878
<LinkIncremental>false</LinkIncremental>
7979
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
8080
<IntDir>$(Platform)\$(Configuration)\</IntDir>
81-
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.2</TargetName>
81+
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.3</TargetName>
8282
</PropertyGroup>
8383
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
8484
<LinkIncremental>false</LinkIncremental>
8585
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
8686
<IntDir>$(Platform)\$(Configuration)\</IntDir>
87-
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.2</TargetName>
87+
<TargetName>$(ProjectName)$(PlatformArchitecture)-2.0.3</TargetName>
8888
</PropertyGroup>
8989
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
9090
<ClCompile>

0 commit comments

Comments
 (0)