Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trouble with Event Callbacks in Wx TaskPane #106

Open
gnyuan opened this issue Jun 20, 2024 · 6 comments
Open

Trouble with Event Callbacks in Wx TaskPane #106

gnyuan opened this issue Jun 20, 2024 · 6 comments

Comments

@gnyuan
Copy link

gnyuan commented Jun 20, 2024

I learned from the documentation examples how to modify the TaskPane components from the Ribbon. However, I am now trying to build a tree within the TaskPane, but clicking on the UI elements does not seem to properly trigger the event functions. Below is the sample code, and I'm not sure where the issue lies. Thank you.

from xloil.gui.wx import wx_thread
import wx

import xloil as xlo


def _ribbon_func_map(func: str):
    xlo.log.debug(f"Calling xlOil Ribbon '{func}'...")
    return globals()[func]


class TreePane(wx.Frame):
    def __init__(self):
        super().__init__(None, title="Tree", size=(400, 300))

        self.panel = wx.Panel(self)
        main_sizer = wx.BoxSizer(wx.VERTICAL)

        self.tree = wx.TreeCtrl(self.panel)
        root = self.tree.AddRoot("a Tree")
        item1 = self.tree.AppendItem(root, "item1")
        item2 = self.tree.AppendItem(root, "item2")
        self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnChanged, self.tree)

        main_sizer.Add(self.tree, 1, wx.EXPAND | wx.ALL, 5)
        self.panel.SetSizer(main_sizer)

    @wx_thread
    def OnChanged(self, event):
        # xlo.active_worksheet().cell(0,0).value = 1  # ERROR, how to control worksheet in TaskPane?
        xlo.info.log(1)


_PENDING_PANES = dict()


async def makeTreePane(ctrl):
    global _ribbon_ui
    pane_name = "tree"
    wb = xlo.active_workbook()
    key = (pane_name, wb.name)
    pane = xlo.gui.find_task_pane(title=pane_name, workbook=wb)
    if pane is not None:
        xlo.log(f"Found pane: {key}")
        pane.visible = True
        return
    pane_future = _PENDING_PANES.get(key, None)
    if pane_future is not None:
        return
    future = _ribbon_ui.attach_pane_async(name=pane_name, pane=TreePane)
    _PENDING_PANES[key] = future
    pane = await future
    del _PENDING_PANES[key]
    pane._pane.position = "left"
    pane.visible = True

    return pane

_ribbon_ui = xlo.ExcelGUI(
    ribbon=r"""
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
   <ribbon>
      <tabs>
         <tab id="tab1" label="TestTab">
            <group id="env" autoScale="false" centerVertically="false" label="TreeGroup">
               <button id="function" size="large" label="Tree" onAction="makeTreePane" imageMso="GroupFunctionLibrary" />
            </group>
         </tab>
      </tabs>
   </ribbon>
</customUI>
    """,
    funcmap=_ribbon_func_map,
)

image

@cunnane
Copy link
Owner

cunnane commented Jul 1, 2024

Does your TreePane class work if you use it in a standalone wx gui, independently of xloil?

To answer the code comment, to write to the worksheet (or interact with Excel in general), you need to invoke your command from the main thread using excel_callback. Just pass a zero-arg lambda which does the worksheet writing.

@gnyuan
Copy link
Author

gnyuan commented Jul 21, 2024

Does your TreePane class work if you use it in a standalone wx gui, independently of xloil?

To answer the code comment, to write to the worksheet (or interact with Excel in general), you need to invoke your command from the main thread using excel_callback. Just pass a zero-arg lambda which does the worksheet writing.

Yes, the TreePane class can be used independently in a standalone wx GUI, without relying on xloil. I have tested this by running the example provided in the documentation here. However, I encountered an issue where Excel crashed when I closed it. Could you please provide some examples that demonstrate the proper usage of the TaskPane ? I would greatly appreciate it. Thank you!

@cunnane
Copy link
Owner

cunnane commented Aug 9, 2024

For reasons I don't quite understand Wx resists my attempt to display it as a subwindow in Excel. I'm working on a workaround...but it's resisting. Will let you know when I have something

@cunnane
Copy link
Owner

cunnane commented Sep 16, 2024

This is fixed in xlOil v0.19 (which is currently on pip)

@gnyuan
Copy link
Author

gnyuan commented Sep 18, 2024

Thank you for the update, but I checked again, and the issue remains unchanged. Additionally, each time the TaskPane is loaded, I am unable to close Excel properly.
The debug log:

