sampledoc

Please contact info@pyxll.com with any enquiries.

Current version: 1.3.3

Previous topic

Macros and Excel Automation

Next topic

Object cache

PyXLL callbacksΒΆ

It’s possible to register functions for PyXLL to call at certain points. These examples show how to use each of the callback decorators.

See also PyXLL callbacks.

"""
PyXLL Examples: Callbacks

The PyXLL Excel Addin is configured to load one or more
python modules when it's loaded.

Moldules can register callbacks with PyXLL that will be
called at various times to inform the user code of
certain events.
"""

from pyxll import xl_on_open,               \
                    xl_on_reload,           \
                    xl_on_close,            \
                    xl_license_notifier,    \
                    xlcCalculateNow

import logging
_log = logging.getLogger(__name__)

try:
    import win32api
    import win32con
except ImportError:
    _log.warning( "*** win32api could not be imported                ***")
    _log.warning( "*** the callback examples will not work correctly ***")
    _log.warning( "*** to fix this, install the pywin32 extensions   ***")
    win32api = None

@xl_on_open
def on_open(import_info):
    """
    on_open is registered to be called by PyXLL when the addin
    is opened via the xl_on_open decorator.
    This happens each time Excel starts with PyXLL installed.
    """
    # check to see which modules didn't import correctly
    errors = []
    for modulename, module, exc_info in import_info:
        if module is None:
            exc_type, exc_value, exc_traceback = exc_info
            errors.append("Error loading '%s' : %s" % (modulename, exc_value))

    if errors:
        # report any errors to the user
        if win32api:
            win32api.MessageBox(0,
                                "\n".join(errors) + "\n\n(See callbacks.py example)",
                                "PyXLL Callbacks Example",
                                win32con.MB_ICONWARNING)
        else:
            _log.info("callbacks.on_open: " + "\n".join(errors))

@xl_on_reload
def on_reload(import_info):
    """
    on_reload is registered to be called by PyXLL whenever a
    reload occurs via the xl_on_reload decorator.
    """
    # check to see which modules didn't import correctly
    errors = []
    for modulename, module, exc_info in import_info:
        if module is None:
            exc_type, exc_value, exc_traceback = exc_info
            errors.append("Error loading '%s' : %s" % (modulename, exc_value))

    if errors:
        # report any errors to the user
        if win32api:
            win32api.MessageBox(0,
                                "\n".join(errors) + "\n\n(See callbacks.py example)",
                                "PyXLL Callbacks Example",
                                win32con.MB_ICONWARNING)
        else:
            _log.info("callbacks.on_reload: " + "\n".join(errors))
    else:
        # report everything reloaded OK
        if win32api:
            win32api.MessageBox(0,
                                "PyXLL Reloaded OK\n(See callbacks.py example)",
                                "PyXLL Callbacks Example",
                                win32con.MB_ICONINFORMATION)
        else:
            _log.info("callbacks.on_reload: PyXLL Reloaded OK")
 
    # recalcuate all open workbooks
    xlcCalculateNow()
 
@xl_on_close
def on_close():
    """
    on_close will get called as Excel is about to close.

    This is a good time to clean up any globals and stop
    any background threads so that the python interpretter
    can be closed down cleanly.
    
    The user may cancel Excel closing after this has been
    called, so your code should make sure that anything
    that's been cleaned up here will get recreated again
    if it's needed.
    """
    _log.info("callbacks.on_close: PyXLL is closing")

@xl_license_notifier
def license_notifier(name, expdate, days_left, is_perpetual):
    """
    license_notifier will be called when PyXLL is starting up, after
    it has read the config and verified the license.
    
    If there is no license name will be None and days_left will be less than 0.
    """
    if days_left >= 0 or is_perpetual:
        _log.info("callbacks.license_notifier: "
                    "This copy of PyXLL is licensed to %s" % name)
        if not is_perpetual:
            _log.info("callbacks.license_notifier: "
                        "%d days left before the license expires (%s)" % (days_left, expdate))
    else:
        _log.info("callbacks.license_notifier: "
                    "This copy of PyXLL is for evaluation or non-commercial use only")