Skip to content

Commit

Permalink
Merge branch 'develop':v0.10.3 release
Browse files Browse the repository at this point in the history
  • Loading branch information
fzumstein committed Jan 28, 2017
2 parents dc33af3 + 801e71a commit 0d50b09
Show file tree
Hide file tree
Showing 20 changed files with 425 additions and 50 deletions.
137 changes: 119 additions & 18 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,110 +7,211 @@ Top-level functions
.. automodule:: xlwings
:members: view

Object model
------------

Apps
----
****

.. autoclass:: xlwings.main.Apps
:members:

App
---
***

.. autoclass:: App
:members:

Books
-----
*****

.. autoclass:: xlwings.main.Books
:members:

Book
----
****

.. autoclass:: Book
:members:

Sheets
------
******

.. autoclass:: xlwings.main.Sheets
:members:

Sheet
-----
*****

.. autoclass:: Sheet
:members:

Range
-----
*****

.. autoclass:: Range
:members:


RangeRows
---------
*********

.. autoclass:: RangeRows
:members:


RangeColumns
------------
************

.. autoclass:: RangeColumns
:members:


Shapes
------
******

.. autoclass:: xlwings.main.Shapes
:members:
:inherited-members:

Shape
-----
*****

.. autoclass:: Shape
:members:

Charts
------
******

.. autoclass:: xlwings.main.Charts
:members:
:inherited-members:

Chart
-----
*****

.. autoclass:: Chart
:members:

Pictures
--------
********

.. autoclass:: xlwings.main.Pictures
:members:
:inherited-members:

Picture
-------
*******

.. autoclass:: Picture
:members:

Names
-----
*****

.. autoclass:: xlwings.main.Names
:members:

Name
----
****

.. autoclass:: Name
:members:
:members:

.. _udf_api:

UDF decorators
--------------


.. py:function:: xlwings.func(category="xlwings", volatile=False, call_in_wizard=True)
Functions decorated with ``xlwings.func`` will be imported as ``Function`` to Excel when running
"Import Python UDFs".

Arguments
---------

category : int or str, default "xlwings"
1-14 represent built-in categories, for user-defined categories use strings

.. versionadded:: 0.10.3

volatile : bool, default False
Marks a user-defined function as volatile. A volatile function must be recalculated
whenever calculation occurs in any cells on the worksheet. A nonvolatile function is
recalculated only when the input variables change. This method has no effect if it's
not inside a user-defined function used to calculate a worksheet cell.

.. versionadded:: 0.10.3

call_in_wizard : bool, default True
Set to False to suppress the function call in the function wizard.

.. versionadded:: 0.10.3

.. py:function:: xlwings.sub()
Functions decorated with ``xlwings.sub`` will be imported as ``Sub`` (i.e. macro) to Excel when running
"Import Python UDFs".

.. py:function:: xlwings.arg(arg, convert=None, **options)
Apply converters and options to arguments, see also :meth:`Range.options`.


**Examples:**

Convert ``x`` into a 2-dimensional numpy array:

.. code-block:: python
import xlwings as xw
import numpy as np
@xw.func
@xw.arg('x', np.array, ndim=2)
def add_one(x):
return x + 1
.. py:function:: xlwings.ret(convert=None, **options)
Apply converters and options to return values, see also :meth:`Range.options`.

**Examples**

1) Suppress the index and header of a returned DataFrame:

.. code-block:: python
import pandas as pd
@xw.func
@xw.ret(index=False, header=False)
def get_dataframe(n, m):
return pd.DataFrame(np.arange(n * m).reshape((n, m)))
2) Dynamic array:

``expand='table'`` turns the UDF into a dynamic array. Currently you must not use volatile functions
as arguments of a dynamic array, e.g. you cannot use ``=TODAY()`` as part of a dynamic array. Also
note that a dynamic array needs an empty row and column at the bottom and to the right and will overwrite
existing data without warning.

Unlike standard Excel arrays, dynamic arrays are being used from a single cell like a standard function
and auto-expand depending on the dimensions of the returned array:

