Skip to content

Commit 5acf2d2

Browse files
2 parents 495639c + 88e3dd3 commit 5acf2d2

File tree

8 files changed

+220
-50
lines changed

8 files changed

+220
-50
lines changed

README.md

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,32 @@
11
# ExcelPython v2
22

3-
### Get started
3+
Write Excel user-defined functions in Python!
44

5-
* Download the [latest release](https://github.com/ericremoreynolds/excelpython/releases)
6-
* Unzip it into the folder containing your workbook (this will create the `xlpython` folder)
7-
* Import the module `xlpython\xlpython.bas` into your workbook
8-
9-
and you're set! No registration or typelibs. All that is needed is Python with PyWin32 installed.
10-
11-
```vb.net
12-
Sub test1()
13-
MsgBox Py.Str(Py.Eval("1+2"))
14-
End Sub
15-
16-
Sub test2()
17-
Set vars = Py.Dict()
18-
Py.Exec "from datetime import date", vars
19-
MsgBox Py.Str(Py.Eval("date.today()", vars))
20-
End Sub
21-
22-
Sub test3()
23-
' Assumes there's a file called MyScript.py in the same folder as the workbook
24-
' with a function called MyFunction taking 3 arguments
25-
Set m = Py.Module("MyScript")
26-
MsgBox Py.Str(Py.Call(m, "MyFunction", Py.Tuple(1, 2, 3)))
27-
End Sub
5+
```python
6+
from xlpython import *
7+
8+
@xlfunc
9+
@xlarg("x", "nparray", 2)
10+
@xlarg("y", "nparray", 2)
11+
def matrixmult(x, y):
12+
return x.dot(y)
2813
```
2914

30-
Note that the latest release zip also contains an Excel add-in `xlpython.xlam`. We're still in the process of developing that, not to mention writing the documentation - but feel welcome to take a look, and see what it does! Sneak preview: automatic generation of VBA wrappers for Python functions.
31-
15+
![image](https://cloud.githubusercontent.com/assets/5197585/3907706/6c3a2cea-22fd-11e4-812f-41c814d1cc54.png)
16+
3217
### About ExcelPython
3318

34-
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.
19+
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.
20+
21+
### Getting started
22+
23+
* Download the [latest release](https://github.com/ericremoreynolds/excelpython/releases)
24+
* Check out the [tutorials](docs/) to help you get going
3525

36-
v2 is a major rewrite of the previous ExcelPython, moving over to a new approach which is more robust and configurable - and importantly should eliminate all those irritating DLL not found problems! The technical details: Python now runs out-of-process and communication happens over COM.
26+
The only prerequisites are Excel and Python with PyWin32 installed.
3727

3828
### Help me!
3929

40-
Check out the [docs](docs/) folder for tutorials to help you get started and links to other resources.
30+
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/).
4131

42-
If you 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 me and everyone else know what you're doing with ExcelPython, please create an issue ticket!
32+
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)!

docs/Readme.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
Learn how to manipulate Python objects in VBA:
1+
**Getting started with the ExcelPython add-in**
2+
3+
1. [Loading the add-in and writing your first user-defined function](tutorials/Addin01.md)
4+
1. [Dealing with array arguments](tutorials/Addin02.md)
5+
1. [Something a bit more interesting - NumPy arrays](tutorials/Addin03.md)
6+
1. [Permanently installing the add-in](tutorials/Addin04.md)
7+
8+
**Learn how to manipulate Python objects in VBA**
29

310
1. [A very simple usage example](tutorials/Usage01.md)
411
2. [A more practical use of ExcelPython](tutorials/Usage02.md)
512
3. [Putting it all together](tutorials/Usage03.md)
613
4. [Ranges, lists and SAFEARRAYs](tutorials/Usage04.md)
714

8-
Delve deeper into how to target a particular Python installation and working environment:
15+
**Delve deeper into how to target a particular Python installation and working environment**
916

1017
* [Configuration](tutorials/Configuration01.md)
1118

12-
Learn how to analyse the problem when something goes wrong:
19+
**Learn how to analyse the problem when something goes wrong**
1320

1421
* [Troubleshooting](tutorials/Troubleshooting01.md)

docs/tutorials/Addin01.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## Loading the ExcelPython add-in
2+
3+
* Download the latest [release](https://github.com/ericremoreynolds/excelpython/releases) and unzip it somewhere.
4+
5+
* Open the add-in `xlpython.xlam` in Excel.
6+
7+
* If all goes well you should see the ExcelPython tab in Excel's toolbar.
8+
9+
![image](https://cloud.githubusercontent.com/assets/5197585/3917034/3623f40a-2385-11e4-9754-5e3b924e38a9.png)
10+
11+
* 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).
12+
13+
Note that it is possible to [permanently install the add-in](./Addin04.md) so you don't need to open it manually each time.
14+
15+
## Writing a user-defined function in Python
16+
17+
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.
18+
19+
* Choose an empty folder and in it save an empty workbook as `Book1.xlsm`.
20+
21+
* From the ExcelPython tab in the toolbar click 'Setup ExcelPython'.
22+
23+
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 can be defined.
24+
25+
* Edit `Book1.py` to contain the following code:
26+
27+
```python
28+
# Book1.py
29+
from xlpython import *
30+
31+
@xlfunc
32+
def DoubleSum(x, y):
33+
'''Returns twice the sum of the two arguments'''
34+
return 2 * (x + y)
35+
```
36+
37+
* Switch back to Excel and click 'Import Python UDFs' in the ExcelPython tab to pick up the changes made to `Book1.py`.
38+
39+
* Enter the formula `=DoubleSum(1, 2)` into a cell and you should get the correct result:
40+
41+
![image](https://cloud.githubusercontent.com/assets/5197585/3917596/e5365b3c-238e-11e4-8bce-0d97caceca2e.png)
42+
43+
* 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
44+
45+
```
46+
?DoubleSum(1, 2)
47+
```
48+
49+
To continue move onto the [next tutorial](./Addin02.md).

docs/tutorials/Addin02.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
## Array arguments
2+
3+
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.
4+
5+
* Add the following code to `Book1.py` from the [previous tutorial](./Addin01.md)
6+
7+
```python
8+
@xlfunc
9+
def MyUDF(x):
10+
return repr(x)
11+
```
12+
13+
This function simply returns its argument converted to string representation. This will allow us to explore how formula arguments are converted into Python objects.
14+
15+
* Click 'Import Python UDFs' to pick up the changes
16+
17+
* Modify the workbook as below
18+
19+
![image](https://cloud.githubusercontent.com/assets/5197585/3918899/302a5790-23a0-11e4-80fe-7c75b63c4225.png)
20+
21+
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.
22+
23+
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.
24+
25+
![image](https://cloud.githubusercontent.com/assets/5197585/3918954/f2a67fce-23a0-11e4-810d-52870204e77f.png)
26+
27+
![image](https://cloud.githubusercontent.com/assets/5197585/3918991/7e2187ec-23a1-11e4-8fd8-6405c3bbc7b7.png)
28+
29+
ExcelPython provides a mechanism for normalizing the input arguments so that your function can safely make assumptions about their dimensionality.
30+
31+
* Modify `Book1.py` as follows
32+
33+
```python
34+
@xlfunc
35+
@xlarg("x", dims=2) # add this line
36+
def MyUDF(x):
37+
return str(x)
38+
```
39+
40+
* Click 'Import Python UDFs' to pick up the changes.
41+
42+
* Now 1x1 ranges are passed as two-dimensional
43+
44+
![image](https://cloud.githubusercontent.com/assets/5197585/3919574/8c257714-23aa-11e4-82d5-97da8b5a5fb2.png)
45+
46+
At other times it you may want to assume that an argument that is one-dimensional
47+
48+
* Modify `Book1.py` as follows
49+
50+
```python
51+
@xlfunc
52+
@xlarg("x", dims=1) # modify this line
53+
def MyUDF(x):
54+
return str(x)
55+
```
56+
57+
* Click 'Import Python UDFs' to pick up the changes.
58+
59+
![image](https://cloud.githubusercontent.com/assets/5197585/3919614/54cedaa2-23ab-11e4-8ba9-56dcd86815ad.png)
60+
61+
![image](https://cloud.githubusercontent.com/assets/5197585/3919622/6b5ed790-23ab-11e4-9dce-52b45bb72717.png)
62+
63+
![image](https://cloud.githubusercontent.com/assets/5197585/3919656/00f96f9a-23ac-11e4-8d7c-c1ae1896002e.png)
64+
65+
* Clearly having specified the argument as one-dimensional, an error is raised if a two-dimensional range is passed
66+
67+
![image](https://cloud.githubusercontent.com/assets/5197585/3919669/379cdd66-23ac-11e4-8e47-dfe333143a45.png)
68+
69+
To continue move onto the [next tutorial](./Addin03.md).

docs/tutorials/Addin03.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Something a bit more interesting - NumPy arrays
2+
3+
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).
4+
5+
We will now define a simple function for doing matrix multiplication using NumPy.
6+
7+
* Add the following code to `Book1.py` from the [first tutorial](./Addin01.md)
8+
9+
```python
10+
@xlfunc
11+
@xlarg("x", "nparray", dims=2)
12+
@xlarg("y", "nparray", dims=2)
13+
def MatrixMult(x, y):
14+
return x.dot(y)
15+
```
16+
17+
* Click 'Import Python UDFs' to pick up the changes
18+
19+
* The function `MatrixMult` can now be used as an array function from Excel
20+
21+
![image](https://cloud.githubusercontent.com/assets/5197585/3918420/9ab74be2-2399-11e4-9b55-8a8005afeabc.png)
22+
23+
To enter the above array formula in Excel
24+
* fill in the values in the ranges `D1:E2` and `G1:H2`
25+
* select cells `A1:B2`
26+
* type in the formula `=MatrixMult(D1:E2, G1:H2)`
27+
* press `Ctrl+Shift+Enter`.
28+
29+
To continue move onto the [next tutorial](./Addin04.md).

docs/tutorials/Addin04.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Permanently installing the ExcelPython add-in
2+
3+
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:
4+
5+
![image](https://cloud.githubusercontent.com/assets/5197585/3917303/0ef6b35e-238a-11e4-9017-ab8cdb74719d.png)
6+
7+
Unfortunately the folder's location varies depending on the version of Excel. Some candidates are
8+
9+
Excel 2013 current user: %APPDATA%\Roaming\Microsoft\Excel\XLSTART
10+
Excel 2010 current user: %APPDATA%\Microsoft\Excel\XLSTART
11+
Excel 2007 current user: %APPDATA%\Microsoft\Excel\XLSTART
12+
Excel 2003 current user: %APPDATA%\Microsoft\Excel\XLSTART
13+
14+
Excel 2013 all users: %PROGRAMFILES%\Microsoft Office 15\root\Office15\XLSTART
15+
Excel 2010 all users: %PROGRAMFILES%\Microsoft Office\Office14\XLSTART
16+
Excel 2007 all users: %PROGRAMFILES%\Microsoft Office\Office12\XLSTART
17+
Excel 2003 all users: %PROGRAMFILES%\Microsoft Office\Office11\XLSTART
18+
19+
Note also that `%PROGRAMFILES%` may need to be substituted with `%PROGRAMFILES(x86)%` for 32-bit Excel installed on a 64-bit machine.
20+
21+
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
22+
23+
?Application.StartupPath
24+
25+
for the current user and
26+
27+
?Application.Path + "\XLSTART"
28+
29+
for all users.

docs/tutorials/AddinTrouble.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## Programmatic access to Visual Basic Project is not trusted
2+
3+
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.
4+
5+
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.
6+
7+
![image](https://cloud.githubusercontent.com/assets/5197585/3921677/77648a04-23c3-11e4-9af4-2a14ca47787e.png)

docs/tutorials/Configuration01.md

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,15 @@
1-
### Note: this documentation is out of date!
1+
**NB: work in progress**
22

33
# Configuring ExcelPython
44

5-
On of the most important features of ExcelPython is the ability to specify exactly which Python installation you wish to distribute, and to define an isolated Python execution environment with which your workbook interacts.
5+
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.
66

7-
In tutorials, the default configuration is used, which runs the PC's default Python installation (i.e. the one that appears by running `python.exe` in the Start > Run box).
7+
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.
88

9-
However when distributing a workbook which has been developed with xlpython, it is better to include a custom `.xlpy` configuration file which ensures that all the workbook's code will execute in a seperate Python process, thus not interfering with other xlpython workbooks which might have been opened by the user in Excel at the same time.
9+
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`.
1010

11-
Let's assume we're developing an Excel workbook called `MatrixAlgebra.xlsm` in the folder `...\Desktop\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 `...\Desktop\MatrixAlgebra\PortablePython` which we want to use to execute our Python code within the context of the workbook.
11+
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.
1212

13-
To create a config file for this setup, copy `xlpython.xlpy` into `...\Desktop\MatrixAlgebra` and rename it `MatrixAlgebra.xlpy`, then edit it as follows:
13+
To specify that the Python distribution in `%SOMEFOLDER%\MatrixAlgebra\PortablePython` must be used, make the following modification to `xlpython.cfg`
1414

15-
CLSID = {66496c37-eb73-4b42-baf6-fad4296e464c}
16-
17-
Command = $(ConfigDir)\PortablePython\python.exe $(DllDir)\xlpython.py $(CLSID)
18-
19-
WorkingDir = $(ConfigDir)
20-
21-
Then, in VBA, edit the xlpython module to use this new config file:
22-
23-
Function Py()
24-
If 0 <> GetPythonInterface(Py, ThisWorbook.Path + "\MatrixAlgebra.xlpy") Then Err.Raise 1000, Description:=Py
25-
End Function
15+
Command = $(ConfigDir)\..\PortablePython\pythonw.exe -u "$(ConfigDir)\xlpyserver.py" $(CLSID)

0 commit comments

Comments
 (0)