From af2e0bcbb9ecef2960aac0e25013d80205c4ff80 Mon Sep 17 00:00:00 2001 From: ericremoreynolds Date: Fri, 18 Jul 2014 17:44:43 +0200 Subject: [PATCH] ExcelPython .xla add-in --- addin/xlpython.xlam | Bin 0 -> 26327 bytes addin/xlpython/__init__.py | 20 ++++++++ .../xlpython/xlpyserver.py | 36 ++++++++++++++- {.xlpy => addin/xlpython}/xlpython.bas | 14 +++--- {.xlpy => addin/xlpython}/xlpython.cfg | 4 +- xlpython/config.cpp | 10 ++-- xlpython/dispatch.cpp | 10 ++++ xlpython/utils.cpp | 43 ++++++++++++++++++ xlpython/utils.h | 4 ++ xlpython/xlpython.vcxproj | 16 +++---- 10 files changed, 134 insertions(+), 23 deletions(-) create mode 100644 addin/xlpython.xlam create mode 100644 addin/xlpython/__init__.py rename .xlpy/xlpython.py => addin/xlpython/xlpyserver.py (86%) rename {.xlpy => addin/xlpython}/xlpython.bas (72%) rename {.xlpy => addin/xlpython}/xlpython.cfg (93%) diff --git a/addin/xlpython.xlam b/addin/xlpython.xlam new file mode 100644 index 0000000000000000000000000000000000000000..db448009f41f92f49ed66b80d80e0dbdfc1d2452 GIT binary patch literal 26327 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ƪ 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 literal 0 HcmV?d00001 diff --git a/addin/xlpython/__init__.py b/addin/xlpython/__init__.py new file mode 100644 index 0000000..827f0ce --- /dev/null +++ b/addin/xlpython/__init__.py @@ -0,0 +1,20 @@ +def xlfunc(f = None, **kwargs): + def inner(f): + if f is None: + f = self + self = None + xlfunc = f.__xlfunc__ = {} + xlfunc["name"] = f.__name__ + xlfunc["doc"] = f.__doc__ if f.__doc__ is not None else "Python function '" + f.__name__ + "' defined in module '" + f.__module__ + "'." + xlargs = xlfunc["args"] = [] + for vname in f.__code__.co_varnames: + xlargs.append({ + "name": vname, + "marshal": "value" + }) + return f + import inspect + if f is not None and len(kwargs) == 0: + return inner(f) + else: + return inner \ No newline at end of file diff --git a/.xlpy/xlpython.py b/addin/xlpython/xlpyserver.py similarity index 86% rename from .xlpy/xlpython.py rename to addin/xlpython/xlpyserver.py index 87e2549..af60923 100644 --- a/.xlpy/xlpython.py +++ b/addin/xlpython/xlpyserver.py @@ -23,6 +23,23 @@ class XLPythonObject(object): _public_methods_ = [] def __init__(self, obj): self.obj = obj + +class XLPythonIterator(object): + _public_methods_ = [ "MoveNext", "Current" ] + + def __init__(self, obj): + self.iter = obj.__iter__() + self.current = None + + def MoveNext(self): + try: + self.current = self.iter.next() + return True + except StopIteration: + return False + + def Current(self): + return ToVariant(self.current) def FromVariant(var): try: @@ -34,7 +51,7 @@ def ToVariant(obj): return win32com.server.util.wrap(XLPythonObject(obj)) class XLPython(object): - _public_methods_ = [ 'Module', 'Tuple', 'Dict', 'List', 'Obj', 'Str', 'Var', 'Call', 'GetItem', 'SetItem', 'GetAttr', 'SetAttr', 'Eval', 'Exec', 'ShowConsole', 'Reload', 'AddPath' ] + _public_methods_ = [ 'Module', 'Tuple', 'Dict', 'List', 'Obj', 'Str', 'Var', 'Call', 'GetItem', 'SetItem', 'GetAttr', 'SetAttr', 'HasAttr', 'Eval', 'Exec', 'ShowConsole', 'Reload', 'AddPath', 'Builtins', 'Len', 'GetIter' ] def ShowConsole(self): import ctypes @@ -117,6 +134,14 @@ def Call(self, obj, *args): else: return ToVariant(getattr(obj, method)(*pargs, **kwargs)) + def Len(self, obj): + obj = FromVariant(obj) + return len(obj) + + def Builtins(self): + import __builtin__ + return ToVariant(__builtin__) + def GetItem(self, obj, key): obj = FromVariant(obj) key = FromVariant(key) @@ -139,6 +164,15 @@ def SetAttr(self, obj, attr, value): value = FromVariant(value) setattr(obj, attr, value) + def HasAttr(self, obj, attr): + obj = FromVariant(obj) + attr = FromVariant(attr) + return hasattr(obj, attr) + + def GetIter(self, obj): + obj = FromVariant(obj) + return win32com.server.util.wrap(XLPythonIterator(obj)) + def Eval(self, expr, *args): globals = None locals = None diff --git a/.xlpy/xlpython.bas b/addin/xlpython/xlpython.bas similarity index 72% rename from .xlpy/xlpython.bas rename to addin/xlpython/xlpython.bas index 180d118..ca7d697 100644 --- a/.xlpy/xlpython.bas +++ b/addin/xlpython/xlpython.bas @@ -3,18 +3,18 @@ Option Private Module Option Explicit #If win64 Then - Const XLPyDLLName As String = "xlpython64-2.0.0.dll" - Declare Function XLPyDLLActivate Lib "xlpython64-2.0.0.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long - Declare Function XLPyDLLNDims Lib "xlpython64-2.0.0.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long + Const XLPyDLLName As String = "xlpython64-2.0.1.dll" + Declare Function XLPyDLLActivate Lib "xlpython64-2.0.1.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long + Declare Function XLPyDLLNDims Lib "xlpython64-2.0.1.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long #Else - Private Const XLPyDLLName As String = "xlpython32-2.0.0.dll" - Private Declare Function XLPyDLLActivate Lib "xlpython32-2.0.0.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long - Private Declare Function XLPyDLLNDims Lib "xlpython32-2.0.0.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long + Private Const XLPyDLLName As String = "xlpython32-2.0.1.dll" + Private Declare Function XLPyDLLActivate Lib "xlpython32-2.0.1.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long + Private Declare Function XLPyDLLNDims Lib "xlpython32-2.0.1.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long #End If Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long Private Function XLPyFolder() As String - XLPyFolder = ThisWorkbook.Path + "\.xlpy" + XLPyFolder = ThisWorkbook.Path + "\xlpython" End Function Function XLPyConfig() As String diff --git a/.xlpy/xlpython.cfg b/addin/xlpython/xlpython.cfg similarity index 93% rename from .xlpy/xlpython.cfg rename to addin/xlpython/xlpython.cfg index c7159c4..2405e2f 100644 --- a/.xlpy/xlpython.cfg +++ b/addin/xlpython/xlpython.cfg @@ -27,10 +27,10 @@ # The value of variable xxx if it has been set, otherwise an empty string - does not raise an error # The CLSID of the object which will get created -CLSID = {C2922F29-0F9F-4A12-8E11-294A961423A1} +CLSID = $(RandomGUID) # The command line used to launch the COM server -Command = pythonw.exe -u "$(ConfigDir)\xlpython.py" $(CLSID) +Command = pythonw.exe -u "$(ConfigDir)\xlpyserver.py" $(CLSID) # Optionally redirect stdout and stderr RedirectOutput = $(ConfigDir)\$(ConfigName).log diff --git a/xlpython/config.cpp b/xlpython/config.cpp index 6ce803e..c44b27c 100644 --- a/xlpython/config.cpp +++ b/xlpython/config.cpp @@ -324,9 +324,8 @@ void Config::ActivateRPCServer() if(!CreateProcessA(NULL, cmdLine, NULL, NULL, TRUE, 0, envStr.p, workingDir.c_str(), &si, &pi)) { formatted_exception e; - e << "Could not create Python process.\n\n"; - if(this->HasValue("RedirectOutput")) - e << "Try consulting '" << this->GetValue("RedirectOutput") << "'.\n\n"; + e << "Could not create Python process.\n"; + e << "Error message: " << GetLastErrorMessage() << "\n"; e << "Command: " << cmdLine << "\nWorking Dir: " << workingDir; throw e; } @@ -348,9 +347,10 @@ void Config::ActivateRPCServer() if(dwExitCode != STILL_ACTIVE) { formatted_exception e; - e << "Python process exited before it was possible to create the interface object.\n\n"; + e << "Python process exited before it was possible to create the interface object."; if(this->HasValue("RedirectOutput")) - e << "Try consulting " << this->GetValue("RedirectOutput") << ".\n\n"; + e << " Try consulting '" << this->GetValue("RedirectOutput") << "'."; + e << "\n"; e << "Command: " << cmdLine << "\nWorking Dir: " << workingDir; throw e; } diff --git a/xlpython/dispatch.cpp b/xlpython/dispatch.cpp index 9a629de..a4cee86 100644 --- a/xlpython/dispatch.cpp +++ b/xlpython/dispatch.cpp @@ -65,5 +65,15 @@ HRESULT __stdcall CDispatchWrapper::Invoke(DISPID dispIdMember, REFIID riid, LCI VariantInit(&result); HRESULT hRet = pDispatch->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult == NULL ? &result : pVarResult, pExcepInfo, puArgErr); VariantClear(&result); + + //if(FAILED(hr)) + //{ + // BSTR bstrOld = pExcepInfo->bstrDescription; + // std::string + + + // SysFreeString(bstrOld); + //} + return hRet; } diff --git a/xlpython/utils.cpp b/xlpython/utils.cpp index 7ab8222..9cb84e3 100644 --- a/xlpython/utils.cpp +++ b/xlpython/utils.cpp @@ -28,6 +28,49 @@ void ToStdString(const wchar_t* ws, std::string& str) delete narrow; } +void ToStdString(BSTR bs, std::string& str) +{ + BOOL bUsedDefaultChar; + int len = (int) SysStringLen(bs); + AutoArrayDeleter narrow(new char[len+1]); + WideCharToMultiByte(CP_ACP, 0, bs, len, narrow.p, len+1, "?", &bUsedDefaultChar); + narrow.p[len] = 0; + str = narrow.p; +} + +void ToBStr(const std::string& str, BSTR& bs) +{ + int sz = (int) str.length() + 1; + OLECHAR* wide = new OLECHAR[sz]; + MultiByteToWideChar(CP_ACP, 0, str.c_str(), sz * sizeof(OLECHAR), wide, sz); + bs = SysAllocString(wide); + delete[] wide; +} + +std::string GetLastErrorMessage() +{ + DWORD dwError = GetLastError(); + char* lpMsgBuf; + + if(0 == FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwError, + 0, + (LPSTR) &lpMsgBuf, + 0, + NULL)) + { + return "Could not get error message: FormatMessage failed."; + } + + std::string ret = lpMsgBuf; + LocalFree(lpMsgBuf); + return ret; +} + const char* GetDLLPath() { static bool initialized = false; diff --git a/xlpython/utils.h b/xlpython/utils.h index 7b4ef11..4a85da4 100644 --- a/xlpython/utils.h +++ b/xlpython/utils.h @@ -1,6 +1,8 @@ void ToVariant(const char* str, VARIANT* var); void ToVariant(const std::string& str, VARIANT* var); void ToStdString(const wchar_t* ws, std::string& str); +void ToStdString(BSTR bs, std::string& str); +void ToBstr(const std::string& str, BSTR& bs); class formatted_exception : public std::exception { @@ -41,6 +43,8 @@ void NewGUID(GUID& guid); void GetLastWriteTime(const char* path, FILETIME* pFileTime); +std::string GetLastErrorMessage(); + static inline std::string strlower(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), std::tolower); diff --git a/xlpython/xlpython.vcxproj b/xlpython/xlpython.vcxproj index 47d972f..a567791 100644 --- a/xlpython/xlpython.vcxproj +++ b/xlpython/xlpython.vcxproj @@ -66,25 +66,25 @@ true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(ProjectName)$(PlatformArchitecture)-2.0.0 + $(ProjectName)$(PlatformArchitecture)-2.0.1 true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(ProjectName)$(PlatformArchitecture)-2.0.0 + $(ProjectName)$(PlatformArchitecture)-2.0.1 false $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(ProjectName)$(PlatformArchitecture)-2.0.0 + $(ProjectName)$(PlatformArchitecture)-2.0.1 false $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(ProjectName)$(PlatformArchitecture)-2.0.0 + $(ProjectName)$(PlatformArchitecture)-2.0.1 @@ -100,7 +100,7 @@ xlpython.def - xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir).xlpy" + xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)addin\xlpython" Copying dll to bin folder @@ -118,7 +118,7 @@ xlpython.def - xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir).xlpy" + xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)addin\xlpython" Copying dll to bin folder @@ -140,7 +140,7 @@ xlpython.def - xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir).xlpy" + xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)addin\xlpython" Copying dll to bin folder @@ -162,7 +162,7 @@ xlpython.def - xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir).xlpy" + xcopy /y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)addin\xlpython" Copying dll to bin folder