.. code-block:: python
import xlwings as xw
import numpy as np
@xw.func
@xw.ret(expand='table')
def dynamic_array(n, m):
return np.arange(n * m).reshape((n, m))
.. versionadded:: 0.10.0
2 changes: 1 addition & 1 deletion docs/debugging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Consider the following sample code of your Python source code ``my_module.py``:
if __name__ == '__main__':
# Expects the Excel file next to this source file, adjust accordingly.
xw.Book('myfile.xlsxm').set_mock_caller()
xw.Book('myfile.xlsm').set_mock_caller()
my_macro()
Expand Down
15 changes: 10 additions & 5 deletions docs/udfs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
UDF Tutorial
============

.. note:: UDFs are currently only available on Windows.
This tutorial gets you quickly started on how to write User Defined Functions.

This tutorial gets you quickly started on how to write User Defined Functions. For details of how to control the behaviour
of the arguments and return values, have a look at :ref:`converters`.
.. note::
* UDFs are currently only available on Windows.
* For details of how to control the behaviour of the arguments and return values, have a look at :ref:`converters`.
* For a comprehensive overview of the available decorators and their options, check out the corresponding API docs: :ref:`udf_api`.

One-time Excel preparations
---------------------------
Expand Down Expand Up @@ -188,8 +190,11 @@ This is a simple example that demonstrates the syntax and effect of UDF expansio
.. figure:: images/dynamic_array2.png
:scale: 40%

**Note**: Expanding array formulas will overwrite cells without prompting and leave an empty border around them, i.e.
they will clear the row to the bottom and the column to the right of the array.
.. note::
* Expanding array formulas will overwrite cells without prompting and leave an empty border around them, i.e.
they will clear the row to the bottom and the column to the right of the array.
* The way that dynamic array formulas are currently implemented doesn't allow them to have volatile functions
as arguments, e.g. you cannot use functions like ``=TODAY()`` as arguments.

Docstrings
----------
Expand Down
20 changes: 20 additions & 0 deletions docs/whatsnew.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
What's New
==========

v0.10.3 (Jan 28, 2017)
----------------------

This release adds new features to User Defined Functions (UDFs):

* categories
* volatile option
* suppress calculation in function wizard

Syntax:

.. code-block:: python
import xlwings as xw
@xw.func(category="xlwings", volatile=False, call_in_wizard=True)
def myfunction():
return ...
For details, check out the (also new) and comprehensive API docs about the decorators: :ref:`udf_api`

v0.10.2 (Dec 31, 2016)
----------------------

Expand Down
Binary file modified examples/database/database.xlsm
Binary file not shown.
Binary file modified examples/fibonacci/fibonacci.xlsm
Binary file not shown.
Binary file modified examples/ga_dashboard/ga_dashboard.xlsm
Binary file not shown.
Binary file modified examples/mpl/mpl.xlsm
Binary file not shown.
Binary file modified examples/simulation/simulation.xlsm
Binary file not shown.
Binary file modified examples/udf/udf.xlsm
Binary file not shown.
2 changes: 1 addition & 1 deletion xlwings/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import absolute_import
import sys

__version__ = '0.10.2'
__version__ = '0.10.3'

# Python 2 vs 3
PY3 = sys.version_info[0] == 3
Expand Down
Binary file modified xlwings/quickstart.xlsm
Binary file not shown.
27 changes: 22 additions & 5 deletions xlwings/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,12 +329,29 @@ def _CreateInstance_(self, reqClsid, reqIID):
break

task = idle_queue.pop(0)
try:
task()
except:
import traceback
print("TaskQueue '%s' threw an exeception: %s", task, traceback.format_exc())
_execute_task(task)

pythoncom.CoRevokeClassObject(revokeId)
pythoncom.CoUninitialize()


def _execute_task(task):
try:
task()
except Exception as e:
if _ask_for_retry(e) and _can_retry(task):
print("Retrying TaskQueue '%s'." % task)
_execute_task(task)
else:
import traceback
print("TaskQueue '%s' threw an exception: %s" % task, traceback.format_exc())


def _can_retry(task):
return hasattr(task, 'nb_remaining_call') and task.nb_remaining_call > 0

RPC_E_SERVERCALL_RETRYLATER = -2147418111


def _ask_for_retry(exception):
return hasattr(exception, 'hresult') and exception.hresult == RPC_E_SERVERCALL_RETRYLATER
Binary file modified xlwings/tests/udfs/bdh_tests.xlsm
Binary file not shown.
Loading

0 comments on commit 0d50b09

Please sign in to comment.