[2024-09-18 10:06:46.018] [logger] [info] [AddinLoader.cpp:65] Found settings file 'C:\Users\yuangn\AppData\Roaming\xlOil\xlOil.ini' for 'D:\workspace\excel\.venv\share\xloil\xlOil.dll'
[2024-09-18 10:06:46.018] [logger] [debug] [AddinLoader.cpp:72] Registering date format '%Y-%m-%d'
[2024-09-18 10:06:46.018] [logger] [debug] [AddinLoader.cpp:72] Registering date format '%Y%b%d'
[2024-09-18 10:06:46.018] [logger] [debug] [AddinLoader.cpp:112] Creating addin context for 'C:\Users\yuangn\AppData\Roaming\Microsoft\Excel\XLSTART\xlOil.xll'
[2024-09-18 10:06:46.018] [logger] [debug] [CoreEntryPoint.cpp:70] Loaded xlOil core from: D:\workspace\excel\.venv\share\xloil\xlOil.dll
[2024-09-18 10:06:46.018] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloRunInXLLContext" at entry point xloRunInXLLContext with 0 args
[2024-09-18 10:06:46.024] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloVersion" at entry point xloVersion with 0 args
[2024-09-18 10:06:46.025] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloLog" at entry point xloLog with 1 args
[2024-09-18 10:06:46.025] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloHelp" at entry point xloHelp with 1 args
[2024-09-18 10:06:46.025] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloRef" at entry point xloRef with 1 args
[2024-09-18 10:06:46.025] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloVal" at entry point xloVal with 1 args
[2024-09-18 10:06:46.026] [logger] [debug] [FuncRegistry.cpp:229] Registering "RegistrationInfo_2b0ab4b16c52540d9fb32e0cff7a62bf" at entry point IntellisenseRegistrationInfo with 1 args
[2024-09-18 10:06:46.340] [logger] [debug] [Connect.cpp:81] Made COM connection to Excel at 'C:\Program Files\Microsoft Office\Office15' with hwnd=4268130
[2024-09-18 10:06:46.340] [logger] [info] [PluginLoader.cpp:62] Loading plugins from settings file C:\Users\yuangn\AppData\Roaming\xlOil\xlOil.ini
[2024-09-18 10:06:46.340] [logger] [info] [PluginLoader.cpp:79] Loading plugin xlOil_Python
[2024-09-18 10:06:46.341] [logger] [debug] [PluginLoader.cpp:95] Setting environment variable: PYTHONCASEOK='1'
[2024-09-18 10:06:46.341] [logger] [debug] [PluginLoader.cpp:95] Setting environment variable: XLOIL_PYTHON_PATH=';'
[2024-09-18 10:06:46.341] [logger] [debug] [PluginLoader.cpp:95] Setting environment variable: XLOIL_PYTHON_VERSION=''
[2024-09-18 10:06:46.341] [logger] [debug] [PluginLoader.cpp:95] Setting environment variable: PYTHONEXECUTABLE='D:\workspace\excel\.venv\Scripts\python.exe'
[2024-09-18 10:06:46.341] [logger] [debug] [PluginLoader.cpp:95] Setting environment variable: PYTHONPATH='D:\workspace\excel;%PYTHONPATH%;;'
[2024-09-18 10:06:46.343] [logger] [debug] [Main.cpp:122] Python interpreter starting
[2024-09-18 10:06:46.368] [logger] [info] [Main.cpp:302] Python started with environment: sys.prefix=D:\workspace\excel\.venv
sys.base_prefix=D:\python312
sys.path=['D:\\workspace\\excel', 'C:\\Users\\yuangn\\Documents\\%PYTHONPATH%', 'C:\\Users\\yuangn\\Documents', 'D:\\python312\\python312.zip', 'D:\\python312\\DLLs', 'D:\\python312\\Lib', 'D:\\python312', 'D:\\workspace\\excel\\.venv', 'D:\\workspace\\excel\\.venv\\Lib\\site-packages', 'D:\\workspace\\excel\\.venv\\Lib\\site-packages\\win32', 'D:\\workspace\\excel\\.venv\\Lib\\site-packages\\win32\\lib', 'D:\\workspace\\excel\\.venv\\Lib\\site-packages\\Pythonwin', 'D:\\workspace\\excel\\.venv\\share\\xloil\\']
[2024-09-18 10:06:46.369] [logger] [debug] [Main.cpp:306] Python importing xloil_core
[2024-09-18 10:06:46.369] [logger] [debug] [PyCore.cpp:142] Python importing numpy
[2024-09-18 10:06:46.524] [logger] [debug] [Main.cpp:322] Python importing xloil
[2024-09-18 10:06:46.540] [logger] [debug] [Events.cpp:61] Started directory watch on 'D:\workspace\excel\.venv'
[2024-09-18 10:06:46.540] [logger] [info] [PyEvents.cpp:117] Event D:\workspace\excel\.venv\ added handler 0x23f5c3d9300
[2024-09-18 10:06:46.540] [logger] [debug] [Events.cpp:61] Started directory watch on 'D:\python312\Lib\zipfile\_path\'
[2024-09-18 10:06:46.540] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\zipfile\_path\glob.py added handler 0x23f5c77f100
[2024-09-18 10:06:46.540] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\zipfile\_path\__init__.py added handler 0x23f5c77ce40
[2024-09-18 10:06:46.544] [logger] [debug] [Events.cpp:61] Started directory watch on 'D:\python312\Lib\email\'
[2024-09-18 10:06:46.544] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\_parseaddr.py added handler 0x23f5c7af7c0
[2024-09-18 10:06:46.545] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\base64mime.py added handler 0x23f5c7ce480
[2024-09-18 10:06:46.545] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\quoprimime.py added handler 0x23f5c7cf0c0
[2024-09-18 10:06:46.546] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\errors.py added handler 0x23f5c7cff40
[2024-09-18 10:06:46.546] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\encoders.py added handler 0x23f5c7d8e80
[2024-09-18 10:06:46.547] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\charset.py added handler 0x23f5c7cde80
[2024-09-18 10:06:46.547] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\utils.py added handler 0x23f5c7d9700
[2024-09-18 10:06:46.548] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\header.py added handler 0x23f5c7f4c00
[2024-09-18 10:06:46.548] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\_policybase.py added handler 0x23f5c3e6100
[2024-09-18 10:06:46.549] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\_encoded_words.py added handler 0x23f5c7f5840
[2024-09-18 10:06:46.549] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\iterators.py added handler 0x23f5c7f5d40
[2024-09-18 10:06:46.549] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\email\message.py added handler 0x23f5c7f5ec0
[2024-09-18 10:06:46.550] [logger] [debug] [Events.cpp:61] Started directory watch on 'D:\python312\Lib\importlib\metadata\'
[2024-09-18 10:06:46.550] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\importlib\metadata\_functools.py added handler 0x23f5c7f67c0
[2024-09-18 10:06:46.550] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\importlib\metadata\_text.py added handler 0x23f5c7f6380
[2024-09-18 10:06:46.550] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\importlib\metadata\_adapters.py added handler 0x23f5c77e7c0
[2024-09-18 10:06:46.551] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\importlib\metadata\_meta.py added handler 0x23f5c800c00
[2024-09-18 10:06:46.551] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\importlib\metadata\_collections.py added handler 0x23f5c800d80
[2024-09-18 10:06:46.552] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\importlib\metadata\_itertools.py added handler 0x23f5c800f00
[2024-09-18 10:06:46.553] [logger] [debug] [importer.py:465] Installed importlib hook to call scan_module
[2024-09-18 10:06:46.555] [logger] [debug] [PluginLoader.cpp:137] Finished loading plugin xlOil_Python
[2024-09-18 10:06:46.903] [logger] [debug] [Events.h:175] Firing event WorkbookOpen C:\Users\yuangn\Downloads\etc, t.xlsx,
[2024-09-18 10:06:46.903] [logger] [debug] [PySource.cpp:167] Looking for workbook module at 'C:\Users\yuangn\Downloads\etc\t.py'
[2024-09-18 10:06:46.909] [logger] [debug] [Events.h:175] Firing event AfterCalculate
[2024-09-18 10:06:47.331] [logger] [debug] [PyEvents.cpp:360] Events enabled: Excel=true, xlOil=false
[2024-09-18 10:06:47.332] [logger] [debug] [register.py:110] Interpreted arg 'ModuleName:str' => 'ModuleName:str ()'
[2024-09-18 10:06:47.332] [logger] [debug] [register.py:110] Interpreted arg 'From:=None' => 'From:object ()'
[2024-09-18 10:06:47.332] [logger] [debug] [register.py:110] Interpreted arg 'As:=None' => 'As:object ()'
[2024-09-18 10:06:47.332] [logger] [debug] [register.py:426] Declared excel func: xloImport(ModuleName: str, From: object, As: object)
[2024-09-18 10:06:47.332] [logger] [debug] [register.py:110] Interpreted arg 'Object:' => 'Object:object ()'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:110] Interpreted arg 'Name:str' => 'Name:str ()'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:110] Interpreted arg '*Args' => 'Args:object (,vargs)'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:426] Declared excel func: xloAttr(Object: object, Name: str, Args: object, Kwargs)
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:110] Interpreted arg 'Object:' => 'Object:object ()'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:110] Interpreted arg 'Name:str' => 'Name:str ()'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:110] Interpreted arg '*Args' => 'Args:object (,vargs)'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:426] Declared excel func: xloAttrObj(Object: object, Name: str, Args: object, Kwargs) -> Cache
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:110] Interpreted arg 'Debugger:str=' => 'Debugger:str ()'
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:426] Declared excel func: xloPyDebug(Debugger: str)
[2024-09-18 10:06:47.333] [logger] [debug] [register.py:476] Found 4 xloil functions in <module 'xloil.excelfuncs' from 'D:\\workspace\\excel\\.venv\\Lib\\site-packages\\xloil\\excelfuncs.py'>
[2024-09-18 10:06:47.396] [logger] [debug] [Events.cpp:61] Started directory watch on 'D:\workspace\excel\.venv\Lib\site-packages\xloil\'
[2024-09-18 10:06:47.396] [logger] [debug] [PyFunctionRegister.cpp:545] Registered Python module 'D:\workspace\excel\.venv\Lib\site-packages\xloil\excelfuncs.py' with linked workbook 'none' for addin 'D:\workspace\excel\.venv\share\xloil\xlOil.dll'
[2024-09-18 10:06:47.396] [logger] [debug] [importer.py:219] Loaded python module 'xloil.excelfuncs' for addin 'D:\workspace\excel\.venv\share\xloil\xlOil.dll'
[2024-09-18 10:06:47.396] [logger] [debug] [PyEvents.cpp:360] Events enabled: Excel=true, xlOil=true
[2024-09-18 10:06:47.397] [logger] [debug] [PyEvents.cpp:360] Events enabled: Excel=true, xlOil=false
[2024-09-18 10:06:47.404] [logger] [debug] [Events.cpp:61] Started directory watch on 'D:\python312\Lib\'
[2024-09-18 10:06:47.404] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\copy.py added handler 0x23f5c2e4c00
[2024-09-18 10:06:47.407] [logger] [info] [PyEvents.cpp:117] Event D:\python312\Lib\dataclasses.py added handler 0x23f3f4301c0
[2024-09-18 10:06:47.411] [logger] [debug] [Thunker.cpp:104] Building thunk with 1 arguments
[2024-09-18 10:06:47.411] [logger] [debug] [DynamicRegistration.cpp:167] Hooking thunk for xloPyDebug
[2024-09-18 10:06:47.411] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloPyDebug" at entry point xloil_stub with 1 args
[2024-09-18 10:06:47.412] [logger] [debug] [Thunker.cpp:104] Building thunk with 3 arguments
[2024-09-18 10:06:47.412] [logger] [debug] [DynamicRegistration.cpp:167] Hooking thunk for xloImport
[2024-09-18 10:06:47.412] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloImport" at entry point xloil_stub with 3 args
[2024-09-18 10:06:47.412] [logger] [debug] [Thunker.cpp:104] Building thunk with 60 arguments
[2024-09-18 10:06:47.412] [logger] [debug] [DynamicRegistration.cpp:167] Hooking thunk for xloAttrObj
[2024-09-18 10:06:47.413] [logger] [debug] [FuncRegistry.cpp:229] Registering "xloAttrObj" at entry point xloil_stub with 60 args
[2024-09-18 10:06:47.413] [logger] [debug] [Thunker.cpp:104] Bu

@cunnane
Copy link
Owner

cunnane commented Sep 23, 2024

I've tried your code on Python 3.12 and it seems to be working bar a couple of things. Your log line in OnChanged should read xlo.log.info("HELLO"). You also don't need the wx_thread decorator where you have it as Wx will execute the callback on its thread.

@cunnane cunnane changed the title Trouble with Event Callbacks in TaskPane UI Trouble with Event Callbacks in Wx TaskPane Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants