wxPython is a Python packages that wraps the UI toolkit wxWindows.
This document is not a guide to use wxPython or wxWindows. It is only intended to instruct you on how to use wxPython with the Custom Task Pane feature of PyXLL. You should refer to the relevant package documentation for details of how to use wxPython and wxWindows.
Both wxWindows can be installed using pip or conda, for example:
> pip install wxpython
# or
> conda install wxpython
You should install it using pip or conda and not both.
You can find more information about wxPython on the website https://www.wxpython.org/.
Two of the main classes we’ll use in wxPython are the wx.Frame
and wx.Panel
classes.
A wx.Frame
is the main window type, and it’s this that you’ll create to contain your user interface that
will be embedded into Excel as a Custom Task Panel. Frames typically host a single wx.Panel
which is where all
the controls that make up your user interface will be placed.
The following code demonstrates how to create simple wx.Frame and corresponding wx.Panel. If you run this code as a Python script then you will see the frame being shown.
import wx
class ExamplePanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent=parent)
# Create a sizer that will lay everything out in the panel.
# A BoxSizer can arrange controls horizontally or vertically.
sizer = wx.BoxSizer(orient=wx.VERTICAL)
# Create a TextCtrl control and add it to the layout
self.text_ctrl = wx.TextCtrl(self)
sizer.Add(self.text_ctrl)
# Create a StaticText control and add it to the layout
self.static_text = wx.StaticText(self)
sizer.Add(self.static_text)
# Connect the 'EVT_TEXT' event to our 'onText' method
self.text_ctrl.Bind(wx.EVT_TEXT, self.onText)
# Set the sizer for this panel and layout the controls
self.SetSizer(sizer)
self.Layout()
def onText(self, event):
"""Called when the TextCtrl's text is changed"""
# Set the text from the event onto the static_text control
text = event.GetString()
self.static_text.SetLabel(text)
class ExampleFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None)
# Give this frame a title
self.SetTitle("Wx Example")
# Create the panel that contains the controls for this frame
self.panel = ExamplePanel(parent=self)
if __name__ == "__main__":
# Create the wx Application object
app = wx.App()
# Construct our example Frame and show it
frame = ExampleFrame()
frame.Show()
# Run the application's main event loop
app.MainLoop()
When you run this code you will see our example frame being display, and as you enter text into the text control the static text below will be updated.
Next we’ll see how we can use this frame in Excel.
To show a wx.Frame in Excel using PyXLL we use the create_ctp
function.
As above, before we can create the frame we have to make sure the wx.App application object has been initialized. Unlike the above script, our function may be called many times and so we don’t want to create a new application each time and so we check to see if one already exists.
The wx.App object must still exist when we call create_ctp
. If it has gone out
of scope and been released then it will cause problems later so always make sure to keep a
reference to it.
We can create the Custom Task Pane from many different places, but usually it will be from a ribbon function or a menu function.
The following code shows how we would create a custom task pane from an Excel menu
function, using the ExampleFrame
control from the example above.
from pyxll import xl_menu, create_ctp, CTPDockPositionFloating
import wx
@xl_menu("Example wx CTP")
def example_wx_ctp():
# Before we can create a wx.Frame the wx.App must have been initialized.
# Make sure we keep a reference to this until create_ctp is called.
app = wx.App.Get()
if app is None:
app = wx.App()
# Create our example frame from the code above
frame = ExampleFrame()
# Use PyXLL's 'create_ctp' function to create the custom task pane.
# The width, height and position arguments are optional, but for this
# example we'll create the CTP as a floating window rather than the
# default of having it docked to the right.
create_ctp(frame,
width=400,
height=400,
position=CTPDockPositionFloating)
When we add this code to PyXLL and reload the new menu function “Example wx CTP” will be available, and when that menu function is run the ExampleFrame is opened as a Custom Task Pane in Excel.
Unlike a modal dialog, a Custom Task Pane does not block Excel from functioning. It can be moved and resized, and even docked into the current Excel window in exactly the same way as the native Excel tools.
See the API reference for create_ctp
for more details.