diff --git a/.gitignore b/.gitignore
index 4892de6..fabc880 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,60 @@
-Debug/
-Release/
-*.suo
-*.user
-*.opensdf
-*.sdf
-*.pyo
-*.pyc
-*.dll
-/installer/*.exe
+.metadata
+*.py[cod]
+*~*
+
+# Config files
+*.cfg
+
+# SQLite Database
+*.db
+
+logfiles
+.settings
+
+# Jekyll
+_site
+
+# Sphinx
+_build
+
+# PyCharm
+.idea
+
+# NetBeans
+/nbproject
+
+# Mac
+*.DS_Store
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+*.zip
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+MANIFEST
+
+# logs
+pip-log.txt
+log*
+
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+
+# Translations
+*.mo
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 3563dd7..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright (c) 2014, ericremoreynolds
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
deleted file mode 100644
index a71cf30..0000000
--- a/README.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# ExcelPython v2
-
-Write Excel user-defined functions and macros in Python!
-
-```python
-from xlpython import *
-
-@xlfunc
-@xlarg("x", "nparray", 2)
-@xlarg("y", "nparray", 2)
-def matrixmult(x, y):
- return x.dot(y)
-```
-
-
-
-Check out the [tutorials](docs/) to get started! The only prerequisites are Excel and Python (2.6 - 3.x) with PyWin32 installed.
-
-### About ExcelPython
-
-ExcelPython is a lightweight, easily distributable library for interfacing Excel and Python. It enables easy access to Python scripts from Excel VBA, allowing you to substitute VBA with Python for complex automation tasks which would be facilitated by Python's extensive standard library while sparing you the complexities of Python COM programming.
-
-Do you like ExcelPython and find it useful? If so please consider donating something to support its continued development and get your name on the donor list!
-
-
-
-### Help me!
-
-Check out the [docs](docs/) folder for tutorials to help you get started and links to other resources. Failing that, try the [issues section](https://github.com/ericremoreynolds/excelpython/issues?q=) or the [discussion forum on SourceForge](https://sourceforge.net/p/excelpython/discussion/general/).
-
-If you still don't find your answer, need more help, find a bug, think of a useful new feature, or just want to give some feedback by letting us know what you're doing with ExcelPython, please go ahead and create an [issue ticket](https://github.com/ericremoreynolds/excelpython/issues/new)!
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..d5fb075
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,9 @@
+name: "ExcelPython - Write Excel UDFs in Python!"
+description: "ExcelPython is a free and open-source Microsoft Excel add-in which allows you to easily write user-defined functions and macros in Python instead of VBA."
+keywords: "Excel, VBA, Alternative, Python, Macro, UDF, Spreadsheet, open-source"
+
+baseurl: "http://ericremoreynolds.github.io/excelpython/"
+
+markdown: redcarpet
+redcarpet:
+ extensions: ['autolink', 'tables']
diff --git a/_includes/analyticstracking.html b/_includes/analyticstracking.html
new file mode 100644
index 0000000..33c61af
--- /dev/null
+++ b/_includes/analyticstracking.html
@@ -0,0 +1,10 @@
+
diff --git a/_includes/footer.html b/_includes/footer.html
new file mode 100644
index 0000000..3752041
--- /dev/null
+++ b/_includes/footer.html
@@ -0,0 +1,13 @@
+
diff --git a/_includes/navbar.html b/_includes/navbar.html
new file mode 100644
index 0000000..199f8dc
--- /dev/null
+++ b/_includes/navbar.html
@@ -0,0 +1,19 @@
+
+
+ {% include footer.html %}
+
+
+
+
+
+
+
+
+
diff --git a/addin/readme.md b/addin/readme.md
deleted file mode 100644
index e41e316..0000000
--- a/addin/readme.md
+++ /dev/null
@@ -1,4 +0,0 @@
-### Note
-
-The `xlpython_xlam_vba_code.bas` file is included in this directory in order to be able to easily diff commits on git (the `.xlam` file itself is not straight-forward to diff).
-In order for this to work, it must of course be manually exported from the `.xlam` file before each commit.
\ No newline at end of file
diff --git a/addin/xlpython.xlam b/addin/xlpython.xlam
deleted file mode 100644
index b42dfc8..0000000
Binary files a/addin/xlpython.xlam and /dev/null differ
diff --git a/addin/xlpython/__init__.py b/addin/xlpython/__init__.py
deleted file mode 100644
index 28e325c..0000000
--- a/addin/xlpython/__init__.py
+++ /dev/null
@@ -1,102 +0,0 @@
-__all__ = [
- "xlfunc",
- "xlret",
- "xlarg",
- "xlsub"
- ]
-
-def xlfunc(f = None, **kwargs):
- def inner(f):
- if not hasattr(f, "__xlfunc__"):
- xlf = f.__xlfunc__ = {}
- xlf = f.__xlfunc__ = {}
- xlf["name"] = f.__name__
- xlf["sub"] = False
- xlf["xlwings"] = kwargs.get("xlwings", None)
- xlargs = xlf["args"] = []
- xlargmap = xlf["argmap"] = {}
- nArgs = f.__code__.co_argcount
- if f.__code__.co_flags & 4: # function has an '*args' argument
- nArgs += 1
- for vpos, vname in enumerate(f.__code__.co_varnames[:nArgs]):
- xlargs.append({
- "name": vname,
- "pos": vpos,
- "marshal": "var",
- "vba": None,
- "range": False,
- "dtype": None,
- "dims": -1,
- "doc": "Positional argument " + str(vpos+1),
- "vararg": True if vpos == f.__code__.co_argcount else False
- })
- xlargmap[vname] = xlargs[-1]
- xlf["ret"] = {
- "marshal": "var",
- "lax": True,
- "doc": f.__doc__ if f.__doc__ is not None else "Python function '" + f.__name__ + "' defined in '" + str(f.__code__.co_filename) + "'."
- }
- return f
- if f is None:
- return inner
- else:
- return inner(f)
-
-def xlsub(f = None, **kwargs):
- def inner(f):
- f = xlfunc(**kwargs)(f)
- f.__xlfunc__["sub"] = True
- return f
- if f is None:
- return inner
- else:
- return inner(f)
-
-xlretparams = set(("marshal", "lax", "doc"))
-def xlret(marshal=None, **kwargs):
- if marshal is not None:
- kwargs["marshal"] = marshal
- def inner(f):
- xlf = xlfunc(f).__xlfunc__
- xlr = xlf["ret"]
- for k, v in kwargs.items():
- if k in xlretparams:
- xlr[k] = v
- else:
- raise Exception("Invalid parameter '" + k + "'.")
- return f
- return inner
-
-xlargparams = set(("marshal", "dims", "dtype", "range", "doc", "vba"))
-def xlarg(arg, marshal=None, dims=None, **kwargs):
- if marshal is not None:
- kwargs["marshal"] = marshal
- if dims is not None:
- kwargs["dims"] = dims
- def inner(f):
- xlf = xlfunc(f).__xlfunc__
- if arg not in xlf["argmap"]:
- raise Exception("Invalid argument name '" + arg + "'.")
- xla = xlf["argmap"][arg]
- for k, v in kwargs.items():
- if k in xlargparams:
- xla[k] = v
- else:
- raise Exception("Invalid parameter '" + k + "'.")
- return f
- return inner
-
-udf_scripts = {}
-def udf_script(filename):
- import os.path
- filename = filename.lower()
- mtime = os.path.getmtime(filename)
- if filename in udf_scripts:
- mtime2, vars = udf_scripts[filename]
- if mtime == mtime2:
- return vars
- vars = {}
- with open(filename, "r") as f:
- exec(compile(f.read(), filename, "exec"), vars)
- udf_scripts[filename] = (mtime, vars)
- return vars
\ No newline at end of file
diff --git a/addin/xlpython/fix_anaconda_pywin32.py b/addin/xlpython/fix_anaconda_pywin32.py
deleted file mode 100644
index c08a403..0000000
--- a/addin/xlpython/fix_anaconda_pywin32.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import sys
-import _win32sysloader
-import os
-
-# Anaconda and possibly other distributions have a bug in PyWin32,
-# the `pythoncom` module can't be loaded because some required
-# DLLs are located in the wrong place, so they aren't found
-
-# force windows to load them with the full path so that subsequent
-# imports work correctly
-
-filename = "pywintypes%d%d.dll" % (sys.version_info[0], sys.version_info[1])
-
-found = _win32sysloader.GetModuleFilename(filename)
-
-if not found:
- found = _win32sysloader.LoadModule(os.path.join(sys.prefix, 'lib', 'site-packages', 'win32', filename))
-
-
-
-
\ No newline at end of file
diff --git a/addin/xlpython/xlpyserver.py b/addin/xlpython/xlpyserver.py
deleted file mode 100644
index c82c69d..0000000
--- a/addin/xlpython/xlpyserver.py
+++ /dev/null
@@ -1,274 +0,0 @@
-import sys
-import fix_anaconda_pywin32
-import types
-import pythoncom
-import pywintypes
-import win32com.client
-import win32com.server.util as serverutil
-import win32com.server.dispatcher
-import win32com.server.policy
-import win32api
-import winerror
-
-# --- XLPython object class id ---
-
-clsid = pywintypes.IID(sys.argv[1])
-
-# --- the XLPython class itself ---
-
-class XLPythonOption(object):
- def __init__(self, option, value):
- self.option = option
- self.value = value
-
-class XLPythonObject(object):
- _public_methods_ = [ 'Item', 'Count' ]
- _public_attrs_ = [ '_NewEnum' ]
-
- def __init__(self, obj):
- self.obj = obj
-
- def _NewEnum(self):
- return win32com.server.util.wrap(XLPythonEnumerator(self.obj), iid=pythoncom.IID_IEnumVARIANT)
-
- def Item(self, key):
- return ToVariant(self.obj[key])
-
- def Count(self):
- return len(self.obj)
-
-class XLPythonEnumerator:
- _public_methods_ = [ "Next", "Skip", "Reset", "Clone" ]
-
- def __init__(self, gen):
- self.iter = gen.__iter__()
-
- def _query_interface_(self, iid):
- if iid == pythoncom.IID_IEnumVARIANT:
- return 1
-
- def Next(self, count):
- r = []
- try:
- r.append(ToVariant(next(self.iter)))
- except StopIteration:
- pass
- return r
-
- def Skip(self, count):
- raise win32com.server.exception.COMException(scode = 0x80004001) # E_NOTIMPL
-
- def Reset(self):
- raise win32com.server.exception.COMException(scode = 0x80004001) # E_NOTIMPL
-
- def Clone(self):
- raise win32com.server.exception.COMException(scode = 0x80004001) # E_NOTIMPL
-
-PyIDispatch = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
-def FromVariant(var):
- try:
- obj = win32com.server.util.unwrap(var).obj
- except:
- obj = var
- if type(obj) is PyIDispatch:
- obj = win32com.client.Dispatch(obj)
- return obj
-
-def ToVariant(obj):
- return win32com.server.util.wrap(XLPythonObject(obj))
-
-class XLPython(object):
- _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' ]
-
- def ShowConsole(self):
- import ctypes
- import sys
- ctypes.windll.kernel32.AllocConsole()
- sys.stdout = open("CONOUT$", "a", 0)
- sys.stderr = open("CONOUT$", "a", 0)
-
- def Module(self, module, reload=False):
- vars = {}
- exec("import " + module + " as the_module", vars)
- m = vars["the_module"]
- if reload:
- m = __builtins__.reload(m)
- return ToVariant(m)
-
- def TupleFromArray(self, elements):
- return self.Tuple(*elements)
-
- def Tuple(self, *elements):
- return ToVariant(tuple((FromVariant(e) for e in elements)))
-
- def DictFromArray(self, kvpairs):
- return self.Dict(*kvpairs)
-
- def Dict(self, *kvpairs):
- if len(kvpairs) % 2 != 0:
- raise Exception("Arguments must be alternating keys and values.")
- n = int(len(kvpairs) / 2)
- d = {}
- for k in range(n):
- key = FromVariant(kvpairs[2*k])
- value = FromVariant(kvpairs[2*k+1])
- d[key] = value
- return ToVariant(d)
-
- def ListFromArray(self, elements):
- return self.List(*elements)
-
- def List(self, *elements):
- return ToVariant(list((FromVariant(e) for e in elements)))
-
- def Obj(self, var, dispatch=True):
- return ToVariant(FromVariant(var, dispatch))
-
- def Str(self, obj):
- return str(FromVariant(obj))
-
- def Var(self, obj, lax=False):
- value = FromVariant(obj)
- if lax:
- t = type(value)
- if t is dict:
- value = tuple(value.items())
- elif t.__name__ == 'ndarray' and t.__module__ == 'numpy':
- value = value.tolist()
- if type(value) is tuple:
- return (value,)
- # elif isinstance(value, types.InstanceType) and value.__class__ is win32com.client.CDispatch:
- # return value._oleobj_
- else:
- return value
-
- def Call(self, obj, *args):
- obj = FromVariant(obj)
- method = None
- pargs = ()
- kwargs = {}
- for arg in args:
- arg = FromVariant(arg)
- if isinstance(arg, tuple):
- pargs = arg
- elif isinstance(arg, dict):
- kwargs = arg
- else:
- # assume string
- method = arg
- if method is None:
- return ToVariant(obj(*pargs, **kwargs))
- else:
- return ToVariant(getattr(obj, method)(*pargs, **kwargs))
-
- def Len(self, obj):
- obj = FromVariant(obj)
- return len(obj)
-
- def Bool(self, obj):
- obj = FromVariant(obj)
- if obj:
- return True
- else:
- return False
-
- def Builtin(self):
- import __builtin__
- return ToVariant(__builtin__)
-
- def GetItem(self, obj, key):
- obj = FromVariant(obj)
- key = FromVariant(key)
- return ToVariant(obj[key])
-
- def SetItem(self, obj, key, value):
- obj = FromVariant(obj)
- key = FromVariant(key)
- value = FromVariant(value)
- obj[key] = value
-
- def DelItem(self, obj, key):
- del obj[key]
-
- def Contains(self, obj, key):
- return key in obj
-
- def GetAttr(self, obj, attr):
- obj = FromVariant(obj)
- attr = FromVariant(attr)
- return ToVariant(getattr(obj, attr))
-
- def SetAttr(self, obj, attr, value):
- obj = FromVariant(obj)
- attr = FromVariant(attr)
- value = FromVariant(value)
- setattr(obj, attr, value)
-
- def HasAttr(self, obj, attr):
- obj = FromVariant(obj)
- attr = FromVariant(attr)
- return hasattr(obj, attr)
-
- def DelAttr(self, obj, attr):
- delattr(obj, attr)
-
- def Eval(self, expr, *args):
- globals = None
- locals = None
- for arg in args:
- arg = FromVariant(arg)
- if type(arg) is dict:
- if globals is None:
- globals = arg
- elif locals is None:
- locals = arg
- else:
- raise Exception("Eval can be called with at most 2 dictionary arguments")
- else:
- pass
- return ToVariant(eval(expr, globals, locals))
-
- def Exec(self, stmt, *args):
- globals = None
- locals = None
- for arg in args:
- arg = FromVariant(arg)
- if type(arg) is dict:
- if globals is None:
- globals = arg
- elif locals is None:
- locals = arg
- else:
- raise Exception("Exec can be called with at most 2 dictionary arguments")
- else:
- pass
- exec(stmt, globals, locals)
-
-# --- ovveride CreateInstance in default policy to instantiate the XLPython object ---
-
-BaseDefaultPolicy = win32com.server.policy.DefaultPolicy
-
-class MyPolicy(BaseDefaultPolicy):
- def _CreateInstance_(self, reqClsid, reqIID):
- if reqClsid == clsid:
- return serverutil.wrap(XLPython(), reqIID)
- else:
- return BaseDefaultPolicy._CreateInstance_(self, clsid, reqIID)
-
-win32com.server.policy.DefaultPolicy = MyPolicy
-
-# --- create the class factory and register it
-
-factory = pythoncom.MakePyFactory(clsid)
-
-clsctx = pythoncom.CLSCTX_LOCAL_SERVER
-flags = pythoncom.REGCLS_MULTIPLEUSE | pythoncom.REGCLS_SUSPENDED
-revokeId = pythoncom.CoRegisterClassObject(clsid, factory, clsctx, flags)
-
-pythoncom.EnableQuitMessage(win32api.GetCurrentThreadId())
-pythoncom.CoResumeClassObjects()
-
-pythoncom.PumpMessages()
-
-pythoncom.CoRevokeClassObject(revokeId)
-pythoncom.CoUninitialize()
diff --git a/addin/xlpython/xlpython.bas b/addin/xlpython/xlpython.bas
deleted file mode 100644
index 3ec4664..0000000
--- a/addin/xlpython/xlpython.bas
+++ /dev/null
@@ -1,49 +0,0 @@
-Attribute VB_Name = "xlpython"
-Option Private Module
-Option Explicit
-
-#If VBA7 Then
- #If win64 Then
- Const XLPyDLLName As String = "xlpython64-2.0.6.dll"
- Declare Function PtrSafe XLPyDLLActivate Lib "xlpython64-2.0.6.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
- Declare Function PtrSafe XLPyDLLNDims Lib "xlpython64-2.0.6.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.6.dll"
- Private Declare PtrSafe Function XLPyDLLActivate Lib "xlpython32-2.0.6.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
- Private Declare PtrSafe Function XLPyDLLNDims Lib "xlpython32-2.0.6.dll" (ByRef src As Variant, ByRef dims As Long, ByRef transpose As Boolean, ByRef dest As Variant) As Long
- #End If
- Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
-#Else
- #If win64 Then
- Const XLPyDLLName As String = "xlpython64-2.0.6.dll"
- Declare Function XLPyDLLActivate Lib "xlpython64-2.0.6.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
- Declare Function XLPyDLLNDims Lib "xlpython64-2.0.6.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.6.dll"
- Private Declare Function XLPyDLLActivate Lib "xlpython32-2.0.6.dll" (ByRef result As Variant, Optional ByVal config As String = "") As Long
- Private Declare Function XLPyDLLNDims Lib "xlpython32-2.0.6.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
-#EndIf
-
-Private Function XLPyFolder() As String
- XLPyFolder = ThisWorkbook.Path + "\xlpython"
-End Function
-
-Function XLPyConfig() As String
- XLPyConfig = XLPyFolder + "\xlpython.cfg"
-End Function
-
-Sub XLPyLoadDLL()
- LoadLibrary XLPyFolder + "\" + XLPyDLLName
-End Sub
-
-Function NDims(ByRef src As Variant, dims As Long, Optional transpose As Boolean = False)
- XLPyLoadDLL
- If 0 <> XLPyDLLNDims(src, dims, transpose, NDims) Then Err.Raise 1001, Description:=NDims
-End Function
-
-Function Py()
- XLPyLoadDLL
- If 0 <> XLPyDLLActivate(Py, XLPyConfig) Then Err.Raise 1000, Description:=Py
-End Function
\ No newline at end of file
diff --git a/addin/xlpython/xlpython.cfg b/addin/xlpython/xlpython.cfg
deleted file mode 100644
index 97f9ef7..0000000
--- a/addin/xlpython/xlpython.cfg
+++ /dev/null
@@ -1,38 +0,0 @@
-# Predefined macros
-#
-# $(ConfigDir)
-# The folder containing this configuration file
-#
-# $(WorkbookDir)
-# The parent folder of the folder containing this configuration file - where it is assumed the workbooks reside.
-#
-# $(RandomGUID)
-# A new random GUID - note that the macro will always resolve to the *same* GUID, not a new one each time
-#
-# $(Environment:XXX)
-# The environment variable XXX
-#
-# $(xxx)
-# Where xxx is the name of a previously defined variable - raises an error if it has not been set
-#
-# $(?xxx)
-# 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 = $(RandomGUID)
-
-# The command line used to launch the COM server
-Command = pythonw.exe -u "$(ConfigDir)\xlpyserver.py" $(CLSID)
-
-# Optionally redirect stdout and stderr
-RedirectOutput = $(ConfigDir)\$(ConfigName).log
-
-# The working directory the COM server will be launched in
-WorkingDir = $(WorkbookDir)
-
-# Optionally manipulate the environment variables.
-# Only variables listed in EnvironmentInclude will reach the process, if set.
-# Alternatively, all variables except those listed in EnvironmentExclude wll reach the process, if set.
-#EnvironmentInclude = PATH, PYTHONPATH, SYSTEMDRIVE, SYSTEMROOT
-#EnvironmentExclude = EXCLUDE, THESE, VARIABLES
-Environment:PYTHONPATH = $(WorkbookDir);$(?Environment:PYTHONPATH)
\ No newline at end of file
diff --git a/addin/xlpython/xlpython_v1back.bas b/addin/xlpython/xlpython_v1back.bas
deleted file mode 100644
index 8266ab6..0000000
--- a/addin/xlpython/xlpython_v1back.bas
+++ /dev/null
@@ -1,96 +0,0 @@
-Attribute VB_Name = "xlpython_v1back"
-Option Explicit
-
-Function PyDict(ParamArray elements())
- Dim els As Variant
- els = elements
- Set PyDict = Py.DictFromArray(els)
-End Function
-
-Function PyTuple(ParamArray elements())
- Dim els As Variant
- els = elements
- Set PyTuple = Py.TupleFromArray(els)
-End Function
-
-Function PyList(ParamArray elements())
- Dim els As Variant
- els = elements
- Set PyList = Py.ListFromArray(els)
-End Function
-
-Function PyBuiltin(method As String, Optional args = Empty, Optional kwargs = Empty)
- Set PyBuiltin = Py.Call(Py.BuiltIn, method, args, kwargs)
-End Function
-
-Function PyStr(obj) As String
- PyStr = Py.Str(obj)
-End Function
-
-Function PyRepr(obj) As String
- PyRepr = PyStr(PyBuiltin("repr", PyTuple(obj)))
-End Function
-
-Function PyVar(obj)
- PyVar = Py.Var(obj)
-End Function
-
-Function PyObj(value)
- Set PyObj = Py.obj(value)
-End Function
-
-Function PyLen(obj) As Long
- PyLen = PyVar(PyBuiltin("len", PyTuple(obj)))
-End Function
-
-Function PyType(obj As Variant)
- Set PyType = PyBuiltin("type", PyTuple(obj))
-End Function
-
-Function PyCall(instance, Optional method As String = "", Optional args = Empty, Optional kwargs = Empty, Optional console As Boolean = False)
- Set PyCall = Py.Call(instance, method, args, kwargs)
-End Function
-
-Function PyGetAttr(instance, attr As String)
- PyGetAttr = Py.GetAttr(instance, attr)
-End Function
-
-Sub PySetAttr(instance, attr As String, value)
- Py.SetAttr instance, attr, value
-End Sub
-
-Sub PyDelAttr(instance, attr As String)
- Py.DelAttr instance, attr
-End Sub
-
-Function PyHasAttr(instance, attr As String) As Boolean
- PyHasAttr = Py.HasAttr(instance, attr)
-End Function
-
-Function PyGetItem(instance, key)
- PyGetItem = Py.GetItem(instance, key)
-End Function
-
-Sub PySetItem(instance, key, value)
- Py.SetItem instance, key, value
-End Sub
-
-Sub PyDelItem(instance, key)
- Py.DelItem instance, key
-End Sub
-
-Function PyContains(instance, key) As Boolean
- PyContains = Py.Contains(instance, key)
-End Function
-
-Function PyEval(expression As String, Optional locals = Empty, Optional globals = Empty, Optional addpath As String = "", Optional path As String = "")
- Set PyEval = Py.Eval(expression, locals, globals)
-End Function
-
-Function PyExec(statement As String, Optional locals = Empty, Optional globals = Empty, Optional addpath As String = "", Optional path As String = "")
- Set PyExec = Py.Exec(statement, locals, globals)
-End Function
-
-Function PyModule(name As String, Optional reload As Boolean = True, Optional addpath As String = "", Optional path As String = "")
- Set PyModule = Py.Module(name)
-End Function
diff --git a/addin/xlpython_xlam_vba_code.bas b/addin/xlpython_xlam_vba_code.bas
deleted file mode 100644
index 76f9577..0000000
--- a/addin/xlpython_xlam_vba_code.bas
+++ /dev/null
@@ -1,297 +0,0 @@
-Attribute VB_Name = "ExcelPython"
-#If VBA7 Then
-
-Private Declare PtrSafe Function GetTempPath32 Lib "kernel32" _
- Alias "GetTempPathA" (ByVal nBufferLength As LongPtr, _
- ByVal lpBuffer As String) As Long
-
-Private Declare PtrSafe Function GetTempFileName32 Lib "kernel32" _
- Alias "GetTempFileNameA" (ByVal lpszPath As String, _
- ByVal lpPrefixString As String, ByVal wUnique As Long, _
- ByVal lpTempFileName As String) As Long
-
-#Else
-
-Private Declare Function GetTempPath32 Lib "kernel32" _
- Alias "GetTempPathA" (ByVal nBufferLength As Long, _
- ByVal lpBuffer As String) As Long
-
-Private Declare Function GetTempFileName32 Lib "kernel32" _
- Alias "GetTempFileNameA" (ByVal lpszPath As String, _
- ByVal lpPrefixString As String, ByVal wUnique As Long, _
- ByVal lpTempFileName As String) As Long
-
-#End If
-
-Private Function GetTempFileName()
- Dim sTmpPath As String * 512
- Dim sTmpName As String * 576
- Dim nRet As Long
- nRet = GetTempPath32(512, sTmpPath)
- If nRet = 0 Then Err.Raise 1234, Description:="GetTempPath failed."
- nRet = GetTempFileName32(sTmpPath, "vba", 0, sTmpName)
- If nRet = 0 Then Err.Raise 1234, Description:="GetTempFileName failed."
- GetTempFileName = Left$(sTmpName, InStr(sTmpName, vbNullChar) - 1)
-End Function
-
-Function ModuleIsPresent(ByVal wb As Workbook, moduleName As String) As Boolean
- On Error GoTo not_present
- Set x = wb.VBProject.VBComponents.Item(moduleName)
- ModuleIsPresent = True
- Exit Function
-not_present:
- ModuleIsPresent = False
-End Function
-
-
-Sub SetupExcelPython(control As IRibbonControl)
- Set wb = ActiveWorkbook
- If wb.Path = "" Then
- MsgBox "Please save this workbook first, as a macro-enabled workbook."
- Exit Sub
- End If
- If LCase$(Right$(wb.name, 5)) <> ".xlsm" And LCase$(Right$(wb.name, 5)) <> ".xlsb" Then
- MsgBox "Please save this workbook, " + wb.name + ", as a macro-enabled workbook first."
- Exit Sub
- End If
- mssg = "This action will:" _
- + vbCrLf + " - install the ExcelPython runtime in the folder '" + wb.Path + Application.PathSeparator + "xlpython'" _
- + vbCrLf + " - set up this workbook ('" + wb.name + "') to interact with Python" _
- + vbCrLf + vbCrLf + "Do you want to proceed?"
- If vbYes = MsgBox(mssg, vbYesNo, "Set up workbook for ExcelPython") Then
- Set fso = CreateObject("Scripting.FileSystemObject")
- If fso.FolderExists(wb.Path + Application.PathSeparator + "xlpython") Then
- isVersionOK = False
- ver = "?.?.?"
- For Each f In fso.GetFolder(ThisWorkbook.Path + Application.PathSeparator + "xlpython").Files
- If LCase$(Right$(f, 4)) = ".dll" Then
- isVersionOK = fso.FileExists(wb.Path + Application.PathSeparator + "xlpython" + Application.PathSeparator + fso.GetFileName(f))
- ver = Mid$(fso.GetBaseName(f), InStr(fso.GetBaseName(f), "-") + 1)
- Exit For
- End If
- Next f
- If Not isVersionOK Then
- MsgBox "The installation folder already exists, but it does not contain ExcelPython version " + ver + "." _
- + vbCrLf + vbCrLf + "Installation folder: " + wb.Path + Application.PathSeparator + "xlpython" _
- + vbCrLf + vbCrLf + "To set up a fresh install please delete it and try again. Note that you may need to close Excel to delete it." _
- , vbCritical, "Error installing ExcelPython runtime"
- Exit Sub
- End If
- Else
- fso.CopyFolder ThisWorkbook.Path + Application.PathSeparator + "xlpython", wb.Path + Application.PathSeparator + "xlpython"
- End If
-
- On Error GoTo not_present
- wb.VBProject.VBComponents.Remove wb.VBProject.VBComponents("xlpython")
-not_present:
- On Error GoTo 0
- wb.VBProject.VBComponents.Import wb.Path + Application.PathSeparator + "xlpython" + Application.PathSeparator + "xlpython.bas"
-
- ' create skeleton py file
- Set fso = CreateObject("Scripting.FileSystemObject")
- If Not fso.FileExists(wb.Path + Application.PathSeparator + fso.GetBaseName(wb.name) + ".py") Then
- Set f = fso.CreateTextFile(wb.Path + Application.PathSeparator + fso.GetBaseName(wb.name) + ".py", True)
- f.WriteLine "from xlpython import *"
- f.Close
- End If
- 'MsgBox "You can now write user-defined functions for this workbook in Python in the file '" + wb.Path + Application.PathSeparator + fso.GetBaseName(wb.Name) + ".py'." + vbCrLf + "Please consult the online docs for more information on how it works.", Title:="ExcelPython setup successful!"
- End If
-End Sub
-
-Sub XLPMacroOptions2010(macroName As String, desc, argdescs() As String)
- Application.MacroOptions macroName, Description:=desc, ArgumentDescriptions:=argdescs
-End Sub
-
-Sub ImportPythonUDFs(control As IRibbonControl)
- sTab = " "
-
- Set wb = ActiveWorkbook
- If Not ModuleIsPresent(wb, "xlpython") Then
- MsgBox "The active workbook does not seem to have been set up to use ExcelPython yet."
- Exit Sub
- End If
-
- Set Py = Application.Run("'" + wb.name + "'!Py")
-
- Set fso = CreateObject("Scripting.FileSystemObject")
- filename = GetTempFileName()
- Set f = fso.CreateTextFile(filename, True)
- f.WriteLine "Attribute VB_Name = ""xlpython_udfs"""
- f.WriteLine
- f.WriteLine "Function PyScriptPath() As String"
- f.WriteLine sTab + "PyScriptPath = Left$(ThisWorkbook.Name, Len(ThisWorkbook.Name)-5) ' assume that it ends in .xlsm"
- ' f.WriteLine sTab + "If LCase$(Right$(PyScriptPath, 5)) = "".xlsm"" Then PyScriptPath = Left$(PyScriptPath, Len(PyScriptPath)-5)"
- f.WriteLine sTab + "PyScriptPath = ThisWorkbook.Path + Application.PathSeparator + PyScriptPath + "".py"""
- f.WriteLine "End Function"
- f.WriteLine
-
- Dim scriptPath As String
- scriptPath = wb.Path + Application.PathSeparator + fso.GetBaseName(wb.name) + ".py"
- Set scriptVars = Py.Call(Py.Module("xlpython"), "udf_script", Py.Tuple(scriptPath))
- For Each svar In Py.Call(scriptVars, "values")
- If Py.HasAttr(svar, "__xlfunc__") Then
- Set xlfunc = Py.GetAttr(svar, "__xlfunc__")
- Set xlret = Py.GetItem(xlfunc, "ret")
- fname = Py.Str(Py.GetItem(xlfunc, "name"))
-
- Dim ftype As String
- If Py.Var(Py.GetItem(xlfunc, "sub")) Then ftype = "Sub" Else ftype = "Function"
-
- f.Write ftype + " " + fname + "("
- first = True
- vararg = ""
- nArgs = Py.Len(Py.GetItem(xlfunc, "args"))
- For Each arg In Py.GetItem(xlfunc, "args")
- If Not Py.Bool(Py.GetItem(arg, "vba")) Then
- argname = Py.Str(Py.GetItem(arg, "name"))
- If Not first Then f.Write ", "
- If Py.Bool(Py.GetItem(arg, "vararg")) Then
- f.Write "ParamArray "
- vararg = argname
- End If
- f.Write argname
- If Py.Bool(Py.GetItem(arg, "vararg")) Then
- f.Write "()"
- End If
- first = False
- End If
- Next arg
- f.WriteLine ")"
- If ftype = "Function" Then
- f.WriteLine sTab + "If TypeOf Application.Caller Is Range Then On Error GoTo failed"
- End If
-
- If vararg <> "" Then
- f.WriteLine sTab + "ReDim argsArray(1 to UBound(" + vararg + ") - LBound(" + vararg + ") + " + CStr(nArgs) + ")"
- End If
- j = 1
- For Each arg In Py.GetItem(xlfunc, "args")
- If Not Py.Bool(Py.GetItem(arg, "vba")) Then
- argname = Py.Str(Py.GetItem(arg, "name"))
- If Py.Bool(Py.GetItem(arg, "vararg")) Then
- f.WriteLine sTab + "For k = lbound(" + vararg + ") to ubound(" + vararg + ")"
- argname = vararg + "(k)"
- End If
- If Not Py.Var(Py.GetItem(arg, "range")) Then
- f.WriteLine sTab + "If TypeOf " + argname + " Is Range Then " + argname + " = " + argname + ".Value2"
- End If
- dims = Py.Var(Py.GetItem(arg, "dims"))
- marshal = Py.Str(Py.GetItem(arg, "marshal"))
- If dims <> -1 Or marshal = "nparray" Or marshal = "list" Then
- f.WriteLine sTab + "If Not TypeOf " + argname + " Is Object Then"
- If dims <> -1 Then
- f.WriteLine sTab + sTab + argname + " = NDims(" + argname + ", " + CStr(dims) + ")"
- End If
- If marshal = "nparray" Then
- dtype = Py.Var(Py.GetItem(arg, "dtype"))
- If IsNull(dtype) Then
- f.WriteLine sTab + sTab + "Set " + argname + " = Py.Call(Py.Module(""numpy""), ""array"", Py.Tuple(" + argname + "))"
- Else
- f.WriteLine sTab + sTab + "Set " + argname + " = Py.Call(Py.Module(""numpy""), ""array"", Py.Tuple(" + argname + ", """ + dtype + """))"
- End If
- ElseIf marshal = "list" Then
- f.WriteLine sTab + sTab + "Set " + argname + " = Py.Call(Py.Eval(""lambda t: [ list(x) if isinstance(x, tuple) else x for x in t ] if isinstance(t, tuple) else t""), Py.Tuple(" + argname + "))"
- End If
- f.WriteLine sTab + "End If"
- End If
- If Py.Bool(Py.GetItem(arg, "vararg")) Then
- f.WriteLine sTab + "argsArray(" + CStr(j) + " + k - LBound(" + vararg + ")) = " + argname
- f.WriteLine sTab + "Next k"
- Else
- If vararg <> "" Then
- f.WriteLine sTab + "argsArray(" + CStr(j) + ") = " + argname
- j = j + 1
- End If
- End If
- End If
- Next arg
-
- If vararg <> "" Then
- f.WriteLine sTab + "Set args = Py.TupleFromArray(argsArray)"
- Else
- f.Write sTab + "Set args = Py.Tuple("
- first = True
- For Each arg In Py.GetItem(xlfunc, "args")
- If Not first Then f.Write ", "
- If Not Py.Bool(Py.GetItem(arg, "vba")) Then
- f.Write Py.Str(Py.GetItem(arg, "name"))
- Else
- f.Write Py.Str(Py.GetItem(arg, "vba"))
- End If
- first = False
- Next arg
- f.WriteLine ")"
- End If
-
- If Py.Bool(Py.GetItem(xlfunc, "xlwings")) Then
- f.WriteLine sTab + "Py.SetAttr Py.GetAttr(Py.Module(""xlwings""), ""xlplatform""), ""xl_app_latest"", Application"
- f.WriteLine sTab + "Py.SetAttr Py.Module(""xlwings.main""), ""xl_workbook_latest"", ThisWorkbook"
- End If
-
- f.WriteLine sTab + "Set xlpy = Py.Module(""xlpython"")"
- f.WriteLine sTab + "Set script = Py.Call(xlpy, ""udf_script"", Py.Tuple(PyScriptPath))"
- f.WriteLine sTab + "Set func = Py.GetItem(script, """ + fname + """)"
- If ftype = "Sub" Then
- f.WriteLine sTab + "Py.Call func, args"
- Else
- f.WriteLine sTab + "Set " + fname + " = Py.Call(func, args)"
- marshal = Py.Str(Py.GetItem(xlret, "marshal"))
- Select Case marshal
- Case "auto"
- f.WriteLine sTab + "If TypeOf Application.Caller Is Range Then " + fname + " = Py.Var(" + fname + ", " + Py.Str(Py.GetItem(xlret, "lax")) + ")"
- Case "var"
- f.WriteLine sTab + fname + " = Py.Var(" + fname + ", " + Py.Str(Py.GetItem(xlret, "lax")) + ")"
- Case "str"
- f.WriteLine sTab + fname + " = Py.Str(" + fname + ")"
- End Select
- End If
-
- If ftype = "Function" Then
- f.WriteLine sTab + "Exit " + ftype
- f.WriteLine "failed:"
- f.WriteLine sTab + fname + " = Err.Description"
- End If
- f.WriteLine "End " + ftype
- f.WriteLine
- End If
- Next svar
- f.Close
-
- On Error GoTo not_present
- wb.VBProject.VBComponents.Remove wb.VBProject.VBComponents("xlpython_udfs")
-not_present:
- On Error GoTo 0
- wb.VBProject.VBComponents.Import filename
-
- For Each svar In Py.Call(scriptVars, "values")
- If Py.HasAttr(svar, "__xlfunc__") Then
- Set xlfunc = Py.GetAttr(svar, "__xlfunc__")
- Set xlret = Py.GetItem(xlfunc, "ret")
- Set xlargs = Py.GetItem(xlfunc, "args")
- fname = Py.Str(Py.GetItem(xlfunc, "name"))
- fdoc = Py.Str(Py.GetItem(xlret, "doc"))
- nArgs = 0
- For Each arg In xlargs
- If Not Py.Bool(Py.GetItem(arg, "vba")) Then nArgs = nArgs + 1
- Next arg
- If nArgs > 0 And Val(Application.Version) >= 14 Then
- ReDim argdocs(1 To WorksheetFunction.Max(1, nArgs)) As String
- nArgs = 0
- For Each arg In xlargs
- If Not Py.Bool(Py.GetItem(arg, "vba")) Then
- nArgs = nArgs + 1
- argdocs(nArgs) = Left$(Py.Str(Py.GetItem(arg, "doc")), 255)
- End If
- Next arg
- XLPMacroOptions2010 "'" + wb.name + "'!" + fname, Left$(fdoc, 255), argdocs
- Else
- Application.MacroOptions "'" + wb.name + "'!" + fname, Description:=Left$(fdoc, 255)
- End If
- End If
- Next svar
-
- 'MsgBox "Import successful!"
-End Sub
-
-
-
diff --git a/contribute/index.md b/contribute/index.md
new file mode 100644
index 0000000..77554c4
--- /dev/null
+++ b/contribute/index.md
@@ -0,0 +1,14 @@
+---
+layout: page
+title: "Contribute"
+---
+
+## Contribute!
+
+### Code and Documentation
+
+ExcelPython is open-source and is hosted on [GitHub][]. It is written in a mix of C++, Python and Visual Basic.
+
+Please fork it, add some great new features and submit a pull request!
+
+[GitHub]: https://github.com/ericremoreynolds/excelpython
diff --git a/docs/Readme.md b/docs/Readme.md
deleted file mode 100644
index 22bbb15..0000000
--- a/docs/Readme.md
+++ /dev/null
@@ -1,25 +0,0 @@
-**Getting started with the ExcelPython add-in**
-
-1. [Loading the add-in and writing your first user-defined function](tutorials/Addin01.md)
-1. [Dealing with array arguments](tutorials/Addin02.md)
-1. [Something a bit more interesting - NumPy arrays](tutorials/Addin03.md)
-1. [Writing macros in Python](tutorials/Addin04.md)
-1. [Permanently installing the add-in](tutorials/Addin05.md)
-
-If you encounter any issues in getting the add-in set up consult the [troubleshooting guide](tutorials/AddinTrouble.md).
-
-**Learn how to manipulate Python objects in VBA**
-
-1. [A very simple usage example](tutorials/Usage01.md)
-2. [A more practical use of ExcelPython](tutorials/Usage02.md)
-3. [Putting it all together](tutorials/Usage03.md)
-4. [Ranges, lists and SAFEARRAYs](tutorials/Usage04.md)
-
-**Delve deeper into how to target a particular Python installation and working environment**
-
-* [Configuration](tutorials/Configuration01.md)
-
-**Learn how to analyse the problem when something goes wrong**
-
-* [Debugging](tutorials/Debugging01.md)
-* [Troubleshooting](tutorials/Troubleshooting01.md)
diff --git a/docs/tutorials/Addin01.md b/docs/tutorials/Addin01.md
deleted file mode 100644
index 10b1555..0000000
--- a/docs/tutorials/Addin01.md
+++ /dev/null
@@ -1,49 +0,0 @@
-## Loading the ExcelPython add-in
-
-* Download the latest [release](https://github.com/ericremoreynolds/excelpython/releases) and unzip it somewhere.
-
-* Open the add-in `xlpython.xlam` in Excel.
-
-* If all goes well you should see the ExcelPython tab in Excel's toolbar.
-
- 
-
-* You may get an error saying `Programmatic access to Visual Basic Project is not trusted`. If so check out the [add-in troubleshooting guide](./AddinTrouble.md).
-
-Note that it is possible to [permanently install the add-in](./Addin05.md) so you don't need to open it manually each time.
-
-## Writing a user-defined function in Python
-
-To interact with Python, a workbook must first be setup to use ExcelPython. To do this it is first necessary to save it as a macro-enabled workbook.
-
-* Choose an empty folder and in it save an empty workbook as `Book1.xlsm`.
-
-* From the ExcelPython tab in the toolbar click 'Setup ExcelPython'.
-
-Next write your user-defined function in Python. In the previous step ExcelPython will have created a file called `Book1.py` in the same folder as `Book1.xlsm` in which the Python functions to be used in the workbook must be defined.
-
-* Edit `Book1.py` to contain the following code:
-
- ```python
- # Book1.py
- from xlpython import *
-
- @xlfunc
- def DoubleSum(x, y):
- '''Returns twice the sum of the two arguments'''
- return 2 * (x + y)
- ```
-
-* Switch back to Excel and click 'Import Python UDFs' in the ExcelPython tab to pick up the changes made to `Book1.py`.
-
-* Enter the formula `=DoubleSum(1, 2)` into a cell and you should get the correct result:
-
- 
-
-* Note that the `DoubleSum` function is usable from VBA as well. Open the VBA window (`Alt+F11`), switch to the Immediate Window (`Ctrl+G`) and type
-
- ```
- ?DoubleSum(1, 2)
- ```
-
-To continue move onto the [next tutorial](./Addin02.md).
diff --git a/docs/tutorials/Addin02.md b/docs/tutorials/Addin02.md
deleted file mode 100644
index 1124620..0000000
--- a/docs/tutorials/Addin02.md
+++ /dev/null
@@ -1,69 +0,0 @@
-## Array arguments
-
-You can pass a range as a function argument, as opposed to a single cell. Its value will be converted to a tuple of tuples.
-
-* Add the following code to `Book1.py` from the [previous tutorial](./Addin01.md)
-
- ```python
- @xlfunc
- def MyUDF(x):
- return repr(x)
- ```
-
- This function simply returns its argument converted to string representation. This will allow us to explore how formula arguments are converted into Python objects.
-
-* Click 'Import Python UDFs' to pick up the changes
-
-* Modify the workbook as below
-
- 
-
-As you can see the value of the 2x2 range `F1:G2` has been convert to a tuple containing tuples representing the range's two rows.
-
-At this point it is worth talking about one of Excel's oddities, namely that the value of a 1x1 range is always a scalar, whereas the value of any range larger than 1x1 is represented by a two-dimensional array.
-
-
-
-
-
-ExcelPython provides a mechanism for normalizing the input arguments so that your function can safely make assumptions about their dimensionality.
-
-* Modify `Book1.py` as follows
-
- ```python
- @xlfunc
- @xlarg("x", dims=2) # add this line
- def MyUDF(x):
- return str(x)
- ```
-
-* Click 'Import Python UDFs' to pick up the changes.
-
-* Now 1x1 ranges are passed as two-dimensional
-
- 
-
-At other times it you may want to assume that an argument that is one-dimensional
-
-* Modify `Book1.py` as follows
-
- ```python
- @xlfunc
- @xlarg("x", dims=1) # modify this line
- def MyUDF(x):
- return str(x)
- ```
-
-* Click 'Import Python UDFs' to pick up the changes.
-
- 
-
- 
-
- 
-
-* Clearly having specified the argument as one-dimensional, an error is raised if a two-dimensional range is passed
-
- 
-
-To continue move onto the [next tutorial](./Addin03.md).
diff --git a/docs/tutorials/Addin03.md b/docs/tutorials/Addin03.md
deleted file mode 100644
index 7205bdf..0000000
--- a/docs/tutorials/Addin03.md
+++ /dev/null
@@ -1,29 +0,0 @@
-## Something a bit more interesting - NumPy arrays
-
-One of the attractions of using Python from Excel is to gain access to the vast range of publicly available Python libraries for numerical computing. Since [NumPy](http://www.numpy.org/) is the cornerstone of many of these libraries, the ExcelPython add-in makes it easy to pass function arguments as and convert return values from [numpy arrays](http://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html).
-
-We will now define a simple function for doing matrix multiplication using NumPy.
-
-* Add the following code to `Book1.py` from the [first tutorial](./Addin01.md)
-
- ```python
- @xlfunc
- @xlarg("x", "nparray", dims=2)
- @xlarg("y", "nparray", dims=2)
- def MatrixMult(x, y):
- return x.dot(y)
- ```
-
-* Click 'Import Python UDFs' to pick up the changes
-
-* The function `MatrixMult` can now be used as an array function from Excel
-
- 
-
- To enter the above array formula in Excel
- * fill in the values in the ranges `D1:E2` and `G1:H2`
- * select cells `A1:B2`
- * type in the formula `=MatrixMult(D1:E2, G1:H2)`
- * press `Ctrl+Shift+Enter`.
-
-To continue move onto the [next tutorial](./Addin04.md).
diff --git a/docs/tutorials/Addin04.md b/docs/tutorials/Addin04.md
deleted file mode 100644
index eb5313c..0000000
--- a/docs/tutorials/Addin04.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# Writing macros in Python
-
-In addition to writing user-defined functions, VBA is typically used for defining macros to automate Excel.
-
-* Add the following code to `Book1.py` from the previous tutorial.
-
- ```python
- @xlsub
- @xlarg("app", vba="Application")
- def my_macro(app):
- from datetime import datetime
- app.StatusBar = str(datetime.now())
- ```
-
-* Click 'Import Python UDFs' to pick up the changes.
-
-* From the Developer tab, select Insert > Form Controls > Button and create the button on Sheet2. You should be prompted to select the macro you want to run when the button is clicked, and should be able to select `my_macro`.
-
- Note that the Developer tab is usually not visible by default. You can enable it from the Excel Options panel.
-
-* If all has gone according to plan, clicking the button will update Excel's status bar (at the bottom of the window) with the current date and time:
-
- 
-
-To understand the above code, let's go through it line by line.
-
-* `@xlsub` indicates that `my_macro` should be wrapped as a VBA subroutine rather than as a VBA function
-* `@xlarg("app", vba="Application")` indicates that the `app` argument should be hard-coded to the VBA expression specified, in this case the `Application` object. Using the `vba` keyword results in the argument being removed from the argument list in Excel. As such our macro does not have any arguments in Excel - indeed, buttons can only be associated with macros with zero parameters.
-* `app.StatusBar = str(datetime.now())`. Once inside the function, the `app` variable has been set to the Excel `Application` object, and in this line we set the status bar message to the current date and time.
-
-Another example of how to use this functionality is to manipulate a worksheet. The following macro copies the contents of cell A1 into cell A2 in Sheet2.
-
-```python
-@xlsub
-@xlarg("sheet", vba="Sheet2")
-def my_other_macro(sheet):
- sheet.Range("A2").Value = sheet.Range("A1").Value
-```
-
-To continue move onto the [next tutorial](./Addin05.md).
diff --git a/docs/tutorials/Addin05.md b/docs/tutorials/Addin05.md
deleted file mode 100644
index bee6714..0000000
--- a/docs/tutorials/Addin05.md
+++ /dev/null
@@ -1,29 +0,0 @@
-## Permanently installing the ExcelPython add-in
-
-The best place to put the ExcelPython add-in is in the Excel startup folder. All files placed in this folder are automatically opened by Excel on startup, so if you place ExcelPython there you do not need to manually open it each time you want to use it. The `xlpython.xlam` file must be placed in the `XLSTART` folder and the `xlpython` folder must be copied alongside it like so:
-
-
-
-Unfortunately the folder's location varies depending on the version of Excel. Some candidates are
-
- Excel 2013 current user: %APPDATA%\Roaming\Microsoft\Excel\XLSTART
- Excel 2010 current user: %APPDATA%\Microsoft\Excel\XLSTART
- Excel 2007 current user: %APPDATA%\Microsoft\Excel\XLSTART
- Excel 2003 current user: %APPDATA%\Microsoft\Excel\XLSTART
-
- Excel 2013 all users: %PROGRAMFILES%\Microsoft Office 15\root\Office15\XLSTART
- Excel 2010 all users: %PROGRAMFILES%\Microsoft Office\Office14\XLSTART
- Excel 2007 all users: %PROGRAMFILES%\Microsoft Office\Office12\XLSTART
- Excel 2003 all users: %PROGRAMFILES%\Microsoft Office\Office11\XLSTART
-
-Note also that `%PROGRAMFILES%` may need to be substituted with `%PROGRAMFILES(x86)%` for 32-bit Excel installed on a 64-bit machine.
-
-If you are in doubt as to where the folder is located, you can also determine it by opening Excel, opening the VBA window (`Alt+F11`), switching to the Immediate Window (`Ctrl+G`) and typing
-
- ?Application.StartupPath
-
-for the current user and
-
- ?Application.Path + "\XLSTART"
-
-for all users.
diff --git a/docs/tutorials/AddinTrouble.md b/docs/tutorials/AddinTrouble.md
deleted file mode 100644
index c8fe863..0000000
--- a/docs/tutorials/AddinTrouble.md
+++ /dev/null
@@ -1,23 +0,0 @@
-## Programmatic access to Visual Basic Project is not trusted
-
-
-
-This appears because your Excel trust settings do not allow an add-in to manipulate another workbook's VBA code, which the ExcelPython add-in needs to be able to do to perform its tasks.
-
-To change this trust setting, select File > Options > Trust Center > Trust Center Settings > Macro Settings and ensure the checkbox labeled 'Trust access to the VBA project object model' is checked.
-
-
-
-## Could not create Python process - the system cannot find the file specified
-
-
-
-This is probably because you don't have Python installed on your machine. If you are sure you do, then it may not be on the system path, or if you have just installed it maybe Excel just needs to be restarted.
-
-## Python process exited before it was possible to create the interface object
-
-
-
-This means that there was an error in running the ExcelPython server script (`xlpyserver.py`) and it can happen for many reasons.
-
-The most likely cause is that you haven't installed the [Python for Windows extensions (PyWin32)](http://sourceforge.net/projects/pywin32/) library into your Python distribution. Failing this you should consult the specified log file, which will show you the output of the Python interpreter including any errors that might have been raised during the script's execution.
diff --git a/docs/tutorials/Configuration01.md b/docs/tutorials/Configuration01.md
deleted file mode 100644
index 9b8c61f..0000000
--- a/docs/tutorials/Configuration01.md
+++ /dev/null
@@ -1,15 +0,0 @@
-**NB: work in progress**
-
-# Configuring ExcelPython
-
-On of the most important features of ExcelPython is the ability to specify exactly which Python installation you wish to use, and to define an isolated Python execution environment with which your workbook interacts.
-
-In many cases there is no need to make any changes to the default configuration, which runs the PC's default Python installation, i.e. the one that appears by entering `python.exe` in the Start > Run box. In other cases however, you may be interested in targeting a specific copy of Python installed on your PC, or executing Python with specific environment variables.
-
-Let's assume we're developing an Excel workbook called `MatrixAlgebra.xlsm` in the folder `%SOMEFOLDER%\MatrixAlgebra`, and that the Python code is in a file called `MatrixAlgebra.py` in the same folder. Let's suppose we want to distribute this workbook in a zip file, and we want to include a copy of a portable Python distribution in the folder `%SOMEFOLDER%\MatrixAlgebra\PortablePython` which we want to use to execute our Python code within the context of the workbook. The ExcelPython runtime has already been copied to `%SOMEFOLDER%\MatrixAlgebra\xlpython`.
-
-Inside this last folder there is a file called `xlpython.cfg` which determines how the Python process is launched when some functionality within the workbook (e.g. a VBA function or a worksheet formula) tries to interact with Python.
-
-To specify that the Python distribution in `%SOMEFOLDER%\MatrixAlgebra\PortablePython` must be used, make the following modification to `xlpython.cfg`
-
- Command = $(WorkbookDir)\PortablePython\pythonw.exe -u "$(ConfigDir)\xlpyserver.py" $(CLSID)
diff --git a/docs/tutorials/Debugging01.md b/docs/tutorials/Debugging01.md
deleted file mode 100644
index 0b61019..0000000
--- a/docs/tutorials/Debugging01.md
+++ /dev/null
@@ -1,65 +0,0 @@
-## Debugging code with ExcelPython
-
-ExcelPython does not have any special provision for debugging Python code because it is fully compatible with existing Python debugging tools. Here we will see how to set up a couple of the most widely-used ones, [Python Tools for Visual Studio](#debugging-with-python-tools-for-visual-studio) and [PyDev](#debugging-with-eclipse-and-pydev).
-
-## Debugging with Python Tools for Visual Studio
-
-On Windows it is possible to debug Python scripts in Microsoft Visual Studio using an add-in called [Python Tools for Visual Studio](http://pytools.codeplex.com/) (PTVS). To get set up (full instructions can be found on the PTVS website) you need to
-
-1. Install a recent version of Visual Studio, either Express or a commercial license.
-2. Download and install the relevant distribution of the PTVS add-in
-3. Install the PTVS debug package into your Python distribution
-4. Prepare your Python script to enable debugging in Visual Studio.
-
-Assuming you've done steps 1 and 2, step 3 can be achieved using [PIP](https://pypi.python.org/pypi/pip).
-
-```
-C:\>pip install ptvsd
-Downloading/unpacking ptvsd
- Running setup.py (path:c:\docume~1\user\locals~1\temp\pip_build_user\ptvsd\setup.py) egg_info for package ptvsd
-
-Installing collected packages: ptvsd
- Running setup.py install for ptvsd
-
-Successfully installed ptvsd
-Cleaning up...
-```
-
-Now you should be able to `import ptvsd` in your Python interpreter.
-
-Let's see how to prepare a [basic script](./Addin01.md) for debugging with PTVS
-
-```python
-# Book1.py
-from xlpython import *
-
-# Add these two lines
-import ptvsd
-ptvsd.enable_attach(secret='cows')
-
-@xlfunc
-def DoubleSum(x, y):
- return 2 * (x + y)
-```
-
-These to lines enable us to attach the Visual Studio debugger to the Python script, so that we can debug it. Note that the Python process itself must be running for this to work, and ExcelPython does not launch it until it is needed - so just to make sure that it is running and that the `Book1.py` script is loaded, click 'Import Python UDFs'.
-
-At this point you may need to unblock a port on the Windows firewall:
-
-
-
-Having done this you should now be in a position to attach the Visual Studio debugger to the Python script. To do this:
-* open the Debug > Attach to Process dialog
-* select 'Python remote debugging' as the transport
-* specify the relevant qualifier in the 'Qualifier' box, for example `cows@localhost`
-* click refresh and select the Python process
-
-
-
-Now you can set breakpoints in the code and the next time your function is invoked from Excel, the execution will be interrupted when the breakpoint is hit.
-
-
-
-## Debugging with Eclipse and PyDev
-
-Coming soon!
diff --git a/docs/tutorials/Usage01.md b/docs/tutorials/Usage01.md
deleted file mode 100644
index 8728ef1..0000000
--- a/docs/tutorials/Usage01.md
+++ /dev/null
@@ -1,32 +0,0 @@
-A very simple usage example
----
-
-You can try out xlpython from the VBA Immediate Window (Ctrl + G if it's not already visible in the VBA window).
-
-Type the following
-
- ?Py.Str(Py.Eval("1+2"))
-
-and press return. You should see
-
- ?Py.Str(Py.Eval("1+2"))
- 3
-
-You can try evaluating any Python expression, and you'll get the result
-printed in the Immediate Window.
-
- ?Py.Str(Py.Eval("[1,2,3]+[4,5,6]"))
- [1, 2, 3, 4, 5, 6]
-
-Why is the PyStr function needed? If you try just calling
-
- ?Py.Eval("1+2")
-
-you'll get a type mismatch error. This is because the `Py.Eval` function returns a handle to the Python object itself, and VBA doesn't know how to print it to the Immediate Window. `Py.Str` takes a Python object and calls the Python str function on it and returns a VBA string, which can be printed)
-
-The `Py.Eval` function takes as an optional second argument a locals dictionary to be used when evaluating the expression. To build the dictionary, you can use the function `Py.Dict` which takes alternating keys and values as arguments.
-
- ?Py.Str(Py.Eval("x+y", Py.Dict("x", 3, "y", 4)))
- 7
- ?Py.Str(Py.Eval("x+y", Py.Dict("x", "abc", "y", "def")))
- abcdef
diff --git a/docs/tutorials/Usage02.md b/docs/tutorials/Usage02.md
deleted file mode 100644
index d6b15ae..0000000
--- a/docs/tutorials/Usage02.md
+++ /dev/null
@@ -1,28 +0,0 @@
-A more practical use of xlpython
----
-
-The above example gives a light introduction to manipulating a few simple objects through VBA. In practice though, what's needed is a way to get a load of inputs from Excel, pass them to a method defined in a Python script somewhere, get the outputs back from Python and use them VBA or place them in the spreadsheet as required.
-
-The key to doing this are the methods `Py.Module` and `Py.Call`.
-
-PyModule returns a pointer to a Python module, much like the import statement. If no additional arguments are specified, the embedded Python interpreter will look for the requested module in the default search path.
-
- ?Py.Str(Py.Module("datetime"))
-
-
-If you want to call functions from a script which you have placed in a non-standard location, you can tell xlpython to add additional search directories before trying to load the module, as follows:
-
- ?Py.Str(Py.Module("MyScript", Py.AddPath("D:\Scripts")))
-
-
-Once you have access to the module you want, you can use `Py.Call` to invoke functions contained in the module (note that `Py.Call` actually calls any method of any object, not just module objects). This is done by explicitly passing the ordered and keyword arguments. For example calling
-
- ?Py.Str(Py.Call(Py.Module("datetime"), "date", Py.Tuple(2013, 8, 9)))
- 2013-08-09
-
-is equivalent to calling `datetime.date(2013, 8, 9)`, whereas
-
- ?Py.Str(Py.Call(Py.Module("datetime"), "timedelta", Py.Tuple(3), Py.Dict("milliseconds", 500)))
- 3 days, 0:00:00.500000
-
-is like calling `datetime.timedelta(3, milliseconds=500)`.
diff --git a/docs/tutorials/Usage03.md b/docs/tutorials/Usage03.md
deleted file mode 100644
index f9651ba..0000000
--- a/docs/tutorials/Usage03.md
+++ /dev/null
@@ -1,34 +0,0 @@
-Putting it all together
----
-
-Let's suppose we have the following script MyScript.py saved in the same folder as the workbook.
-
-```python
-def MyFunction(x, y):
- return {
- "sum": x + y,
- "sorted": sorted([x, y])
- }
-```
-
-The following VBA code can be used to call this function, taking the input parameters from a worksheet and pasting the outputs back to that sheet.
-
- Function PyPath()
- PyPath = ThisWorkbook.Path
- End Function
-
- Sub CallPythonCode()
- Set res = Py.Call( _
- Py.Module("MyScript", Py.AddPath(PyPath)), "MyFunction", _
- Py.Dict( _
- "x", Sheet1.Range("A1").Value2, _
- "y", Sheet1.Range("A2").Value2))
- Sheet1.Range("A3").Value2 = Py.Var(Py.GetItem(res, "sum"))
- Sheet1.Range("A4:B4").Value2 = Py.Var(Py.GetItem(res, "sorted"))
- End Sub
-
-The function `PyPath` is a utility function which returns our additional module search path. It's set up so that to access Python scripts we just need to place them in the same folder as the workbook. It's worth defining this once in your workbook's VBA project for use wherever necessary.
-
-The calls to `Py.Module` and `Py.Call` have been explained above. Once the result dictionary is obtained from the function, its elements can be accessed using `Py.GetItem`.
-
-Finally, we use `Py.Var` to convert the Python objects into variants so that they can be pasted into worksheet ranges.
diff --git a/docs/tutorials/Usage04.md b/docs/tutorials/Usage04.md
deleted file mode 100644
index 15b153e..0000000
--- a/docs/tutorials/Usage04.md
+++ /dev/null
@@ -1,144 +0,0 @@
-Ranges, lists and SAFEARRAYs
----
-
-If you pass a VBA object to an ExcelPython function that expects a Python object, it will get converted automatically.
-
-That's why you can do the following
-
-```
-?Py.Str(Range("A1:C1").Value2)
-((3.0, 1.0, 2.0),)
-```
-
-The function `Py.Str` applies the Python `str` function to whatever object you pass it. If that object is not already a Python object, ExcelPython will convert it for you.
-
-In this specific example, the object that gets passed is a VBA array:
-
-```
-?TypeName(Range("A1:C1").Value2)
-Variant()
-```
-
-Specifically, it's a 1x3 two-dimensional array:
-
-```
-?UBound(Range("A1:C1").Value2,1) & " to " & LBound(Range("A1:C1").Value2, 1)
-1 to 1
-?UBound(Range("A1:C1").Value2,2) & " to " & LBound(Range("A1:C1").Value2, 2)
-3 to 1
-```
-
-This is an 'oddity' of Excel's VBA model - the values of 1x1 ranges are scalars:
-
-```
-?TypeName(Range("A1").Value2)
-Double
-```
-
-and all other size ranges have two-dimensional array values.
-
-Since two-dimensional tuples do not exist in Python, it gets converted to a tuple-of-tuples. Often however, you will want to pass a range as a one-dimensional tuple. Consider for example the built-in Python function `sorted`. If you call this function on the range "A1:C1" it returns the same value as is passed in:
-
-```
-?Py.Str(Py.Call(Py.Builtins, "sorted", Py.Tuple(Range("A1:C1").Value2)))
-[(3.0, 1.0, 2.0)]
-```
-
-This is because `sorted` only sorts the top-level sequence, which contains only one element, the tuple `(3.0, 1.0, 2.0)`.
-
-The VBA code is equivalent to the following Python code:
-
-```python
-sorted(((3.0, 1.0, 2.0),))
-```
-
-but we want the equivalent to:
-
-```python
-sorted((3.0, 1.0, 2.0))
-```
-
-To do this, you can convert the 1x3 two-dimensional VBA array to 3-element one-dimensional array before passing it to the python function Python:
-
-```
-?Py.Str(NDims(Range("A1:C1").Value2, 1))
-(3.0, 1.0, 2.0)
-?Py.Str(Py.Call(Py.Builtins, "sorted", Py.Tuple(NDims(Range("A1:C1").Value2, 1))))
-[1.0, 2.0, 3.0]
-```
-
-NumPy arrays
---
-
-Conversion to/from NumPy types is a frequent necessity, and ExcelPython does not do this automatically.
-
-For example, the function `scipy.stats.norm.cdf` returns a `numpy.float64` object:
-
-```
-Set vars = Py.Dict()
-Py.Exec "from scipy.stats import norm", vars
-?Py.Str(Py.Eval("norm.cdf(0.0)", vars))
-0.5
-?Py.Str(Py.Eval("type(norm.cdf(0.0))", vars))
-
-?Py.Var(Py.Eval("norm.cdf(0.0)", vars))
-```
-
-The last expression causes an error, because the `Py.Var` function (or, more generally PyWin32) doesn't know how to convert a `numpy.float64` object to a native VBA type.
-
-So how do you get the value out of Python and into VBA? The key is to convert it to a type which `Py.Var` _does_ know how to convert, such as `float`. Note that this can be done either within your Python code:
-
-```
-?Py.Var(Py.Eval("float(norm.cdf(0.0))", vars))
- 0.5
-```
-
-or in the VBA code by calling the Python conversion function directly on the returned object:
-
-```
-?Py.Var(Py.Call(Py.Builtins, "float", Py.Tuple(Py.Eval("norm.cdf(0.0)", locals))))
- 0.5
-```
-
-This second method, while a bit more convoluted, means your Python code does not have to be written to take into account that it could be called from Excel.
-
-The same applies to passing in/out Numpy arrays. Suppose you have a function that takes NumPy arrays as inputs and returns them as outputs:
-
-```python
-# MatrixFunctions.py
-import numpy as np
-
-def xl_mmult(x, y):
- return x.dot(y)
-```
-
-This can be called from VBA code (without modifying the original Python code) like so:
-
-```vb.net
-Public Function PyXLMult(x As Range, y As Range)
-
-On Error GoTo fail:
-
- ' Python equivalent: import numpy; numpyArray = numpy.array
- Set numpyArray = Py.GetAttr(Py.Module("numpy"), "array")
-
- ' Python equivalent: x_array = numpyArray(x)
- Set x_array = Py.Call(numpyArray, Py.Tuple(x.Value2))
-
- ' Python equivalent: y_array = numpyArray(y)
- Set y_array = Py.Call(numpyArray, Py.Tuple(y.Value2))
-
- ' Python equivalent: result_array = xl_mmult(x_array, y_array)
- Set result_array = Py.Call(Py.Module("MatrixFunctions"), "xl_mmult", Py.Tuple(x_array, y_array))
-
- ' Python equivalent: result_list = result_array.tolist()
- Set result_list = Py.Call(result_array, "tolist")
-
- PyXLMult = Py.Var(result_list)
- Exit Function
-
-fail:
- PyXLMult = Err.Description
-
-End Function
-```
diff --git a/examples/index.md b/examples/index.md
new file mode 100644
index 0000000..d786905
--- /dev/null
+++ b/examples/index.md
@@ -0,0 +1,88 @@
+---
+layout: page
+title: "Examples"
+---
+
+## Examples
+
+**Note**: The lite examples now require the latest version of xlwings installed. Also, the only sample that currently works
+on Windows and Mac is the Fibonacci Lite sample. The others use ActiveX controls that are not supported on Mac. This
+will be changed at some point to make them all cross-platform. Standalone samples work on Windows only.
+
+### Instructions
+
+1. Download the zip-file
+2. Windows: Right-Click > Extract All... > Extract / Mac: Double-click the zip-file
+3. Open the Spreadsheet in the unzipped folder
+4. "Protected View": click on "Enable Editing"
+5. Optional: If Excel gives you an additional "Security Warning": click on "Enable Content", then
+ please close and reopen the file
+6. Run the examples by clicking on the "Run" button
+
+
+### Downloads
+
+**Example 1: Fibonacci Sequence**
+
+This is the simplest possible example demonstrating the calculation of the Fibonacci sequence.
+
+* **Lite (Win & Mac):** [fibonacci.zip][] (32.5 KB) - Dependencies: Python, pywin32, xlwings
+* **Standalone (Win):** [fibonacci_standalone.zip][] (6.3 MB)
+
+[fibonacci.zip]: https://bitbucket.org/zoomeranalytics/xlwings_examples/downloads/fibonacci.zip
+[fibonacci_standalone.zip]: https://bitbucket.org/zoomeranalytics/xlwings_examples/downloads/fibonacci_standalone.zip
+
+
+**Example 2: Database**
+
+This example shows how easy it is to work with databases. It uses [Chinook][], a popular [SQLite][] sample
+database.
+
+* **Lite (Win):** [database.zip][] (484.4 KB) - Dependencies: Python, pywin32, xlwings
+* **Standalone (Win):** [database_standalone.zip][] (7.1 MB)
+
+[Chinook]: http://chinookdatabase.codeplex.com/
+[SQLite]: http://sqlite.org/
+[database.zip]: https://bitbucket.org/zoomeranalytics/xlwings_examples/downloads/database.zip
+[database_standalone.zip]: https://bitbucket.org/zoomeranalytics/xlwings_examples/downloads/database_standalone.zip
+
+**Example 3: Monte Carlo Simulation**
+
+This example shows the computational power of Python by performing a Monte Carlo simulation of the price development of
+a financial asset. Prices are assumed to follow a log-normal distribution.
+
+* **Lite (Win):** [simulation.zip][] (151.1 KB) - Dependencies: Python, pywin32, xlwings, NumPy
+* **Standalone (Win):** [simulation_standalone.zip][] (16.8 MB)
+
+
+
+[simulation.zip]: https://bitbucket.org/zoomeranalytics/xlwings_examples/downloads/simulation.zip
+[simulation_standalone.zip]: https://bitbucket.org/zoomeranalytics/xlwings_examples/downloads/simulation_standalone.zip
+
+
+### Lite Versions
+
+These versions are small in size but require an installation of Python with xlwings. It is highly recommended to install
+one of the following scientific Python distributions as they already contain all of the necessary packages used in the
+examples, most importantly pywin32, numpy, scipy and pandas.
+
+* [Anaconda](https://store.continuum.io/cshop/anaconda/)
+* [WinPython](http://winpython.sourceforge.net/) (see Notes below)
+* [Canopy](https://www.enthought.com/products/canopy/)
+* [Python(x,y)](https://code.google.com/p/pythonxy/)
+
+
+### Standalone Versions
+
+These versions run out-of-the-box after unzipping without any dependencies but are bigger in size.
+
+
+### Notes
+
+**WinPython**: Since WinPython doesn't change the PATH environment variables, you either have to add the location
+ of the Python interpreter to the PATH manually or change the directory in the spreadsheet as follows:
+
+* Press `Alt-F11` to fire up the VBA Editor
+* Double-click the `xlwings` module
+* In the `RunPython` function, change `PYTHON_DIR = ""` to the directory of where `python.exe` is, e.g.:
+`PYTHON_DIR = "C:\WinPython-64bit-2.7.6.3\python-2.7.6"`
diff --git a/index.md b/index.md
new file mode 100644
index 0000000..fda212f
--- /dev/null
+++ b/index.md
@@ -0,0 +1,54 @@
+---
+layout: landingpage
+title: ExcelPython
+
+box_title: Why ExcelPython is awesome
+box: |
+ * **Easy deployment**: Just zip up your ExcelPython-powered workbook folder and distribute! No messing around with installing add-ins or registering COM servers on the end-user's machine.
+ * **Compatible**: Works with most combinations of Excel and Python - you can even mix 32 and 64 bits. Plays well with [xlwings]!
+ * **Flexible**: Target specific a Python installation or runtime environment for your workbook.
+ * **High performance**: The Python runtime only gets loaded once the first time you call into Python code, which means the successive calls are not slowed down by heavy library imports.
+ * **Powerful**: Access the entire Excel COM object model from Python.
+ * **Free and open-source**: ExcelPython is released under a permissive [MIT license][].
+
+ [xlwings]: http://xlwings.org
+ [Python]: http://www.python.org
+ [MIT license]: https://github.com/ericremoreynolds/excelpython/blob/master/LICENSE
+ [dependencies]: http://docs.xlwings.org/installation.html#dependencies
+---
+
+
+
+
+
+# Write Excel UDFs and macros in Python!
+
+
+
+
+
+## Replace your VBA code with Python, a powerful yet easy-to-use programming language that is highly suited for numerical analysis.
+
+