Full Code of cunnane/xloil for AI

master 21c0f866351d cached
680 files
4.6 MB
1.2M tokens
2704 symbols
1 requests
Download .txt
Showing preview only (4,940K chars total). Download the full file or copy to clipboard to get everything.
Repository: cunnane/xloil
Branch: master
Commit: 21c0f866351d
Files: 680
Total size: 4.6 MB

Directory structure:
gitextract__p1idbhy/

├── .gitattributes
├── .gitignore
├── .readthedocs.yml
├── .runsettings
├── FUNDING.yml
├── LICENSE
├── README.md
├── Version.txt
├── config/
│   ├── xloil.ini
│   ├── xloil_local.ini
│   └── xloil_local_32.ini
├── docs/
│   ├── Excel Function Numbers.xlsx
│   ├── make.cmd
│   ├── requirements.txt
│   ├── source/
│   │   ├── Concepts.rst
│   │   ├── Core.rst
│   │   ├── Developer.rst
│   │   ├── Events.rst
│   │   ├── Introduction.rst
│   │   ├── conf.py
│   │   ├── index.rst
│   │   ├── xlOil_Core_Functions.rst
│   │   ├── xlOil_Cpp/
│   │   │   ├── COM.rst
│   │   │   ├── CppRtd.rst
│   │   │   ├── CustomGUI.rst
│   │   │   ├── DynamicRegistration.rst
│   │   │   ├── Events.rst
│   │   │   ├── GettingStarted.rst
│   │   │   ├── ObjectHandles.rst
│   │   │   ├── SpecialArgs.rst
│   │   │   ├── StaticXLLs.rst
│   │   │   └── index.rst
│   │   ├── xlOil_Python/
│   │   │   ├── BuiltInUDFs.rst
│   │   │   ├── Concepts.rst
│   │   │   ├── CustomGUI.rst
│   │   │   ├── Debugging.rst
│   │   │   ├── DistributingAddins.rst
│   │   │   ├── Dynamic.rst
│   │   │   ├── Example.rst
│   │   │   ├── ExampleGUI.rst
│   │   │   ├── ExampleRTD.rst
│   │   │   ├── ExcelApplication.rst
│   │   │   ├── ExternalPackages.rst
│   │   │   ├── FAQ.rst
│   │   │   ├── Functions.rst
│   │   │   ├── GettingStarted.rst
│   │   │   ├── Jupyter.rst
│   │   │   ├── ModuleReference.rst
│   │   │   ├── Rtd.rst
│   │   │   ├── TypeConversion.rst
│   │   │   └── index.rst
│   │   ├── xlOil_SQL/
│   │   │   └── index.rst
│   │   ├── xlOil_Utils.rst
│   │   └── xloil.doxyfile
│   └── xlOil-Sphinx.code-workspace
├── external/
│   ├── Excel2013SDK/
│   │   ├── INCLUDE/
│   │   │   └── XLCALL.H
│   │   ├── LIB/
│   │   │   ├── WIn32/
│   │   │   │   └── XLCALL32.LIB
│   │   │   └── x64/
│   │   │       └── XLCALL32.LIB
│   │   └── SRC/
│   │       ├── ReadMe.txt
│   │       └── XLCALL.CPP
│   ├── Sources.txt
│   └── boost-1.67/
│       └── boost/
│           └── preprocessor/
│               ├── arithmetic/
│               │   ├── add.hpp
│               │   ├── dec.hpp
│               │   ├── detail/
│               │   │   └── div_base.hpp
│               │   ├── div.hpp
│               │   ├── inc.hpp
│               │   ├── mod.hpp
│               │   ├── mul.hpp
│               │   └── sub.hpp
│               ├── arithmetic.hpp
│               ├── array/
│               │   ├── data.hpp
│               │   ├── detail/
│               │   │   └── get_data.hpp
│               │   ├── elem.hpp
│               │   ├── enum.hpp
│               │   ├── insert.hpp
│               │   ├── pop_back.hpp
│               │   ├── pop_front.hpp
│               │   ├── push_back.hpp
│               │   ├── push_front.hpp
│               │   ├── remove.hpp
│               │   ├── replace.hpp
│               │   ├── reverse.hpp
│               │   ├── size.hpp
│               │   ├── to_list.hpp
│               │   ├── to_seq.hpp
│               │   └── to_tuple.hpp
│               ├── array.hpp
│               ├── assert_msg.hpp
│               ├── cat.hpp
│               ├── comma.hpp
│               ├── comma_if.hpp
│               ├── comparison/
│               │   ├── equal.hpp
│               │   ├── greater.hpp
│               │   ├── greater_equal.hpp
│               │   ├── less.hpp
│               │   ├── less_equal.hpp
│               │   └── not_equal.hpp
│               ├── comparison.hpp
│               ├── config/
│               │   ├── config.hpp
│               │   └── limits.hpp
│               ├── control/
│               │   ├── deduce_d.hpp
│               │   ├── detail/
│               │   │   ├── dmc/
│               │   │   │   └── while.hpp
│               │   │   ├── edg/
│               │   │   │   └── while.hpp
│               │   │   ├── msvc/
│               │   │   │   └── while.hpp
│               │   │   └── while.hpp
│               │   ├── expr_if.hpp
│               │   ├── expr_iif.hpp
│               │   ├── if.hpp
│               │   ├── iif.hpp
│               │   └── while.hpp
│               ├── control.hpp
│               ├── debug/
│               │   ├── assert.hpp
│               │   ├── error.hpp
│               │   └── line.hpp
│               ├── debug.hpp
│               ├── dec.hpp
│               ├── detail/
│               │   ├── auto_rec.hpp
│               │   ├── check.hpp
│               │   ├── dmc/
│               │   │   └── auto_rec.hpp
│               │   ├── is_binary.hpp
│               │   ├── is_nullary.hpp
│               │   ├── is_unary.hpp
│               │   ├── null.hpp
│               │   └── split.hpp
│               ├── empty.hpp
│               ├── enum.hpp
│               ├── enum_params.hpp
│               ├── enum_params_with_a_default.hpp
│               ├── enum_params_with_defaults.hpp
│               ├── enum_shifted.hpp
│               ├── enum_shifted_params.hpp
│               ├── expand.hpp
│               ├── expr_if.hpp
│               ├── facilities/
│               │   ├── apply.hpp
│               │   ├── detail/
│               │   │   └── is_empty.hpp
│               │   ├── empty.hpp
│               │   ├── expand.hpp
│               │   ├── identity.hpp
│               │   ├── intercept.hpp
│               │   ├── is_1.hpp
│               │   ├── is_empty.hpp
│               │   ├── is_empty_or_1.hpp
│               │   ├── is_empty_variadic.hpp
│               │   └── overload.hpp
│               ├── facilities.hpp
│               ├── for.hpp
│               ├── identity.hpp
│               ├── if.hpp
│               ├── inc.hpp
│               ├── iterate.hpp
│               ├── iteration/
│               │   ├── detail/
│               │   │   ├── bounds/
│               │   │   │   ├── lower1.hpp
│               │   │   │   ├── lower2.hpp
│               │   │   │   ├── lower3.hpp
│               │   │   │   ├── lower4.hpp
│               │   │   │   ├── lower5.hpp
│               │   │   │   ├── upper1.hpp
│               │   │   │   ├── upper2.hpp
│               │   │   │   ├── upper3.hpp
│               │   │   │   ├── upper4.hpp
│               │   │   │   └── upper5.hpp
│               │   │   ├── finish.hpp
│               │   │   ├── iter/
│               │   │   │   ├── forward1.hpp
│               │   │   │   ├── forward2.hpp
│               │   │   │   ├── forward3.hpp
│               │   │   │   ├── forward4.hpp
│               │   │   │   ├── forward5.hpp
│               │   │   │   ├── reverse1.hpp
│               │   │   │   ├── reverse2.hpp
│               │   │   │   ├── reverse3.hpp
│               │   │   │   ├── reverse4.hpp
│               │   │   │   └── reverse5.hpp
│               │   │   ├── local.hpp
│               │   │   ├── rlocal.hpp
│               │   │   ├── self.hpp
│               │   │   └── start.hpp
│               │   ├── iterate.hpp
│               │   ├── local.hpp
│               │   └── self.hpp
│               ├── iteration.hpp
│               ├── library.hpp
│               ├── limits.hpp
│               ├── list/
│               │   ├── adt.hpp
│               │   ├── append.hpp
│               │   ├── at.hpp
│               │   ├── cat.hpp
│               │   ├── detail/
│               │   │   ├── dmc/
│               │   │   │   └── fold_left.hpp
│               │   │   ├── edg/
│               │   │   │   ├── fold_left.hpp
│               │   │   │   └── fold_right.hpp
│               │   │   ├── fold_left.hpp
│               │   │   └── fold_right.hpp
│               │   ├── enum.hpp
│               │   ├── filter.hpp
│               │   ├── first_n.hpp
│               │   ├── fold_left.hpp
│               │   ├── fold_right.hpp
│               │   ├── for_each.hpp
│               │   ├── for_each_i.hpp
│               │   ├── for_each_product.hpp
│               │   ├── rest_n.hpp
│               │   ├── reverse.hpp
│               │   ├── size.hpp
│               │   ├── to_array.hpp
│               │   ├── to_seq.hpp
│               │   ├── to_tuple.hpp
│               │   └── transform.hpp
│               ├── list.hpp
│               ├── logical/
│               │   ├── and.hpp
│               │   ├── bitand.hpp
│               │   ├── bitnor.hpp
│               │   ├── bitor.hpp
│               │   ├── bitxor.hpp
│               │   ├── bool.hpp
│               │   ├── compl.hpp
│               │   ├── nor.hpp
│               │   ├── not.hpp
│               │   ├── or.hpp
│               │   └── xor.hpp
│               ├── logical.hpp
│               ├── max.hpp
│               ├── min.hpp
│               ├── punctuation/
│               │   ├── comma.hpp
│               │   ├── comma_if.hpp
│               │   ├── detail/
│               │   │   └── is_begin_parens.hpp
│               │   ├── is_begin_parens.hpp
│               │   ├── paren.hpp
│               │   ├── paren_if.hpp
│               │   └── remove_parens.hpp
│               ├── punctuation.hpp
│               ├── repeat.hpp
│               ├── repeat_2nd.hpp
│               ├── repeat_3rd.hpp
│               ├── repeat_from_to.hpp
│               ├── repeat_from_to_2nd.hpp
│               ├── repeat_from_to_3rd.hpp
│               ├── repetition/
│               │   ├── deduce_r.hpp
│               │   ├── deduce_z.hpp
│               │   ├── detail/
│               │   │   ├── dmc/
│               │   │   │   └── for.hpp
│               │   │   ├── edg/
│               │   │   │   └── for.hpp
│               │   │   ├── for.hpp
│               │   │   └── msvc/
│               │   │       └── for.hpp
│               │   ├── enum.hpp
│               │   ├── enum_binary_params.hpp
│               │   ├── enum_params.hpp
│               │   ├── enum_params_with_a_default.hpp
│               │   ├── enum_params_with_defaults.hpp
│               │   ├── enum_shifted.hpp
│               │   ├── enum_shifted_binary_params.hpp
│               │   ├── enum_shifted_params.hpp
│               │   ├── enum_trailing.hpp
│               │   ├── enum_trailing_binary_params.hpp
│               │   ├── enum_trailing_params.hpp
│               │   ├── for.hpp
│               │   ├── repeat.hpp
│               │   └── repeat_from_to.hpp
│               ├── repetition.hpp
│               ├── selection/
│               │   ├── max.hpp
│               │   └── min.hpp
│               ├── selection.hpp
│               ├── seq/
│               │   ├── cat.hpp
│               │   ├── detail/
│               │   │   ├── binary_transform.hpp
│               │   │   ├── is_empty.hpp
│               │   │   ├── split.hpp
│               │   │   └── to_list_msvc.hpp
│               │   ├── elem.hpp
│               │   ├── enum.hpp
│               │   ├── filter.hpp
│               │   ├── first_n.hpp
│               │   ├── fold_left.hpp
│               │   ├── fold_right.hpp
│               │   ├── for_each.hpp
│               │   ├── for_each_i.hpp
│               │   ├── for_each_product.hpp
│               │   ├── insert.hpp
│               │   ├── pop_back.hpp
│               │   ├── pop_front.hpp
│               │   ├── push_back.hpp
│               │   ├── push_front.hpp
│               │   ├── remove.hpp
│               │   ├── replace.hpp
│               │   ├── rest_n.hpp
│               │   ├── reverse.hpp
│               │   ├── seq.hpp
│               │   ├── size.hpp
│               │   ├── subseq.hpp
│               │   ├── to_array.hpp
│               │   ├── to_list.hpp
│               │   ├── to_tuple.hpp
│               │   ├── transform.hpp
│               │   └── variadic_seq_to_seq.hpp
│               ├── seq.hpp
│               ├── slot/
│               │   ├── counter.hpp
│               │   ├── detail/
│               │   │   ├── counter.hpp
│               │   │   ├── def.hpp
│               │   │   ├── shared.hpp
│               │   │   ├── slot1.hpp
│               │   │   ├── slot2.hpp
│               │   │   ├── slot3.hpp
│               │   │   ├── slot4.hpp
│               │   │   └── slot5.hpp
│               │   └── slot.hpp
│               ├── slot.hpp
│               ├── stringize.hpp
│               ├── tuple/
│               │   ├── detail/
│               │   │   └── is_single_return.hpp
│               │   ├── eat.hpp
│               │   ├── elem.hpp
│               │   ├── enum.hpp
│               │   ├── insert.hpp
│               │   ├── pop_back.hpp
│               │   ├── pop_front.hpp
│               │   ├── push_back.hpp
│               │   ├── push_front.hpp
│               │   ├── rem.hpp
│               │   ├── remove.hpp
│               │   ├── replace.hpp
│               │   ├── reverse.hpp
│               │   ├── size.hpp
│               │   ├── to_array.hpp
│               │   ├── to_list.hpp
│               │   └── to_seq.hpp
│               ├── tuple.hpp
│               ├── variadic/
│               │   ├── detail/
│               │   │   └── is_single_return.hpp
│               │   ├── elem.hpp
│               │   ├── size.hpp
│               │   ├── to_array.hpp
│               │   ├── to_list.hpp
│               │   ├── to_seq.hpp
│               │   └── to_tuple.hpp
│               ├── variadic.hpp
│               ├── while.hpp
│               └── wstringize.hpp
├── include/
│   └── xloil/
│       ├── AppObjects.h
│       ├── ArrayBuilder.h
│       ├── Async.h
│       ├── AutoBind.h
│       ├── Caller.h
│       ├── Date.h
│       ├── DynamicRegister.h
│       ├── EnumHelper.h
│       ├── Events.h
│       ├── ExcelArray.h
│       ├── ExcelCall.h
│       ├── ExcelObj.h
│       ├── ExcelObjCache.h
│       ├── ExcelRef.h
│       ├── ExcelThread.h
│       ├── ExcelTypeLib.h
│       ├── ExcelUI.h
│       ├── ExportMacro.h
│       ├── FPArray.h
│       ├── FuncSpec.h
│       ├── Interface.h
│       ├── Limits.h
│       ├── Log.h
│       ├── LogWindow.h
│       ├── NumericTypeConverters.h
│       ├── ObjectCache.h
│       ├── PString.h
│       ├── Plugin.h
│       ├── Preprocessor.h
│       ├── Range.h
│       ├── Register.h
│       ├── RtdServer.h
│       ├── State.h
│       ├── StaticRegister.h
│       ├── StringUtils.h
│       ├── Throw.h
│       ├── TypeConverters.h
│       ├── Version.h
│       ├── WindowsSlim.h
│       ├── XlCallSlim.h
│       ├── XllEntryPoint.h
│       └── xlOil.h
├── libs/
│   ├── SetRoot.props
│   ├── xlOilPlugin.props
│   ├── xlOilStaticLib.props
│   ├── xlOil_Python/
│   │   ├── ArrayHelpers.h
│   │   ├── AsyncFunctions.cpp
│   │   ├── AsyncFunctions.h
│   │   ├── CPython.h
│   │   ├── EventLoop.cpp
│   │   ├── EventLoop.h
│   │   ├── Loader/
│   │   │   ├── StubLoader.cpp
│   │   │   └── xlOil_Python.vcxproj
│   │   ├── Main.cpp
│   │   ├── Package/
│   │   │   ├── TestConfig.py
│   │   │   ├── generate_stubs.py
│   │   │   ├── setup.py
│   │   │   ├── test_JupyterConnection.py
│   │   │   ├── test_PythonAutomation.py
│   │   │   ├── test_SpreadsheetRunner.py
│   │   │   ├── xlOil_Python_Package.pyproj
│   │   │   └── xloil/
│   │   │       ├── __init__.py
│   │   │       ├── _core.py
│   │   │       ├── _event_loop.py
│   │   │       ├── _paths.py
│   │   │       ├── _pyinstaller/
│   │   │       │   ├── __init__.py
│   │   │       │   └── hook-xloil.py
│   │   │       ├── _superreload.py
│   │   │       ├── com.py
│   │   │       ├── command_line.py
│   │   │       ├── debug.py
│   │   │       ├── excelfuncs.py
│   │   │       ├── func_inspect.py
│   │   │       ├── gui/
│   │   │       │   ├── __init__.py
│   │   │       │   ├── qt_console.py
│   │   │       │   ├── qtpy.py
│   │   │       │   ├── tk_console.py
│   │   │       │   ├── tkinter.py
│   │   │       │   └── wx.py
│   │   │       ├── importer.py
│   │   │       ├── jupyter.py
│   │   │       ├── jupyter_kernel.py
│   │   │       ├── logging.py
│   │   │       ├── matplotlib.py
│   │   │       ├── pandas.py
│   │   │       ├── pillow.py
│   │   │       ├── register.py
│   │   │       ├── rtd.py
│   │   │       ├── stubs/
│   │   │       │   ├── __init__.py
│   │   │       │   └── xloil_core/
│   │   │       │       ├── __init__.py
│   │   │       │       └── event/
│   │   │       │           └── __init__.py
│   │   │       ├── type_converters.py
│   │   │       └── xloil_ribbon.py
│   │   ├── PyAddin.cpp
│   │   ├── PyAddin.h
│   │   ├── PyAddress.cpp
│   │   ├── PyAddress.h
│   │   ├── PyAppCallRun.cpp
│   │   ├── PyAppCallRun.h
│   │   ├── PyAppObjects.cpp
│   │   ├── PyCOM.cpp
│   │   ├── PyCOM.h
│   │   ├── PyCache.cpp
│   │   ├── PyCache.h
│   │   ├── PyCore.cpp
│   │   ├── PyCore.h
│   │   ├── PyEvents.cpp
│   │   ├── PyEvents.h
│   │   ├── PyFunctionRegister.cpp
│   │   ├── PyFunctionRegister.h
│   │   ├── PyFuture.h
│   │   ├── PyHelpers.cpp
│   │   ├── PyHelpers.h
│   │   ├── PyImage.cpp
│   │   ├── PyImage.h
│   │   ├── PyLogWriter.cpp
│   │   ├── PyObjectGC.cpp
│   │   ├── PyRibbon.cpp
│   │   ├── PyRtd.cpp
│   │   ├── PyRtd.h
│   │   ├── PyRunLater.cpp
│   │   ├── PySettings.props
│   │   ├── PySettings310.props
│   │   ├── PySettings311.props
│   │   ├── PySettings312.props
│   │   ├── PySettings313.props
│   │   ├── PySettings314.props
│   │   ├── PySettings36.props
│   │   ├── PySettings37.props
│   │   ├── PySettings38.props
│   │   ├── PySettings39.props
│   │   ├── PySource.cpp
│   │   ├── PySource.h
│   │   ├── PyStatusBar.cpp
│   │   ├── TypeConversion/
│   │   │   ├── BasicTypes.cpp
│   │   │   ├── BasicTypes.h
│   │   │   ├── ConverterInterface.h
│   │   │   ├── Numpy.h
│   │   │   ├── NumpyDatetime.cpp
│   │   │   ├── NumpyDatetime.h
│   │   │   ├── NumpyFromExcel.cpp
│   │   │   ├── NumpyHelpers.cpp
│   │   │   ├── NumpyHelpers.h
│   │   │   ├── NumpyPandas.cpp
│   │   │   ├── NumpyToExcel.cpp
│   │   │   ├── PyCustomType.cpp
│   │   │   ├── PyDateType.cpp
│   │   │   ├── PyDateType.h
│   │   │   ├── PyDictType.cpp
│   │   │   ├── PyDictType.h
│   │   │   ├── PyExcelArrayType.cpp
│   │   │   ├── PyExcelArrayType.h
│   │   │   ├── PyRangeType.cpp
│   │   │   ├── PyTupleType.cpp
│   │   │   └── PyTupleType.h
│   │   ├── xlOil_Python310.vcxproj
│   │   ├── xlOil_Python311.vcxproj
│   │   ├── xlOil_Python312.vcxproj
│   │   ├── xlOil_Python313.vcxproj
│   │   ├── xlOil_Python314.vcxproj
│   │   ├── xlOil_Python36.vcxproj
│   │   ├── xlOil_Python37.vcxproj
│   │   ├── xlOil_Python38.vcxproj
│   │   ├── xlOil_Python39.vcxproj
│   │   └── xlOil_Python39.vcxproj.filters
│   ├── xlOil_SQL/
│   │   ├── Cache.cpp
│   │   ├── Cache.h
│   │   ├── Common.cpp
│   │   ├── Common.h
│   │   ├── Main.cpp
│   │   ├── XlArrayTable.cpp
│   │   ├── XlArrayTable.h
│   │   ├── xlOil_SQL.vcxproj
│   │   ├── xlOil_SQL.vcxproj.filters
│   │   ├── xloSql.cpp
│   │   ├── xloSqlDB.cpp
│   │   ├── xloSqlQuery.cpp
│   │   ├── xloSqlTable.cpp
│   │   └── xloSqlTables.cpp
│   └── xlOil_Utils/
│       ├── Main.cpp
│       ├── RegexHelpers.h
│       ├── xlOil_Utils.vcxproj
│       ├── xloBlock.cpp
│       ├── xloConcat.cpp
│       ├── xloFill.cpp
│       ├── xloFillNA.cpp
│       ├── xloIndex.cpp
│       ├── xloPad.cpp
│       ├── xloRegex.cpp
│       ├── xloSearch.cpp
│       ├── xloSort.cpp
│       └── xloSplit.cpp
├── src/
│   ├── BuildPaths.props
│   ├── Common.props
│   ├── Debug.props
│   ├── Release.props
│   ├── external/
│   │   ├── asmjit.vcxproj
│   │   ├── rdcfswatcher.vcxproj
│   │   └── spdlog.vcxproj
│   ├── xlOil/
│   │   ├── Interface.cpp
│   │   ├── Loaders/
│   │   │   ├── AddinLoader.cpp
│   │   │   ├── AddinLoader.h
│   │   │   ├── CoreEntryPoint.cpp
│   │   │   ├── CoreEntryPoint.h
│   │   │   ├── PluginLoader.cpp
│   │   │   └── PluginLoader.h
│   │   ├── Log.cpp
│   │   ├── xlOil.vcxproj
│   │   └── xlOil.vcxproj.filters
│   ├── xlOil-COM/
│   │   ├── API/
│   │   │   ├── ComUtils.cpp
│   │   │   ├── Events.cpp
│   │   │   ├── ExcelRange.cpp
│   │   │   ├── ExcelThread.cpp
│   │   │   └── RtdServer.cpp
│   │   ├── AppObjects.cpp
│   │   ├── ClassFactory.cpp
│   │   ├── ClassFactory.h
│   │   ├── ComAddin.cpp
│   │   ├── ComAddin.h
│   │   ├── ComEventSink.cpp
│   │   ├── ComEventSink.h
│   │   ├── ComVariant.cpp
│   │   ├── ComVariant.h
│   │   ├── Connect.cpp
│   │   ├── Connect.h
│   │   ├── CustomTaskPane.cpp
│   │   ├── CustomTaskPane.h
│   │   ├── RibbonExtensibility.cpp
│   │   ├── RibbonExtensibility.h
│   │   ├── RtdAsyncManager.cpp
│   │   ├── RtdAsyncManager.h
│   │   ├── RtdManager.cpp
│   │   ├── RtdManager.h
│   │   ├── RtdServerWorker.h
│   │   ├── TaskPaneHostControl.cpp
│   │   ├── TaskPaneHostControl.h
│   │   ├── WorkbookScopeFunctions.cpp
│   │   ├── WorkbookScopeFunctions.h
│   │   ├── XllContextInvoke.cpp
│   │   ├── XllContextInvoke.h
│   │   ├── xlOil-COM.vcxproj
│   │   └── xlOil-COM.vcxproj.filters
│   ├── xlOil-Dynamic/
│   │   ├── DynamicRegistration.cpp
│   │   ├── ExternalRegionAllocator.h
│   │   ├── LocalFunctions.cpp
│   │   ├── LocalFunctions.h
│   │   ├── PEHelper.cpp
│   │   ├── PEHelper.h
│   │   ├── Thunker.cpp
│   │   ├── Thunker.h
│   │   ├── xlOil-Dynamic.vcxproj
│   │   └── xlOil-Dynamic.vcxproj.filters
│   ├── xlOil-Funcs/
│   │   ├── ExcelObjCache.cpp
│   │   ├── xlOil-Funcs.vcxproj
│   │   ├── xlOil-Funcs.vcxproj.filters
│   │   ├── xloHelp.cpp
│   │   ├── xloLog.cpp
│   │   ├── xloReload.cpp
│   │   └── xloVersion.cpp
│   ├── xlOil-Loader/
│   │   ├── LoaderEntryPoint.cpp
│   │   ├── xlOil-Loader.vcxproj
│   │   └── xlOilAddin.def
│   ├── xlOil-XLL/
│   │   ├── ArrayBuilder.cpp
│   │   ├── Async.cpp
│   │   ├── Caller.cpp
│   │   ├── Date.cpp
│   │   ├── ExcelArray.cpp
│   │   ├── ExcelCall.cpp
│   │   ├── ExcelCallMapping.h
│   │   ├── ExcelObj.cpp
│   │   ├── ExcelRef.cpp
│   │   ├── FPArray.cpp
│   │   ├── FuncRegistry.cpp
│   │   ├── FuncRegistry.h
│   │   ├── Intellisense.cpp
│   │   ├── Intellisense.h
│   │   ├── Log.cpp
│   │   ├── LogWindow.cpp
│   │   ├── LogWindowSink.cpp
│   │   ├── LogWindowSink.h
│   │   ├── State.cpp
│   │   ├── StaticRegister.cpp
│   │   ├── Throw.cpp
│   │   ├── XlCall.cpp
│   │   ├── XllEvents.cpp
│   │   ├── xlOil-XLL.vcxproj
│   │   └── xlOil-XLL.vcxproj.filters
│   └── xlOilHelpers/
│       ├── Environment.cpp
│       ├── Environment.h
│       ├── Exception.h
│       ├── GuidUtils.cpp
│       ├── GuidUtils.h
│       ├── Settings.cpp
│       ├── Settings.h
│       ├── Utils.h
│       └── xlOilHelpers.vcxproj
├── tests/
│   ├── AutoSheets/
│   │   ├── PythonTest.py
│   │   ├── PythonTest.xlsx
│   │   ├── TestModule.py
│   │   ├── TestSQL.xlsx
│   │   ├── TestUtils.ipynb
│   │   └── TestUtils.xlsx
│   ├── CodePageConversion.cpp
│   ├── Date.cpp
│   ├── Environment.cpp
│   ├── ManualSheets/
│   │   ├── python/
│   │   │   ├── PySpeedTest.py
│   │   │   ├── PySpeedTest.xlsm
│   │   │   ├── PythonRTDTest.py
│   │   │   ├── PythonRTDTest.xlsx
│   │   │   ├── PythonTestAsync.py
│   │   │   ├── PythonTestAsync.xlsm
│   │   │   ├── PythonTestUI.py
│   │   │   ├── PythonTestUI.xlsm
│   │   │   ├── TestJupyter.xlsx
│   │   │   └── TestJupyterConnection.ipynb
│   │   └── rtd/
│   │       └── RtdTest.xlsx
│   ├── PString.cpp
│   ├── TestAddin/
│   │   ├── AutoBind.cpp
│   │   ├── CacheTest.cpp
│   │   ├── CacheTest2.cpp
│   │   ├── CallbackTest.cpp
│   │   ├── ExoticArgTest.cpp
│   │   ├── Main.cpp
│   │   ├── RtdServerTest.cpp
│   │   ├── TestAddin.vcxproj
│   │   ├── TestAddin.vcxproj.filters
│   │   └── TestTestAddin.xlsx
│   ├── TestArrayBuilder.cpp
│   ├── TestCOM.cpp
│   ├── TestCache.cpp
│   ├── TestExcelCall.cpp
│   ├── TestExcelObj.cpp
│   ├── TestGuid.cpp
│   ├── TestRange.cpp
│   ├── TestSimpleAllocator.cpp
│   ├── TestStringUtils.cpp
│   ├── TestTempFile.cpp
│   ├── TestThunker.cpp
│   ├── Tests.vcxproj
│   └── Tests.vcxproj.filters
├── tools/
│   ├── BuildRelease.cmd
│   ├── DownloadDependencies.cmd
│   ├── WriteInclude.ps1
│   ├── WriteVersion.ps1
│   ├── stage.py
│   ├── xlOil_Install.ps1
│   ├── xlOil_NewAddin.ps1
│   ├── xlOil_RegistryClean.ps1
│   └── xlOil_Remove.ps1
└── xlOil.sln

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto


================================================
FILE: .gitignore
================================================
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a

# Executables
*.out
*.app

# Visual studio stuff
.vs
build/
packages/
graveyard/
*.vcxproj.user
.vscode

# Other caches
__pycache__
.ipynb_checkpoints

# External libraries
/external/python/
/external/sqlite
/external/pybind11-stubgen
/external/CTPL
/external/tomlplusplus
/external/spdlog
/external/pybind11
/external/rdcfswatcher
/external/asmjit
/external/winreg
/docs/source/_build

~$*

================================================
FILE: .readthedocs.yml
================================================
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Build documentation in the docs/ directory with Sphinx
sphinx:
  configuration: docs/source/conf.py

build:
  os: "ubuntu-22.04"
  tools:
    python: "3.11"
    
python:
  install:
    - requirements: docs/requirements.txt

================================================
FILE: .runsettings
================================================
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
    <RunConfiguration>
        <EnvironmentVariables>
            <XLOIL_TEST_BIN_DIR>build/x64/Debug</XLOIL_TEST_BIN_DIR>
        </EnvironmentVariables>
    </RunConfiguration>
</RunSettings>


================================================
FILE: FUNDING.yml
================================================
github: [cunnane]

================================================
FILE: LICENSE
================================================
Apache License

   Copyright 2020 Steven Cunnane

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================

xlOil
=====

xlOil provides framework for interacting with Excel in different programming
languages. It gives a way to write functions in a language and have them 
appear in Excel as worksheet functions or macros or have them control GUI elements. 
For example, the Python bindings can replace VBA in almost all use cases 
and even provide functionality not available from VBA.

xlOil is designed to have very low overheads when calling your worksheet 
functions.

xlOil supports different languages via plugins. The languages currently 
supported are:

- C++
- Python
- SQL

In addition there is *xlOil_Utils* which contains some handy tools which Microsoft
never quite got around to adding.

The latest stable documentation is here: https://xloil.readthedocs.io/en/stable.

xlOil features
--------------

* Python
  - Concise syntax to declare an Excel function
  - Optional type checking of function parameters
  - Supports keyword arguments
  - Choice of globally declared functions or code modules limited to a single workbook
    like VBA workbook-level functions
  - Tight integration with *numpy* - very low overheads for array functions
  - Understands python tuples, lists, dictionarys and *pandas* dataframes
  - Async functions
  - RTD functions and on-the-fly RTD server creation
  - Macro type functions which write to ranges on the sheet
  - Access to the Excel Application object and the full Excel object model
  - Drive Excel through COM automation
  - Hook Excel events
  - Pass any python object back to Excel and back into another function
  - Simple add-in deployment
  - Two-way connection to *Jupyter* notebooks: run worksheet functions in *Jupyter* and query variables
    in the *jupyter* kernel
  - Create Ribbon toolbars and Custom Task Panes
  - Return *matplotlib* plots and images from worksheet functions
* C++
  - Safe and convenient wrappers around most things in the C-API
  - Concise syntax to declare Excel functions: registration is automatic
  - Deal with Excel variants, Ranges, Arrays and strings in a natural C++ fashion
  - Object cache allows returning opaque objects to Excel and passing them back to other functions
  - Simplified RTD server creation
  - RTD-based background calculation
  - Create Ribbon toolbars and Custom Task Panes  
* SQL
  - Create tables from Excel ranges and arrays
  - Query and join them with the full sqlite3 SQL syntax
* Utils: very fast functions to:
  - Sort on multiple columns
  - Split and join strings
  - Make arrays from blocks


Supporting other languages
--------------------------

You can use xlOil as an end-user of these plugins or you can use it to write
you own language bindings (and ideally add them to the repo).

================================================
FILE: Version.txt
================================================
0.22.1


================================================
FILE: config/xloil.ini
================================================
#
######## xlOil Settings #########
#
# This is a TOML file.
#
#################################
#
[Addin]

##### Plugins to load
#
# Load these plugins. The directory containing xloil.dll is searched
# first, then the normal DLL search path order.
#
Plugins=["xlOil_Python", "xlOil_SQL", "xlOil_Utils"]

#
# Load any plugins in the same directory as the core dll which 
# match this pattern.
#
#PluginSearchPattern="xloil_*.dll"


##### Log file settings 
#
# Intensity of logging, choose from:
# "trace", "debug", "info", "warning", "error", "critical", "off"
#
LogLevel="warning"

#
# Level at which xlOil will pop up a log window to display recent 
# log entries
#
LogPopupLevel="error"

#
# Level at which xlOil will flush the log file to disk, lower levels
# decrease performance but can be useful for debugging crashes
#
#LogFlushLevel="warning"

#
# The log file is created at <name-of-ini-file>.log and in the same 
# directory unless specified below
#
#LogFile="my.log"

#
# Log file rotation is controlled by these two parameters. A single
# log file can grow to the *LogMaxSize* in Kb. Once this limit is
# reached, a new blank log file is started, existing old log files
# are renamed and the oldest is deleted to ensure maximum of 
# *LogNumberOfFiles* files.
# 
#LogMaxSize=512
#LogNumberOfFiles=2

# If you have an ini file at %APPDATA%\xlOil\xlOil.ini, the core xlOil.dll
# is loaded using those settings before any other xlOil-based XLL. Since only one 
# instance of xlOil can be hosted in Excel, one settings file must take precedence. 
# The assumption is that if you have xlOil installed, you want those settings to 
# be the primary ones.  The below option, when used in a XLL-specific ini file,
# allows it to be loaded before the core.
# LoadBeforeCore=False

##### Date
#
# The date formats xlOil will attempt to parse for a string to date
# conversion. Syntax follows C++ get_time here: 
# https://en.cppreference.com/w/cpp/io/manip/get_time
# Note the date parsing is case sensitive because get_time is case 
# sensitive on Windows.
#
DateFormats=["%Y-%m-%d", "%Y%b%d"]

# 
# The key XLOIL_PATH is edited by the xlOil_Install powershell script
# Note: Use [[]] syntax because the order of Environment variables matters
#
[[Addin.Environment]]
XLOIL_PATH=""
[[Addin.Environment]]
PATH='''%PATH%;%XLOIL_PATH%'''


##### Python Plugin Settings
#
[xlOil_Python]
#
# Python modules to load on start up. Must be on python's sys.path.
# xlOil provides the following optional modules:
#   * xloil.xloil_ribbon: adds a ribbon toolbar with some useful functions
#   * xloil.jupyter: adds jupyter interaction
#
LoadModules=["xloil.xloil_ribbon"]

#
# On workbook open, look for a python file matching this template 
# where * is replaced by the Excel workbook name
#
WorkbookModule="*.py"

#
# Look for a module matching this pattern in the directory of the 
# XLL when it is loaded where '*' is replaced with the addin name.
# The default is "*.py" which means an ini file is optional for a 
# simple addin
#
#AddinModule="*.py"

#
# Calls Py_SetPath before initialising python. This allows explict
# specification of python's sys.path rather than using the usual
# search routine, which overrides any setting of PYTHONPATH.
# Generally this option is not required.
#
#SetSysPath='''.'''

#
# Sets the library for COM support. This is used by the `xloil.app` 
# and `to_com` functions although can be override on a per-call basis.
# The default is 'win32com', 'comtypes' is also available. 
#
#ComLib="comtypes"

#
# Selects the debugger to use. The choices are:
#   * Visual Studio 2019+ : no need to pre-select this, just attach to 
#     a running Excel process
#   * VS Code: choose `vscode` or `debugpy`. The `DebugPyPort` attribute
#     then determines the port on which the server listens.
#   * Pdb: choose 'pdb'
#
Debugger = ""

#
# Determines the port on which the server listens.
# 
DebugPyPort = "5678"

#
# By default xlOil loads python modules in a background thread when the addin
# starts up or a local worksheet module is loaded. This avoids blocking the 
# UI but can lead to #NAME! errors if the a workbook is calculated before
# the relevant functions are registered. Set UseLoaderThread to false to 
# disable background loading
# 
#UseLoaderThread=false


#
# When error propagation is enabled, if any function argument is an error code 
# (#N/A!, #NUM!, etc.) that error code is given as the function's return value,
# otherwise all argument values are handled by the function. Error propagation 
# is consistent with how Excel built-in functions handle errors, it improves 
# performance in the presence of error codes and it allow's Excel's error tracing
# to function.
#
# Currently this setting is respected only by the xlOil_Python plugin.
#
#ErrorPropagation=false


#
# List of path prefixes which will be ignored for autoreloading on file 
# modification detection.
#
#AutoReloadExcludePaths = []


##### Python Environment
#
# We need to set the python environment paths. Usually this is done automatically 
# by `xloil install` or `xloil create` or the ribbon.
#
# Usually just set PYTHONEXECUTABLE - python should be able to figure out the rest.
# xlOil also uses this variable to help detect the presence of a virtual Environment. 
# Alternatively set the PYTHONPATH, PYTHONHOME and PATH directly as required by your
# distribution.
#
# Note environment vars can be set by dynamically expanding a registry key.
#
[[xlOil_Python.Environment]]
	#
	# Tells python to do case-insensitve module name lookup and so minimises 
	# surprises on windows when creating workbook and addin modules. Recommended!
	#
    PYTHONCASEOK="1"

	#
	# If this environment variable is set, xlOil tries to load the corresponding
	# pythonXY.dll as the interpreter. If unset or blank, xlOil uses the first python 
	# version discovered using the paths set below.
	# 
	XLOIL_PYTHON_VERSION=""

	#
	# Additional paths to add to python's sys.path. Prefer to add user search
	# paths here and reserve the PYTHONPATH setting below for system paths. 
	# (We make the empty value a semi-colon so that the variable exists 
	# for the environment variable expansion below)
	XLOIL_PYTHON_PATH=";"

[[xlOil_Python.Environment]]
	
	#
	# PYTHONEXECUTABLE should point to the python.exe of the current environment.
	# Note it is possible to dynamically expand registry keys contained in angle 
	# brackets <>.
	#
	PYTHONEXECUTABLE='''<HKLM\SOFTWARE\Python\ContinuumAnalytics\Anaconda39-64\InstallPath\ExecutablePath>'''
	
	PYTHONPATH='''%PYTHONPATH%;%XLOIL_PYTHON_PATH%'''

================================================
FILE: config/xloil_local.ini
================================================
#
######## xlOil Dev Settings ###########################################
#
# This is a version of xlOil.ini which is copied to the build directory
# when xloil.xll is built. Its purpose is to configure dev settings 
# without accidentally overwriting the distriuted xloil.ini file
#
#######################################################################
#
[Addin]

##### Plugins to load
#
# Load these plugins. The directory containing xloil.dll is searched
# first, then the normal DLL search path order.
#
Plugins=["xlOil_Python", "xlOil_SQL", "xlOil_Utils"]

##### Log file settings 
#
# Intensity of logging, choose from:
# "trace", "debug", "info", "warning", "error", "critical", "off"
#
LogLevel="trace"

#
# Level at which xlOil will pop up a log window to display recent 
# log entries
#
LogPopupLevel="error"

#
# Level at which xlOil will flush the log file to disk, lower levels
# decrease performance but can be useful for debugging crashes
#
#LogFlushLevel="warning"


#
# The log file is created at <name-of-ini-file>.log and in the same 
# directory unless specified below
#
#LogFile="my.log"

#
# Log file rotation is controlled by these two parameters. A single
# log file can grow to the *LogMaxSize* in Kb. Once this limit is
# reached, a new blank log file is started, existing old log files
# are renamed and the oldest is deleted to ensure maximum of 
# *LogNumberOfFiles* files.
# 
#LogMaxSize=512
#LogNumberOfFiles=2


# If you have an ini file at %APPDATA%\xlOil\xlOil.ini, the core xlOil.dll
# is loaded using those settings before any other xlOil-based XLL. The assumption
# is that you have xlOil installed, but since only one instance of xlOil 
# can be hosted in Excel, one settings file must take precedence. The below option
# allows an XLL to be loaded before the core.
# LoadBeforeCore=false

##### Date
#
# The date formats xlOil will attempt to parse for a string to date
# conversion. Syntax follows C++ get_time here: 
# https://en.cppreference.com/w/cpp/io/manip/get_time
# Note the date parsing is case sensitive because get_time is case 
# sensitive on Windows.
#
DateFormats=["%Y-%m-%d", "%Y%b%d"]

# 
# The key XLOIL_PATH is edited by the xlOil_Install powershell script
# Note: Use [[]] syntax because the order of Environment variables matters
#
#[[Addin.Environment]]
#XLOIL_PATH=""
#[[Addin.Environment]]
#PATH='''%PATH%;%XLOIL_PATH%'''


##### Python Plugin Settings
#
[xlOil_Python]
#
# Python modules to load on start up. Must be on python's sys.path
#
LoadModules=["xloil.xloil_ribbon"]

#
# On workbook open, look for a python file matching this template 
# where * is replaced by the Excel workbook name
#
WorkbookModule="*.py"

#
# Look for a module matching this pattern in the directory of the 
# XLL when it is loaded where '*' is replaced with the addin name.
# The default is "*.py" which means an ini file is optional for a 
# simple addin
#
#AddinModule="*.py"

#
# Calls Py_SetPath before initialising python. This allows explict
# specification of python's sys.path rather than using the usual
# search routine, which overrides any setting of PYTHONPATH.
# Generally this option is not required.
#
#SetSysPath='''.'''

#
# Sets the library for COM support. This is used by the `xloil.app` 
# and `to_com` functions although can be override on a per-call basis.
# The default is 'win32com', 'comtypes' is also available. 
#
#ComLib="comtypes"

#
# Selects the debugger to use. The choices are:
#   * Visual Studio 2019+ : no need to pre-select this, just attach to 
#     a running Excel process
#   * VS Code: choose `vscode` or `debugpy`. The `DebugPyPort` attribute
#     then determines the port on which the server listens.
#   * Pdb: choose 'pdb'
#
Debugger = ""

#
# Determines the port on which the server listens.
# 
DebugPyPort = "5678"

#UseLoaderThread=false

ErrorPropagation=false


##### Python Environment
#
# We need to set the python environment paths. Usually this is done automatically 
# by `xloil install` or `xloil create` or the ribbon.
#
# Usually just set PYTHONEXECUTABLE - python should be able to figure out the rest.
# xlOil also uses this variable to help detect the presence of a virtual Environment. 
# Alternatively set the PYTHONPATH, PYTHONHOME and PATH directly as required by your
# distribution.
#
# Note environment vars can be set by dynamically expanding a registry key.
#
[xlOil_Python.Environment]
    
	PYTHONCASEOK="1"

	#
	# If this environment variable is set, xlOil tries to load the corresponding
	# pythonXY.dll as the interpreter. If unset or blank, xlOil uses the reported
	# python version of the interpreter in the first python dist found.
	# 
	XLOIL_PYTHON_VERSION=""

    #
	# PYTHONEXECUTABLE should point to the python.exe of the current environment.
	# Note it is possible to dynamically expand registry keys contained in angle 
	# brackets <>.
	#
	PYTHONEXECUTABLE='''D:\lib\conda311\python.exe'''
	#PYTHONEXECUTABLE='''<HKLM\SOFTWARE\Python\PythonCore\3.6\InstallPath\ExecutablePath>'''
	
	XLOIL_PYTHON_PATH='''D:\lib'''

	PYTHONPATH='''%PYTHONPATH%;D:\lib'''


================================================
FILE: config/xloil_local_32.ini
================================================
#
######## xlOil Dev Settings ###########################################
#
# This is a version of xlOil.ini which is copied to the build directory
# when xloil.xll is built. Its purpose is to configure dev settings 
# without accidentally overwriting the distriuted xloil.ini file
#
#######################################################################
#
[Addin]

##### Plugins to load
#
# Load these plugins. The directory containing xloil.dll is searched
# first, then the normal DLL search path order.
#
Plugins=["xlOil_Python", "xlOil_SQL", "xlOil_Utils"]

##### Log file settings 
#
# Intensity of logging, choose from:
# "trace", "debug", "info", "warning", "error", "critical", "off"
#
LogLevel="trace"

#
# Level at which xlOil will pop up a log window to display recent 
# log entries
#
LogPopupLevel="error"

#
# The log file is created at <name-of-ini-file>.log and in the same 
# directory unless specified below
#
#LogFile="my.log"

#
# Log file rotation is controlled by these two parameters. A single
# log file can grow to the *LogMaxSize* in Kb. Once this limit is
# reached, a new blank log file is started, existing old log files
# are renamed and the oldest is deleted to ensure maximum of 
# *LogNumberOfFiles* files.
# 
#LogMaxSize=512
#LogNumberOfFiles=2


# If you have an ini file at %APPDATA%\xlOil\xlOil.ini, the core xlOil.dll
# is loaded using those settings before any other xlOil-based XLL. The assumption
# is that you have xlOil installed, but since only one instance of xlOil 
# can be hosted in Excel, one settings file must take precedence. The below option
# allows an XLL to be loaded before the core.
# LoadBeforeCore=false

##### Date
#
# The date formats xlOil will attempt to parse for a string to date
# conversion. Syntax follows C++ get_time here: 
# https://en.cppreference.com/w/cpp/io/manip/get_time
# Note the date parsing is case sensitive because get_time is case 
# sensitive on Windows.
#
DateFormats=["%Y-%m-%d", "%Y%b%d"]

# 
# The key XLOIL_PATH is edited by the xlOil_Install powershell script
# Note: Use [[]] syntax because the order of Environment variables matters
#
#[[Addin.Environment]]
#XLOIL_PATH=""
#[[Addin.Environment]]
#PATH='''%PATH%;%XLOIL_PATH%'''


##### Python Plugin Settings
#
[xlOil_Python]
#
# Python modules to load on start up. Must be on python's sys.path
#
LoadModules=["xloil.xloil_ribbon", "excelfunc"]

#
# On workbook open, look for a python file matching this template 
# where * is replaced by the Excel workbook name
#
WorkbookModule="*.py"

#
# Look for a module matching this pattern in the directory of the 
# XLL when it is loaded where '*' is replaced with the addin name.
# The default is "*.py" which means an ini file is optional for a 
# simple addin
#
#AddinModule="*.py"

#
# Calls Py_SetPath before initialising python. This allows explict
# specification of python's sys.path rather than using the usual
# search routine, which overrides any setting of PYTHONPATH.
# Generally this option is not required.
#
#SetSysPath='''.'''

#
# Sets the library for COM support. This is used by the `xloil.app` 
# and `to_com` functions although can be override on a per-call basis.
# The default is 'win32com', 'comtypes' is also available. 
#
#ComLib="comtypes"

#
# Selects the debugger to use. The choices are:
#   * Visual Studio 2019+ : no need to pre-select this, just attach to 
#     a running Excel process
#   * VS Code: choose `vscode` or `debugpy`. The `DebugPyPort` attribute
#     then determines the port on which the server listens.
#   * Pdb: choose 'pdb'
#
Debugger = ""

#
# Determines the port on which the server listens.
# 
DebugPyPort = "5678"

#UseLoaderThread=false

##### Python Environment
#
# We need to set the python environment paths. Usually this is done automatically 
# by `xloil install` or `xloil create` or the ribbon.
#
# Usually just set PYTHONEXECUTABLE - python should be able to figure out the rest.
# xlOil also uses this variable to help detect the presence of a virtual Environment. 
# Alternatively set the PYTHONPATH, PYTHONHOME and PATH directly as required by your
# distribution.
#
# Note environment vars can be set by dynamically expanding a registry key.
#
[xlOil_Python.Environment]
    
	PYTHONCASEOK="1"

	#
	# If this environment variable is set, xlOil tries to load the corresponding
	# pythonXY.dll as the interpreter. If unset or blank, xlOil uses the reported
	# python version of the interpreter in the first python dist found.
	# 
	XLOIL_PYTHON_VERSION=""

    #
	# PYTHONEXECUTABLE should point to the python.exe of the current environment.
	# Note it is possible to dynamically expand registry keys contained in angle 
	# brackets <>.
	#
	PYTHONEXECUTABLE='''D:\lib\Python311-32\python.exe'''
	#PYTHONEXECUTABLE='''<HKLM\SOFTWARE\Python\PythonCore\3.6\InstallPath\ExecutablePath>'''

	XLOIL_PYTHON_PATH='''D:\lib'''

	PYTHONPATH='''%PYTHONPATH%;D:\lib'''


================================================
FILE: docs/make.cmd
================================================
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
	set SPHINXBUILD=sphinx-build
)

if "%1" == "" goto help

set XLOIL_SOLN_DIR=%~dp0..
set DOC_BUILD_DIR=%XLOIL_SOLN_DIR%\build\docs
set PY_PACKAGE_DIR=%XLOIL_SOLN_DIR%\libs\xlOil_Python\Package
set SOURCEDIR=%~dp0\source
set PATH=%PATH%;C:\Program Files\doxygen\bin

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
	echo.
	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
	echo.installed, then set the SPHINXBUILD environment variable to point
	echo.to the full path of the 'sphinx-build' executable. Alternatively you
	echo.may add the Sphinx directory to PATH.
	echo.
	echo.If you don't have Sphinx installed, grab it from
	echo.http://sphinx-doc.org/
	exit /b 1
)

mkdir "%DOC_BUILD_DIR%"

if "%1" == "doxygen" goto doxygen

if "%1" == "-bin" (
  set XLOIL_BIN_DIR=%XLOIL_SOLN_DIR%\build\%2
  shift
  shift
)

REM Generate the doc stubs: since we can import the core pyd locally, this is
REM really just for ReadTheDocs
if exist "%PY_PACKAGE_DIR%\generate_stubs.py" (
	echo.Generating doc stubs for xloil_core
	python "%PY_PACKAGE_DIR%\generate_stubs.py"
)

REM It's very important to pass the -E argument to sphinx, otherwise it does
REM not notice changes to docstrings in python modules and generates the 
REM wrong documentation

REM Set READTHEDOCS so we get consistency with the RTD online version
set READTHEDOCS=1
%SPHINXBUILD% -M %1 "%SOURCEDIR%" "%DOC_BUILD_DIR%" %SPHINXOPTS% -E -W --keep-going %O%
set READTHEDOCS=
goto end


:doxygen

pushd source

REM For some reason doxygen can't create directories itself
mkdir "%DOC_BUILD_DIR%\doxygen\html\doxygen"
mkdir "%DOC_BUILD_DIR%\doxygen\xml\doxygen"

REM Need to reverse slashes for doxygen because life is tough
set "XLO_SOLN_DIR=%XLOIL_SOLN_DIR:\=/%"
doxygen xloil.doxyfile
popd
goto end


:help
%SPHINXBUILD% -M help %SOURCEDIR% %DOC_BUILD_DIR% %SPHINXOPTS% %O%

:end
popd


================================================
FILE: docs/requirements.txt
================================================
numpy
numpydoc
autodocsumm
sphinx-rtd-theme 
docutils>=0.16 
sphinx_rtd_theme
autodocsumm

================================================
FILE: docs/source/Concepts.rst
================================================
==============
xlOil Concepts
==============

This document explains some of the key xlOil concepts shared accross different languages

.. contents::
    :local:


Excel Functions (UDFs)
----------------------

Excel supports several classes of user-defined functions:

- Macros: run at user request, have write access to workbook
- Worksheet functions: run by Excel's calculation cycle. Several sub-types:
  - Vanilla
  - Thread-safe: can be run concurrently
  - Macro-type: can read from sheet addresses and invoke a wider variety of Excel interface functions
  - Async: can run asynchronously during the calc cycle, but not in the background
  - RTD: (real time data) background threads which push data onto the sheet when it becomes available
  - Cluster: can be packaged to run on a remote Excel compute cluster

xlOil currently supports all but Cluster functions.

Excel can pass functions / macros data in one of these types:

- Integer
- Boolean
- Floating point
- String
- Error, e.g. #NUM!, #VALUE!
- Empty
- Array of any of the above
- Range refering to a worksheet address

There is no date type. Excel's builtin date functions interpret numbers as days since 1900. 
Excel does not support timezones.


.. _core-cached-objects:

Cached Excel Objects
--------------------

xlOil has an internal lookup for Excel values, which is a convenient way of 
passing arrays around a sheet and as arguments to other xlOil functions.

The function ``=xloRef(A1:B2)`` returns a cache string of the form:
``<UniqueChar>[WorkbookName]SheetName!CellRef,#``

The data can be recovered using ``=xloVal(<CacheString>)``. Alternatively,
this string can be passed instead of the source range to xlOil functions which
support cache lookups - and for large arrays this is much faster.

Example use cases are:

    * Where you might use a named range - to avoid updating references 
      in multiple functions when data is appended.  Because `xloRef` automatically 
      trims the range back to the last non-blank row, it can be pointed to a range
      far larger than the data.
    * To speed up passing the same large array into several functions 
      (e.g. multiple lookups from a data table, although consider xlOil_SQL if
      you want to do this).

However, there is a disadvantage to using `xloRef`: the cache is cleared when
a workbook is closed, but Excel does not know to recalculate the `xloRef` 
functions when the workbook is reopened. Hence you need to force a sheet
recalculation using *Ctrl-Alt-F9*.

In addition to caching arrays, xlOil plugins use the cache to opaquely return
referencs to in-memory structures.  Although the strings look similar, they 
point to very different objects and cannot be written to the sheet using `xloVal`.


.. _concepts-rtd-async:

Rtd / Async
-----------

In Excel, RTD (real time data) functions are able to return values independently of Excel's 
calculation cycle.  Excel has supported RTD functions since at least Excel 2002.  In Excel 
2010, Excel introduced native async functions.

RTD:

    * Pro: operates independently of the calc cycle - true background execution
    * Pro: provides notification when an RTD function call is changed or removed
    * Con: increased overhead compared to native async
    * Con: requires automatic calculation enabled (or repeated presses of F9 until calc is done)

Native async:

    * Pro: Less overhead compared to RTD
    * Pro: works with manual calc mode
    * Con: tied to calc cycle, so any interruption cancels all asyncs functions

The last con is particularly problematic for native async: *any* user interaction with Excel will
interrupt the calc, so whilst native async functions can run asynchronously with each other, they
cannot be used to perform background calculations.

.. _concepts-ribbon:

Custom UI: The Fluent Ribbon
----------------------------

xlOil allows dynamic creation of Excel Ribbon components. The ribbon is defined by XML
(surrounded with <customUI> tags) which should be created with a specialised editor, see the 
*Resources* below. Controls in the ribbon interact with user code via callback handlers.  
These callbacks pass a variety of arguments and may expect a return value; it is important 
to check that the any callback behaves as per the callback specifications in the *Resources*.

To pass ribbon XML into Excel, xlOil creates a COM-based add-in in addition to the XLL-based 
add-in which loads the xlOil core - you can see this appearing in Excel's add-in list in the 
Excel's Options windows.

Resources:

   * `Microsoft: Overview of the Office Fluent Ribbon <https://docs.microsoft.com/en-us/office/vba/library-reference/concepts/overview-of-the-office-fluent-ribbon>`_
   * `Microsoft: Customizing the Office Fluent Ribbon for Developers <https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2007/aa338202(v=office.12)>`_
   * `Microsoft: Custom UI XML Markup Specification <https://docs.microsoft.com/en-us/openspecs/office_standards/ms-customui/31f152d6-2a5d-4b50-a867-9dbc6d01aa43>`_
   * `Microsoft: Ribbon Callback Specifications <https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2010/ee691833(v=office.14)>`_
   * `Office RibbonX Editor <https://github.com/fernandreu/office-ribbonx-editor>`_
   * `Ron de Bruin: Ribbon Examples files and Tips <https://www.rondebruin.nl/win/s2/win003.htm>`_


.. _concepts-intellisense:

Intellisense / Function Context Help
------------------------------------

To get pop-up function help, install `Excel-DNA Intellisense <https://github.com/Excel-DNA/IntelliSense/releases>`_

In addition to the function wizard, Excel has a function context help which pops up as you type.
This is only directly available for built-in functions.  Fortunately, Govert of *Excel-DNA* has created
an add-in which mimics this behaviour for user-defined functions.  Download the XLL (with the right bitness)
from the link above and activate it by one of:

   1) Dragging the XLL into Excel (must be done once per session)
   2) Install it via *Excel* => *Options* => *Addins* => *Manage*. 
   3) Copy it to your `%APPDATA%\\Microsoft\\Excel\\XLSTART` directory.

You will now get pop-up help for all xlOil plugins functions, including any dynamically registered ones, 
for example, created with python plugin.

================================================
FILE: docs/source/Core.rst
================================================
===========
xlOil Core
===========

Here we tell you how to get started using xlOil and how to distribute addins

.. _core-getting-started:

Getting Started
---------------

You need **Excel 2010** or later on a desktop PC. xlOil will not work with online 
or Mac versions of Office.

.. important::

    If you want to use xlOil with python you should install it via `pip`. Stop reading
    this page and go to :doc:`xlOil_Python/GettingStarted`

Download the binary package (e.g. from gitlab) and unzip to a directory of 
your choice. 

You can run the `xlOil_Install.ps1` script to install the addin for every
Excel session, or just drop `xlOil.xll` into any running Excel session
to load xlOil temporarily.

xlOil should now load when you open Excel, try following 
:any:`sql-getting-started`

To configure the plugins being loaded, see :any:`core-edit-settings-files`.
Some plugings, such as the python one, have several paths which must be set 
correctly - it will generally be easier to use these plugins by following their
specific installation instructions.

.. _core-example-sheets:

Example sheets
--------------

To check your setup and see some of the capabilities of xlOil, try:
:download:`Tests and Examples </_build/xlOilExamples.zip>`.

.. _core-edit-settings-files:

Editing the settings file
-------------------------

There is an `xlOil.ini` file linked to the main `xlOil.xll` addin. (This ini file 
is actually parsed as TOML, an extension of the ini format). xlOil searches for
this file first in `%APPDATA%/xlOil` then in the directory containing the `xlOil.xll` 
addin. 

The two most important setting in `xlOil.ini` are:

::

    ...
    XLOIL_PATH='''C:\lib\xloil```
    ...
    Plugins=["xloil_Python.dll", "xlOil_SQL.dll"]

``XLOIL_PATH`` allows the `xlOil.xll` addin to locate the main xlOil DLL if the 
addin is being run from a different directory.  When the main DLL has loaded, 
xlOil loads the specified plugins. It searches for these plugins first in the 
directory containing `xlOil.dll`, then the directory containing the XLL, then 
the usual DLL search paths. 


Setting enviroment variables in settings files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Each plugin can have an *Environment* section in the settings file. Within this block
tokens are interpreted as enviroment variables to set. A plugin's environment settings 
are processed before the plugin is loaded. 

Keys are interpreted as environement variables to set. Values can reference other enviroment 
variables by surrounding the name with `%` characters.

In addition you can pull values from the registry by surrounding the registry
path with angle brackets `<>`. Leaving a trailing backslash `\\` in the 
registry path fetches the default value for that key.

The TOML syntax of three single quotes indicates a string literal, this avoids escaping 
all the backslashes.

The default enviroment block for Python looks like this:

::

    [[xlOil_Python.Environment]]
    xlOilPythonVersion="3.7"

    [[xlOil_Python.Environment]]
    PYTHONPATH='''<HKLM\SOFTWARE\Python\PythonCore\%xlOilPythonVersion%\PythonPath\>'''
    PYTHON_LIB='''<HKLM\SOFTWARE\Python\PythonCore\%xlOilPythonVersion%\InstallPath\>'''

    [[xlOil_Python.Environment]]
    PATH='''%PATH%;%PYTHON_LIB%;%PYTHON_LIB%\Library\bin'''

The double brackets tell TOML that the order of these declarations is important,
this means we can refer to previously set enviroment variables.

In addition you can pull values from the registry by surrounding the registry
path with angle brackets `<>`, for example, 
`<HKLM\SOFTWARE\Python\PythonCore\3.6\InstallPath\ExecutablePath>`. 
Leaving a trailing backslash `\\` in the registry path fetches the default 
value for that key.

Troubleshooting
---------------

You may need to tweak your settings file: :any:`core-edit-settings-files`

A common problem is that the COM interface misbehaves by either failing on start-up or failing
because of an open dialog box in Excel.  For a start-up fail, unload and reload the addin. 
For other errors try to close dialog boxes or panes and if that fails, restart Excel.

The log file
~~~~~~~~~~~~~

If xlOil detects a serious load error, it pops up a log window to alert you (this can
be turned off). If it succesfully loaded the core DLL a log file will also be created
next to `xlOil.ini`, which by default is in ``%APPDATA%\xlOil``.  If xlOil loaded, the 
worksheet function `xloLog` can tell you where this file is.  A setting in `xlOil.ini` 
controls the log level.

Manual installation
~~~~~~~~~~~~~~~~~~~

The `xlOil_Install.ps1` script does the following:

   1. Check xlOil is not in Excel's disabled add-ins
   2. Copy xlOil.xll to the ``%APPDATA%\Microsoft\Excel\XLSTART`` directory
   3. Copy xlOil.ini in the ``%APPDATA%\xlOil``` directory
   4. Check VBA Object Model access is allowed in 
      `Excel > File > Options > Trust Center > Trust Center Settings > Macro Settings``


Manual removal
~~~~~~~~~~~~~~

Should you need to force remove xlOil, do the following:

   1. Remove *xlOil.xll* from ``%APPDATA%\Microsoft\Excel\XLSTART``
   2. Remove the directory ``%APPDATA%\xlOil```

If you have added *xlOil.xll* or another xll add-in (xlOil does not do this by default)
and you want to remove it go to:

   1. `Excel > File > Options > Add-ins > Manage Excel Addins`
   2. If the previous step fails to remove the addin, start Excel with elevated/admin 
      priviledges and retry
   3. If that fails, try to remove the add-in from the registry key
      ``HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\<Version>\Excel\Options``.
      You should see values *OPEN*, *OPEN1*, etc with add-in names to be loaded. After removing
      a value, you need to rename the others to preserve the numeric sequence.
   4. If that does not work, also look at this registry key:
      ``HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\<Version>\Excel\Options``.

Note you may need to run the registry editor with elevated priviledges.

To really scrub the registry, you may find references to the addin under:
   * `HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\<Version>\\Excel\\Add-in Manager`
   * `HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\<Version>\\Excel\\AddInLoadTimes`
   * `HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\<Version>\\Excel\\Resiliency\DisabledItems`
   * `HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\Excel\\Addins`
   * `HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\Excel\\AddinsData`


================================================
FILE: docs/source/Developer.rst
================================================
=======================
xlOil Development Guide
=======================

Getting started as developer
----------------------------

- You need Visual Studio 2022 or newer
- All xlOil_Core dependencies are already in the `external` folder. Some of them are compressed, 
  so unpack them.
- To build the `xlOil-COM` library you need the ATL headers which can be installed with the Visual
  Studio installer (under C++ development). 
- For debugging, set xlOil_Loader as the target project, with 
  command=`<Path-to-Excel.exe>` args=`$(OutDir)\xloil.xll`


Release Instructions
--------------------

::

    cd <xloil_root>\tools
    python stage.py

(Optional) test python wheels with 

::

    cd <xloil_root>\build\staging\pypackage
    pip install dist/xlOil-0.3-cp37-cp37m-win_amd64.whl
    pip uninstall dist/xlOil-0.3-cp37-cp37m-win_amd64.whl

Use twine to upload to PyPI (note you need to ensure twine has the right login
keys/secrets):

::

    cd <xloil_root>\build\staging\pypackage

    # (Optional test)
    twine upload --repository-url https://test.pypi.org/legacy/ dist/*

    # The real thing
    twine upload dist/*


================================================
FILE: docs/source/Events.rst
================================================
==================
xlOil Excel Events
==================

.. contents::
    :local:

Introduction
------------

xlOil allows code to hook into Excel events.  The Excel API documentation 
`Excel.Application <https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)#events>`_
contains more complete descriptions of most of these events, with the exception of the
`CalcCancelled`, `WorkbookAfterClose`, `XllAdd` and `XllRemove` events which are not part of the
*Application* object and are provided by xlOil.

For the syntax used to hook these events, see the individual language documentation.

Parameter types
===============
Most events use some of the parameter types described below:

* *Workbook name*: passed as a string (not a ``Workbook`` object)
* *Worksheet name*: passed as a string 
* *Range*: passed as a ``Range`` object
* *Cancel*: a bool which starts as False If the event handler sets this argument to True,
  further processing of the event will stop
  
AfterCalculate
--------------

This event occurs after all Worksheet.Calculate, Chart.Calculate, QueryTable.AfterRefresh, 
and SheetChange events. It's the last event to occur after all refresh processing and all 
calc processing have completed, and it occurs after CalculationState is set to xlDone.
This event is called if the calculation was interrupted (for example by the user pressing 
a key or mouse button).

WorkbookOpen
------------
Occurs when a workbook is opened. Takes a single parameter containing the workbook name.

NewWorkbook
-----------
Occurs when a new workbook is created. Takes a single parameter containing the workbook name.

SheetSelectionChange
--------------------
Occurs when the selection changes on any worksheet (doesn't occur if the selection is on a 
chart sheet). Takes two paramters:

* Worksheet name
* Target / selected Range

SheetBeforeDoubleClick
----------------------
Occurs when any worksheet is double-clicked, before the default double-click action. 
Takes three parameters

 * Worksheet name
 * Target - A Range giving cell nearest to the mouse pointer when the double-click occurred.
 * Cancel - False when the event occurs. If the event procedure sets this argument to True, the default 
   double-click action isn't performed when the procedure is finished.

SheetBeforeRightClick
---------------------
Occurs when any worksheet is right-clicked, before the default right-click action. 
Takes three parameters

 * Worksheet name
 * Target - A Range giving the cell nearest to the mouse pointer when the right-click occurred.
 * Cancel - False when the event occurs. If the event procedure sets this argument to True, the default 
   right-click action isn't performed when the procedure is finished.

SheetActivate
-------------
Occurs when any sheet is activated. Takes a single parameter containing the sheet name.

SheetDeactivate
---------------
Occurs when any sheet is deactivated. Takes a single parameter containing the sheet name.

SheetCalculate
--------------
Occurs after any worksheet is recalculated or after any changed data is plotted on a chart.
Takes a single parameter containing the sheet name.

SheetChange
-----------
Occurs when cells in any worksheet are changed by the user or by an external link. Takes 
two paramters:

* Worksheet name
* Changed Range

WorkbookActivate
----------------
Occurs when any workbook is activated.  Takes a single parameter containing the workbook name.

WorkbookDeactivate
------------------
Occurs when any workbook is deactivated.  Takes a single parameter containing the workbook name.

WorkbookBeforeClose
-------------------
Occurs immediately before any open workbook closes. Takes two parameters

 * Workbook name
 * Cancel - False when the event occurs. If the event procedure sets this argument to True, the 
   workbook doesn't close when the procedure is finished.

The event is not called for each workbook when Excel exits.

WorkbookBeforeSave
------------------
Occurs before any open workbook is saved. Takes three parameters:

 * Workbook name
 * SaveAsUI - True if the Save As dialog box will be displayed due to changes made that need to 
   be saved in the workbook.
 * Cancel - False when the event occurs. If the event procedure sets this argument to True, the 
   workbook isn't save when the procedure is finished.

WorkbookBeforePrint
-------------------
Occurs immediately before any open workbook is printed. Takes two parameters

 * Workbook name
 * Cancel - False when the event occurs. If the event procedure sets this argument to True, the 
   workbook doesn't print when the procedure is finished.

WorkbookAfterClose
------------------
Excel's *WorkbookBeforeClose* event is cancellable by the user so it is not possible to know if 
the workbook actually closed.  When xlOil calls `WorkbookAfterClose`, the workbook is certainly 
closed, but it may be some time since that closure happened. Takes a single parameter containing the 
workbook name.

The event is not called for each workbook when xlOil exits. This event is not part of the 
*Excel.Application* API.

WorkbookNewSheet
----------------
Occurs when a new sheet is created in any open workbook. The first parameter is the workbook name, 
the second is the new sheet name.

WorkbookAddinInstall
--------------------
Occurs when a workbook is installed as an add-in. Takes a single parameter containing the workbook name.

WorkbookAddinUninstall
----------------------
Occurs when any add-in workbook is uninstalled. Takes a single parameter containing the workbook name.

CalcCancelled
-------------
Called when the calculation cycle is cancelled (for example by the user pressing a key or mouse button).
Native async functions should stop any background calculation when this event is received.

This event is not part of the *Excel.Application* API.

XllAdd
------
Triggered when an XLL related to this instance of xlOil is added by the user using the Addin settings
window. The parameter is the XLL filename.

This event is not part of the *Excel.Application* API.

XllRemove
---------
Triggered when an XLL related to this instance of xlOil is removed by the user using the Addin settings
window. The parameter is the XLL filename.

This event is not part of the *Excel.Application* API.


================================================
FILE: docs/source/Introduction.rst
================================================
=====
xlOil
=====

xlOil is a framework for linking programming languages with Excel language. 
That is, a way to write functions in a language of your choice and have them
appear in Excel as worksheet functions and macros, as well as manipulating
the application and GUI similar to VBA.

xlOil is designed to have very low overheads when calling your own worksheet 
functions.

xlOil supports different languages via plugins. The languages currently 
supported are:

- C++
- Python
- SQL

In addition there is :any:`xlOil_Utils` which contains some handy tools which Microsoft
never quite got around to adding.

You can use xlOil as an end-user of these plugins or you can use it to write
you own language bindings and contribute.

.. important::

    **Start Here:**  :any:`core-getting-started`

xlOil features
--------------

* Python
    - Very concise syntax to declare an Excel function
    - Optional type checking of function parameters
    - Supports keyword arguments
    - Choice of globally declared functions or code modules limited to a single workbook (just
      like VBA workbook-level functions)
    - Tight integration with numpy - very low overheads for array functions
    - Understands python tuples, lists, dictionarys and pandas dataframes
    - Async functions
    - RTD functions and on-the-fly RTD server creation
    - Macro type functions which write to ranges on the sheet
    - Access to the Excel Application object 
    - Hook Excel events
    - Pass any python object back to Excel and then back into any python function
    - Simple and quick add-in deployment
    - Two-way connection to Jupyter notebooks: run worksheet functions in Jupyter and query variables
      in the jupyter kernel
    - On-the-fly creation/destruction of COM addin objects and Ribbon UI

* C++
    - Safe and convenient wrappers around most things in the C-API
    - Concise syntax to declare Excel functions: registration is automatic
    - Deal with Excel variants, Ranges, Arrays and strings in a natural C++ fashion
    - Object cache allows returning opaque objects to Excel and passing them back to other functions
    - Async functions
    - RTD functions and on-the-fly RTD server creation
    - On-the-fly creation/destruction of COM addin objects and Ribbon UI

* SQL
    - Create tables from Excel ranges and arrays
    - Query and join them with the full sqlite3 SQL syntax

* Utils: very fast functions to
    - Sort on multiple columns
    - Split and join strings
    - Make arrays from blocks

Why xlOil was created
---------------------

Programming with Excel has no ideal solution. You have a choice of APIs:

- VBA - great integration with Excel, but clunky syntax compared with
  other languages, few common libraries, limited IDE, testing and source 
  control very difficult, single-threaded, use not encouraged by MS.
- C-API - It's C and hence unsafe. The API is also old, has some quirks 
  and is missing many features of the other APIs. But it's the fastest
  interface.
- COM - More fully-featured but slower and strangely missing some features
  of the C-API.  It's C++ so still pretty unsafe. Has some unexpected behaviour
  and may fail to respond.  Requires COM binding support in your language 
  or the syntax is essentially unusuable.
- .Net API - actually sits on top of COM, the best modern interface
  but only for .Net languages and speed-limited by COM overheads, still missing 
  some C-API features.
- Javascript API - supports Office on multiple devices and operating system, but 
  very slow with limited functionality compared to other APIs.

xlOil tries to give you the C and COM APIs blended in a more friendly 
fashion and adds:

- Solution to the "how to register a worksheet function without a static DLL entry point" problem
- Object caching
- A framework for converting excel variant types to another language and back
- A convenient way of creating worksheet-scope functions
- A loader stub
- Goodwill to all men


Comparison between xlOil and other Excel Addin solutions
--------------------------------------------------------

Given the age of Excel, there are many other solutions for Excel add-in
development.

Most available packages are commercial (and quite expensive) so I 
cannot test relative performance with xlOil. They are generally
focussed on a single language rather than providing a framework
for language bindings as xlOil does.

The following, likely incomplete, list includes some of the most  
prominent Excel addin software. 

- Addin express: (commercial) fully-featured with nice GUI and the support
  seems good as well. Limited to .Net languages, but covers the entire Office
  suite (not just Excel)
- ExcelDNA: (free) mature, well-regarded and widely used, covers 
  almost all Excel API features, but only for .Net languages.  I strongly
  recommend this software if you are using .Net languages.
- XLL Plus: (commercial) seems to be fully-featured with GUI wizards
  to help developers, but only for C++ and the most expensive sofware 
  here.
- PyXLL: (commercial) Python-only.  Supports the full range of Excel
  API features and some functionality to run on remote servers.
- XlWings: (mostly free) Python-only. More mature sofware, but considerably
  slower (2000x in my test case) than xlOil due to use of slower APIs.
  Can only create 'local' functions backed by VBA, so every Excel sheet needs
  to be be a macro sheet with special VBA redirects. This means it is not viable
  for addin deployment.  Supports Mac and Python 2.7 (but licence fee required 
  for this).


================================================
FILE: docs/source/conf.py
================================================
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#     sys.path.insert(0, os.path.abspath('.'))

import os
import sys
from pathlib import Path

#
# The default soln_dir and bin_dir paths here are to allow VS code to auto
# preview the docs. I'm currently not sure how to add environment variables
# to processes run by VS code.
#

file_dir = Path(__file__).parent
xloil_dir = file_dir.parent.parent
soln_dir = Path(os.environ.get("XLOIL_SOLN_DIR", xloil_dir)).resolve()
bin_dir = Path(os.environ.get("XLOIL_BIN_DIR", xloil_dir / "build/x64/Debug")).resolve()

if bin_dir.exists():
    sys.path.append(str(bin_dir))
sys.path.append(str(soln_dir / "libs/xlOil_Python/Package"))

# May as well fail here if we can't find xloil
try:
    import xloil
except Exception as e:
    raise Exception(f'{e}. SysPath={sys.path}', e)

# -- Project information -----------------------------------------------------

project = 'xlOil'
copyright = '2022, Steven Cunnane'
author = 'Steven Cunnane'

# The full version, including alpha/beta/rc tags
release = (soln_dir / "Version.txt").read_text()

# -- General configuration ---------------------------------------------------


# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "sphinx.ext.autodoc", 
    "sphinx.ext.autosummary", 
    "sphinx.ext.autosectionlabel", 
    "numpydoc",
    'autodocsumm'
    ]

# Avoid duplicate label warnings from autosectionlabel
suppress_warnings = ['autosectionlabel.*']

# True to prefix each section label with the name of the document it is in, 
# followed by a colon. For example, index:Introduction for a section called 
# Introduction that appears in document index.rst.
autosectionlabel_prefix_document = True

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.

USE_READTHEDOCS_THEME = True
if USE_READTHEDOCS_THEME:
    import sphinx_rtd_theme
    extensions.append('sphinx_rtd_theme')
    html_theme = "sphinx_rtd_theme"
else:
    html_theme = 'bizstyle'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []# ['_static']

# A list of paths that contain extra files not directly related to the documentation, 
# such as robots.txt or .htaccess. Relative paths are taken as relative to the 
# configuration directory. They are copied to the output directory.
#html_extra_path = ['../build/doxygen']

autodoc_default_flags = ['members']

#
# If autosummary_generate is True, stub .rst files for for items in the autosummary
# toctree are automatically generated. We prefer to keep a flatter structure.
#
autosummary_generate = False

# See https://stackoverflow.com/questions/34216659/
numpydoc_show_class_members=False

#
# Required for readthedocs build as the master_doc seems to default to 'contents' in
# their environment. Locally sphinx builds fine without this
#
master_doc = 'index'

# -- Generate examples file ---------------------------------------------------
#
# Only do this when XLOIL_BIN_DIR is explicitly set so not on ad-hoc run
#
if "XLOIL_BIN_DIR" in os.environ:
    import zipfile
    from zipfile import ZipFile

    try: os.makedirs('_build')
    except FileExistsError: pass

    zipObj = ZipFile('_build/xlOilExamples.zip', 'w', compression=zipfile.ZIP_BZIP2)
    try:
        zipObj.write(soln_dir / "tests" / "AutoSheets" / "PythonTest.xlsm", "PythonTest.xlsx")
        zipObj.write(soln_dir / "tests" / "ManualSheets" / "python" / "PythonTestAsync.xlsm", "PythonTestAsync.xlsm")
        zipObj.write(soln_dir / "tests" / "AutoSheets" / "PythonTest.py", "PythonTest.py")
        zipObj.write(soln_dir / "tests" / "AutoSheets" / "TestModule.py", "TestModule.py")
        zipObj.write(soln_dir / "tests" / "AutoSheets" / "TestSQL.xlsx", "TestSQL.xlsx")
        zipObj.write(soln_dir / "tests" / "AutoSheets" / "TestUtils.xlsx", "TestUtils.xlsx")
    
    except FileNotFoundError as err: 
        print("WARNING: Could not create xlOilExamples.zip due to: ", str(err))

    zipObj.close()


================================================
FILE: docs/source/index.rst
================================================
.. raw:: html

	<iframe src="https://github.com/sponsors/cunnane/card" title="Sponsor xlOil" height="200" width="500" style="border: 0;"></iframe>

xlOil documentation
===================

.. toctree::
	:maxdepth: 4
	:caption: Contents:
	:glob:

	Introduction
	Core
	Concepts
	Events
	xlOil_Core_Functions
	xlOil_Cpp/index
	xlOil_Python/index
	xlOil_SQL/index
	xlOil_Utils
	Developer


Indices and tables
==================

* :ref:`genindex`
* :ref:`search`


================================================
FILE: docs/source/xlOil_Core_Functions.rst
================================================
=========================
xlOil Core Functions
=========================

This page describes the worksheet functions registered by the xlOil core, which should always 
be available when xlOil is running.

xloRef: adds a value or array to the cache
------------------------------------------

.. function:: xloRef(arrayOrRange)

    Adds the specified value or range or array to the object cache and returns a string 
    reference.

    See :any:`core-cached-objects`

xloVal: Retrives a value from the Excel data cache
--------------------------------------------------

.. function:: xloVal(cacheRefString)

    Given a reference string, returns a stored array or value. Cached values 
    are not saved with the workbook so will need to be recreated by forcing 
    a full recalc (press Ctrl-Alt-F9) when the workbook is opened

    See :any:`core-cached-objects`


xloHelp: returns help on an xlOil registered function
------------------------------------------------------

.. function:: xloHelp(functionName)

    Returns a two column array containing the help information passed to Excel's 
    function wizard when the function was registered.  The first row contains 
    the function name and the main help string. Subsequent rows contain argument
    names and their associated help.

    In the function wizard all help strings are limited to 256 characters. xloHelp
    does not have this limitation. 

xloLog: flushes the log file and returns its location
-----------------------------------------------------

.. function:: xloLog(ShowWindow=FALSE)

    The xlOil log is only flushed (written to file) occasionally or when an error 
    or warning occurs. Executing this function flushes the log and returns the 
    location of the log file (by default this is the same directory as the settings
    file).

    Setting the *ShowWindow* parameter causes xlOil's log window to appear. This 
    doesn't display the contents of the entire log file but only the most recent log 
    messages.


xloVersion: returns information on the xlOil version
----------------------------------------------------

.. function:: xloVersion()

    Returns a two-column array of version information.

================================================
FILE: docs/source/xlOil_Cpp/COM.rst
================================================
=======================
xlOil C++ Using COM
=======================

The root of Excel's COM interface is `Excel.Application <https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)>`_
which VBA programmers will be familiar with.

The easiest way to work with it in C++ is by importing the type library into your source file - 
this allows compile time checks and auto-completion and results in faster code.  COM objects
can be accessed using 'late-binding' where methods and properties are queried from the object
at runtime, but this clearly limits performance.

In xlOil, the appropriate type library can be imported with the *ExcelTypeLib.h* header:

::

    #include <xlOil\ExcelTypeLib.h>
    #include <xlOil\xlOil.h>
    using namespace xloil;

    XLO_FUNC_START(testToday())
    {
        excelApp().Range[L"A1"]->NumberFormat = L"dd-mm-yyyy";
    }
    XLO_FUNC_END(testToday).macro();

If *ExcelTypeLib.h* is included before `xlOil.h` it adds COM error handling to any worksheet 
functions declared with `XLO_FUNC_START`.  This is useful because COM throws its own `_com_error`
classes which do not derive from `std::exception`.

I cannot find a specific Excel/COM/C++ tutorial at this time, but the *Excel.Application* API 
documentation is comprehensive. 


================================================
FILE: docs/source/xlOil_Cpp/CppRtd.rst
================================================
=======================
xlOil C++ RTD functions
=======================

In Excel, RTD (real time data) functions are able to return values independently of Excel's 
calculation cycle. The classic example of this is a stock ticker with live prices. This is contrasted 
with  Excel's native async support in :any:`concepts-rtd-async`.


Example: Subscription
---------------------

xlOil wraps the RTD server implementation to make subscription and publication straightfoward as in the 
following example:

.. highlight:: c++

::

    #include <xloil/xlOil.h>
    using namespace xloil;

    IRtdServer& myRtdServer()
    {
      static shared_ptr<IRtdServer> ptr = newRtdServer();
      static auto backgroundTask = std::async([]()
        {
          // Somehow fetch live prices here
          ptr->publish("SP500", ExcelObj(123));
          ptr->publish("FTSE100", ExcelObj(456));
        });
      return *ptr;
    }

    XLO_FUNC_START(
      getStock(const ExcelObj& ticker)
    )
    {
      auto value = myRtdServer().subscribe(tag.toString().c_str());
      return returnValue(value
        ? *value
        : Const::Error(CellError::NA));
    }
    XLO_FUNC_END(getStock);


Example: Background task
------------------------

The RTD mechanism can be used to run slow tasks like data fetches or calculations in the background whilst
the user continues to interact with Excel.  The following demonstrates a simple counter which increments
stepwise.

.. highlight:: c++

::

    #include <xloil/xlOil.h>
    using namespace xloil;
    
    struct Counter : public RtdAsyncTask
    {
      Counter(int iStep) : _iStep(iStep) {}

      int _iStep;

      // This function arranges for the work to be done in the background, but must
      // exit when the `RtdNotifier` requests it
      std::future<void> operator()(RtdNotifier notify) override
      {
        return std::async([=, step = _iStep]()
        {
          int _count = 0;
          while (!notify.cancelled())
          {
            notify.publish(ExcelObj(_count));
            std::this_thread::sleep_for(std::chrono::seconds(2));
            _count += step;
          }
        });
      }

      // When the cell which generated the task is recalculated, xlOil cannot tell
      // whether Excel is calling it with new inputs or RTD triggered the call to get
      // a result. It uses this equality operator to determine if it already has a 
      // running task for the given set of inputs
      bool operator==(const IRtdAsyncTask& that_) const override
      {
        const auto* that = dynamic_cast<const Counter*>(&that_);
        if (!that)
          return false;
        return _iStep == that->_iStep;
      }
    };

    XLO_FUNC_START(
      rtdCounter(const ExcelObj& step)
    )
    {
      auto value = rtdAsync(
        std::make_shared<Counter>(step.toInt(1)));
      return returnValue(value ? *value : CellError::NA);
    }
    XLO_FUNC_END(rtdCounter);

================================================
FILE: docs/source/xlOil_Cpp/CustomGUI.rst
================================================
==============================
xlOil C++ GUI Customisation
==============================

.. contents::
    :local:

xlOil allows dynamic creation of Excel Ribbon components and custom task panes. See 
:any:`concepts-ribbon` for background. The code differs slightly depending on whether 
you are writing a static XLL or an xlOil plugin.

Creating a ribbon in a static XLL
---------------------------------

.. highlight:: c++

::
    
    void ribbonHandler(const RibbonControl& ctrl) {}
    

    struct MyAddin
    {
        std::shared_ptr<IComAddin> theComAddin;
        MyAddin()
        {
            // We need this call so that xlOil defers execution of the ribbon creation
            // until Excel's COM interface is ready
            xllOpenComCall([this]()
            {
                auto mapper = [=](const wchar_t* name) mutable { return ribbonHandler; };
                theComAddin = makeAddinWithRibbon(
                    L"TestXlOil",
                    LR"(
                        <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
                        ...
                        </customUI>
                    )", 
                    mapper);
            });
        }
    };
    XLO_DECLARE_ADDIN(MyAddin);


Creating a ribbon in an xlOil plugin
------------------------------------

.. highlight:: c++

:: 

    #incude <xloil/xloil.h>

    void ribbonHandler(const RibbonControl& ctrl) {}
    std::shared_ptr<IComAddin> theComAddin;

    XLO_PLUGIN_INIT(xloil::AddinContext* ctx, const xloil::PluginContext& plugin)
    {
        xloil::linkLogger(ctx, plugin);

        auto mapper = [=](const wchar_t* name) mutable { return ribbonHandler; };
        theComAddin = makeAddinWithRibbon(
            L"TestXlOil",
            LR"(
                <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
                ...
                </customUI>
            )", 
            mapper);

        return 0;
    }

    
Creating a Custom Task Pane
---------------------------

After a COM addin has been created using the ribbon examples above, a custom task pane
can be added in the following way.

.. highlight:: c++

:: 
    
    std::shared_ptr<ICustomTaskPane> taskPane(theComAddin->createTaskPane(L"xloil"));
    taskPane->setVisible(true);

An option progid can be passed to `createTaskPane` to create a specific COM object 
as the root of the task pane, if omitted, xlOil uses a simple default object.

================================================
FILE: docs/source/xlOil_Cpp/DynamicRegistration.rst
================================================
==============================
xlOil C++ Dynamic Registration
==============================

To support registration of functions in other languages, xlOil has the ability to register worksheet
functions generated at runtime.  In C++, you usually can create a static entry point for each function
you want to register using xlOil macros.  These macros end up calling `Excel12(xlfRegister, ...)` and 
pass the name of your function.  Dynamic registration is a little trickier since `xlfRegister` requires
the name of an entry point into your XLL rather than a function pointer.  xlOil arranges for such a 
suitable entry point to exist by generating a small trampoline function in assembler which redirects
to your function.  However, this creates a tiny performance overhead (typically around 8-16 instructions
increasing with the number of arguments).

.. highlight:: c++

::

    auto regId = RegisterLambda<>(
        [](const ExcelObj& arg1, const ExcelObj& arg2)
        {
            ...
            return returnValue(...);
        })
        .name("Foobar")
        .help("Does nothing")
        .arg("Arg1")
        .registerFunc();

The lambda's can take as many `const ExcelObj&` args as required. It must return `ExcelObj*`,
but it may throw: xlOil will return the error string.  By specifying `const FuncInfo&` as the 
type of the first argument, the callable will be given a reference to the function registration info
in addition the arguments passed by Excel.

You can dynamically register any function you could register statically, so :any:`SpecialArgs` 
arguments are valid, as well as a void return, for example:

.. highlight:: c++

::

    auto regId = RegisterLambda<void>(
        [](const FuncInfo&, const ExcelObj& arg1, const AsyncHandle& handle)
        {
            handle.returnValue(...);
        })
        .name("AsyncFoobar").registerFunc();

The returned register Id is a `shared_ptr` whose destructor unregisters the function, so this must be
kept in scope.



================================================
FILE: docs/source/xlOil_Cpp/Events.rst
================================================
================
xlOil C++ Events
================

See :ref:`Events:Introduction`.

Examples
--------

.. highlight:: c++

::

    // When the returned shared_ptr is destroyed, the handler is unhooked.
    auto ptr = xloil::Event::CalcCancelled().bind(
          [this]() { this->cancel(); }));

    // The returned id can be used to unhook the handler
    static auto id = Event::AfterCalculate() += [logger]() { logger->flush(); };



================================================
FILE: docs/source/xlOil_Cpp/GettingStarted.rst
================================================
=========================
xlOil C++ Getting Started
=========================


There are a few ways to build a C++ project with xlOil:

   1. xlOil plugin: writing a DLL which can be loaded by xlOil after the loader XLL 
      starts up the application. This allows co-operation with other xlOil features such as
      the the object cache and settings file.  It means that cache references created by 
      `xloRef` can be used in your addin.
   2. XLL dynamically linking xlOil. This allows co-operation with the Excel object cache.
      Your XLL will need to be able to find xlOil when it loads - this may be easier if delay
      loading is employed.
   3. XLL statically linking xlOil. This gives a standalone XLL. It does not include
      the xlOil cache functions `xloRef` and `xloVal`, although it is easy to define a private
      object cache with your own function names.

The header files and `xlOil.lib` file required for dynamic linking are included in the 
`binary releases <https://gitlab.com/stevecu/xloil/-/releases>`_.

You need: 
    * `xlOil.lib`: linking library
    * `xlOil.dll`: main binary 
    * `xlOil.xll`: XLL loader stub
    * `xlOil.ini`: Main settings file
    * `include/xloil`: header files

The static libs are a lot larger, so you'll need to build them from source.

If you want to read settings from the add-in's *.ini* file using *tomlplusplus* you can find 
this in `xlOil/external` - it's header-only.

Creating an xlOil Plugin
~~~~~~~~~~~~~~~~~~~~~~~~

This method assumes you already have a running install of xlOil.

Create a project & solution for your DLL.

Building an xlOil plugin requires a number of build settings and the easiest way to get these right
it is use a property sheet.  First, include an edited copy of `./libs/SetRoot.props` where *xlOilRoot* 
points to the xlOil directory. Then include `./libs/xlOilPlugin.props`.

Now add the following source file:

.. highlight:: c++

:: 

    #include <xloil/xloil.h>

    XLO_PLUGIN_INIT(xloil::AddinContext* ctx, const xloil::PluginContext& plugin)
    {
      xloil::linkLogger(ctx, plugin);
      return 0;
    }

    using namespace xloil;

    XLO_FUNC_START( 
        MyFunc(const ExcelObj* arg1, const ExcelObj* arg2)
    )
    {
        auto result = arg1->toString() + ": " + arg2->toString(L"default value");
        return ExcelObj::returnValue(result);
    }
    XLO_FUNC_END(MyFunc).threadsafe()
        .help(L"Joins two strings")
        .arg(L"Val1", L"First String")
        .arg(L"Val2", L"Second String");


Declaring an `XLO_PLUGIN_INIT` entry point lets xlOil know the DLL is a plugin. Calling `linkLogger`
links the *spdlog* to the main xlOil log output.  This is optional if you don't plan on using any logging
functionality.

The ``ExcelObj`` class wraps the xloper12 variant type used in the XLL interface. It provides
a number of accessors with a focus on efficiency and avoidance of copying (see below).

To load your plugin in Excel you need to ensure that the main xlOil add-in can locate your DLL. 
You can do this by changing the Addin enviroment in the `xlOil.ini` file or changing the
current working directory or system PATH, or by simply ensuring your DLL is in the same directory
as *xlOil.dll*.

You should also add your plugin to the `Plugins=` key in `xlOil.ini`.


Creating an XLL which statically links xlOil
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Build xlOil with the *DebugStatic* or *ReleaseStatic* configuration.

Create a project & solution for your XLL. It should output a DLL, but change the *Target Extension* to XLL.

Building an xlOil-linked XLL requires a number of build settings and the easiest way to get these right
it is use a property sheet.  First, include an edited copy of `./libs/SetRoot.props` where *xlOilRoot* 
points to the xlOil directory. Then include `./libs/xlOilStaticLib.props`.

Alternatively, you can copy and modify the `TestAddin` project, though you will still need to ensure
*xlOilRoot* is set correctly.

Create a `Main.cpp` file with the following contents:

.. highlight:: c++

::

    #include <xloil/xlOil.h>
    #include <xloil/XllEntryPoint.h>
    using namespace xloil;
    
    struct MyAddin
    {};
    XLO_DECLARE_ADDIN(MyAddin);

    XLO_FUNC_START( 
        MyFunc(const ExcelObj* arg1, const ExcelObj* arg2)
    )
    {
        auto result = arg1->toString() + ": " + arg2->toString(L"default value");
        return ExcelObj::returnValue(result);
    }
    XLO_FUNC_END(MyFunc).threadsafe()
        .help(L"Joins two strings")
        .arg(L"Val1", L"First String")
        .arg(L"Val2", L"Second String");


Debugging your addin
~~~~~~~~~~~~~~~~~~~~

Start a debugging session with the following settings where the XLL may be `xlOil.xll`
or one you built yourself depending on which path you are following.

   * Command: <path to Excel.exe>
   * Arguments: <path to the XLL>

Setting the working directory is optional, but it may help locate any externals DLLs your
add-in uses.

There are many examples to follow in the ``xloil_Utils`` and ``xloil_SQL`` projects.

================================================
FILE: docs/source/xlOil_Cpp/ObjectHandles.rst
================================================
========================
xlOil C++ Object Handles
========================

It is often convenient to pass a pointer to an in-memory object from one function to another in a way
which generalises :any:`core-cached-objects`.  xlOil makes this very straightforward:

.. highlight:: c++

::

    XLO_FUNC_START(
        cacheOut(const ExcelObj& val)
    )
    {
        auto key = makeCached<int>(val.toInt());
        return returnValue(key);
    }
    XLO_FUNC_END(cacheOut);

    XLO_FUNC_START(
        cacheIn(const ExcelObj& cacheKey)
    )
    {
        auto* val = getCached<int>(cacheKey.asPString());
        return returnValue(val ? *val : 0);
    }
    XLO_FUNC_END(cacheIn);

The cache key or handle returned looks `<UnusualChar>[Book1]Sheet1!R1C1,A`. The leading character 
allows rapid rejection of invalid cache strings; it is unique per cached object type.

Cached objects do not persist when a spreadsheet is closed, but Excel does not know to recalculate
the cells which generate the cache handles when a spreadsheet is opened, so a full recalc must
be manually performed with Ctrl-Alt-F9.  To avoid this requirement, you can make the functions which
generate the handles RTD, but this carries some overhead.


================================================
FILE: docs/source/xlOil_Cpp/SpecialArgs.rst
================================================
======================
XLL Special Arguments
======================

User-defined Excel functions in XLLs usually take a number of `const ExcelObj&` arguments
and return a `ExcelObj*`.  xlOil supports a number of other possibilities, the most useful
of which are `RangeArg` and `AsyncHandle`.

RangeArg
--------

Declaring a class as `const RangeArg&` instead of an `ExcelObj` in registered function tells 
xlOil to allow range references to be passed.  These are sheet addresses which avoid copying
the underlying data.  Normally, references to areas on the sheet are converted to arrays
before being passed to the function.  A `RangeArg` only allows the possibility that a range
reference be specified, `RangeArg` inherits from `ExcelObj` and so may actually be any Excel 
type.

AsyncHandle
-----------

Declaring an argument as `const AsyncHandle&` causes the function to be declared as native
async type to Excel. Such a function does not return a value directly but invokes the 
`returnValue` method on its handle to pass a value to Excel (which should only be done once).

ExcelObj pointer
----------------

You may opt to receive a `const ExcelObj*` instead of a reference. This is purely preference
and has no other impact.

FPArray
-------

An `FPArray` argument is a two-dimensional array of double. This is naturally very fast to 
access, particulary when combined with inplace returns but has a significant drawback: if
if any value in the array passed to the function is not a number, Excel will return *#VALUE!*
without actually invoking the function.

Inplace returns
----------------

Excel supports returning values by modifying arguments in place.  This is most useful for the 
FPArray type.  To declare inplace return, simply make the argument a non-const ref or pointer.

It is also possible to return an `ExcelObj` in-place but this is disabled by default. 
In the words of the XLL SDK:


    "Excel permits the registration of functions that return an XLOPER by modifying 
    an argument in place. However, if an XLOPER argument points to memory, and the 
    pointer is then overwritten by the return value of the DLL function, Excel can 
    leak memory. If the DLL allocated memory for the return value, Excel might try 
    to free that memory, which could cause an immediate crash.  Therefore, you should 
    not modify XLOPER/XLOPER12 arguments in place."


In practice, it can be safe to modify an ExcelObj in place, for instance *xloSort*
modifies its input by changing the row order in the array, but without changing memory 
allocation.  However it does not use an inplace return because the drawback of this  
technique is that you cannot return a different type to the one passed, in particular
you cannot return an error message or error type. 

To enable inplace `ExcelObj` returns, define the macro 
`XLOIL_UNSAFE_INPLACE_RETURN` before including any xlOil headers.

================================================
FILE: docs/source/xlOil_Cpp/StaticXLLs.rst
================================================
======================
xlOil C++ Static XLLs
======================

As explained in :any:`GettingStarted`, it is possible to create an XLL which statically links xlOil.
This allows an all-in-one XLL without worrying about DLL search paths.  We expand on the example 
in :any:`GettingStarted` to illustrate some of the other static XLL features:

.. highlight:: c++

::

    #include <xloil/xlOil.h>
    #include <xloil/XllEntryPoint.h>
    using namespace xloil;

    struct MyAddin
    {
        MyAddin()
        {
            // This constructor is called by Excel's AutoOpen

            xllOpenComCall([this]()
            {
            // If we need to do some COM stuff on startup, like register a Ribbon,
            // it needs to go in this delayed COM callback.
            });
        }

        ~MyAddin()
        {
            // This destructor is called by Excel's AutoClose
        }

        
        static wstring addInManagerInfo()
        {
            // The string returned here is displayed in Excel's addin options window
            // Note the function is static: it can be called before AutoOpen.
            return wstring(L"My Addin Name");
        }
    };
    XLO_DECLARE_ADDIN(MyAddin);



================================================
FILE: docs/source/xlOil_Cpp/index.rst
================================================
======================
xlOil C++
======================

xlOil C++ provides a layer above the `XLL API <https://docs.microsoft.com/en-us/office/client-developer/excel/excel-xll-sdk-api-function-reference>`_
and includes features not available via the XLL API, such as RTD Servers, Ribbon customisation
and event handling.

The xlOil C++ interface has a `doxygen API description <../../doxygen/html/doxygen/index.html>`_.

.. toctree::
    :maxdepth: 4
    :caption: Contents

    GettingStarted
    SpecialArgs
    Events
    ObjectHandles
    CustomGUI
    CppRtd
    DynamicRegistration
    StaticXLLs
    COM


Quick Tour of the Key Classes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ExcelObj - An XLOPER wrapper
----------------------------

An *ExcelObj* is a friendly wrapper around Excel's *xloper12* struct which is the variant type
used to pass arguments in the XLL interface.  An *ExcelObj* it has the same size and *xloper12* so
you can freely cast between the two (although be aware that *ExcelObj* has a destructor).
*ExcelObj* supports a number of variant-like operations: it can be compared to strings or numbers,
converted to a string, and created from values or initialiser lists. However, it's not recommended
to use *ExcelObj* as a generic variant type - reserve it for interaction with the XLL API.

ExcelArray / ArrayBuilder
-------------------------

To **view** a suitable `ExcelObj` as an array, pass it to the `ExcelArray` constructor.  
By default, the array is 'trimmed' to last row and column containing data (i.e. not empty or 
N/A).  `ExcelArray` is a view - it is lightweight but does not own the underlying
data.

The `ArrayBuilder` class constructs arrays to return to Excel. For efficiency (of the CPU not
the programmer!) it requires you to know up-front how many array elements you require and the
total length of all strings in the array.  This may mean you need to make two passes of your 
data, but it saves iterating through the array on destruction. 

PString
-------

Strings in the XLL API are Pascal wide char strings: the first character is the length and 
they are not null terminated.  `PString` wraps such a string and provides a similar interface to 
`std::wstring`.  There's also a `PStringView` type like `std::wstring_view`.

Range / RangeArg / ExcelRef
---------------------------

There are few types of range class with slightly different internals and usages. All behave 
in a "range-like" way, supporting:

    * `(i, j)` - accessor to pick out individual elements
    * `range(fromRow, fromCol, toRow, toCol)` - create a sub-range
    * `value()` - convert to an `ExcelObj` single value or array
    * `address()` - fetch the sheet address as a string 
    * `set(val)` - sets the range values to the given `ExcelObj` (which may be an array)


The `RangeArg` type should only be used to declare an argument to a user-defined worksheet
function.  Specifing this type means that xlOil is allowed to pass range references to your
function.  See :any:`SpecialArgs`.  A `RangeArg` is not directly constructable - you should
convert it to an `ExcelRef` to copy and pass it around.

The `ExcelRef` type is equivalent to an *xltypeRef* `ExcelObj`, that is it points to a 
rectangular space on a specific sheet.  It can be created from an `ExcelObj` which is a 
range reference (typically via `RangeArg.toExcelRef()`) or a sheet address string.

The `Range` type is a virtual base: it may point either to an `ExcelRef` range or a COM 
range object.  Prefer `ExcelRef` when you are sure the range information has been passed via
an XLL worksheet function.


callExcel - calling XLL API functions
-------------------------------------

The XLL SDK docs describe a number of API calls beginning with `xl` such as `xlCoerce` and
`xlSheetNm`. There are also many more poorly documented API calls beginning with `xlc` and 
`xlf`. They can all be found in `xlcall.h`.  Invoking these functions is straightforward:

.. highlight:: c++

::
    
    ExcelObj result = callExcel(msxll::xlSheetId, "Sheet1");


All arguments are automatically converted to `ExcelObj` type where a conversion is possible
before being passed to Excel.  The type of the return value is given in the documentation.

runExcelThread - calling blocked API functions 
----------------------------------------------

Excel's COM API must be called on the main thread, since it's single-threaded apartment.
Breaking this rule may lead to undefined behaviour. In addition, the COM interface must be 'ready'
which means no dialog boxes are open or other tasks which busy the COM interface.

Calls to the XLL API generally also require the main thread (with a few exceptions) and being in 
the correct 'context', that is being in a function invoked by Excel.

The `runExcelThread` function queues a message to a hidden window or an asynchronous procedure call 
(APC) callback which will be executed on the main thread when Excel passes control to windows 
or pumps its message loop respectively (a window message is the default, most responsive choice).

The `runExcelThread` function can retry calls, trying to wait until the COM interface is ready (sadly 
there is no mechanism to allow Excel to inform applications when it is ready to work, you just 
have to keep trying).
 
In addition, setting the `XLL_API` flag runs the callback in the XLL context.

 

================================================
FILE: docs/source/xlOil_Python/BuiltInUDFs.rst
================================================
==================================
xlOil Built-in Worksheet Functions
==================================

The the important ``xloRef`` and ``xloVal`` functions are described at
:ref:`core-cached-objects`

xloPyLoad: import and scan a python module (worksheet function)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. function:: xloImport(ModuleName:str, From=None, As=None)

    Loads functions from a module and registers them in Excel. The functions do not have to be decorated.
    Provides an analogue of `from X import Y as Z`

    ModuleName:
        A module name or a full path name to a target py file. If empty, the workbook module
        with the same name as the calling workbook is (re)loaded.
    From: 
        If omitted, imports the specified module as normal, i.e. :any:`xloil.scan_module` If a 
        value or array, registers only the specified object names.  If "*", all objects are registered.
    To: 
        Optionally specifies the Excel function names to register in the same order as `From`.
        Should have the same length as `From`.

    See :any:`xloil.import_functions`

.. function:: xloAttr(Object, Name:str, *Args, **Kwargs)
    Returns the named attribute value, or the result of calling it if possible. ie, ``object.attr`` 
    or ``object.attr(*args, *kwargs)`` if it is a callable.

    Object: 
        The target object
    Name: 
        The name of the attribute to be returned.  The attribute can be a bound method,
        member, property, method, function or class
    Args
        If the attribute is callable, it will be called using these positional arguments
    Kwargs
        If the attribute is callable, it will be called using these keyword arguments
   
.. function:: xloAttrObj(Object, Name:str, *Args, **Kwargs)
    Returns the value of named attribute or the result of calling the attribute.  Behaves like
    `xloAttr` except always returns a cache object (see :ref:`xlOil_Python/TypeConversion:Cached Objects`).

    This function is useful to stop the default conversion to Excel, for example when returning
    an iterable. A typical use is when chaining `=xloAttrObj` calls.

.. function:: xloPyDebug(Debugger)

    See :ref:`xlOil_Python/Debugging:Selecting the debugger programmatically`

================================================
FILE: docs/source/xlOil_Python/Concepts.rst
================================================
=========================
xlOil Python Concepts
=========================

.. contents::
    :local:


Workbook Modules
----------------

When an Excel workbook is opened, xlOil tries to load the module `<workbook_name>.py` 
(this is configurable).  When registering functions from workbook modules, xlOil defaults 
to making any declared functions :ref:`xlOil_Python/Functions:Local Functions`

The function :any:`xloil.linked_workbook` when called from a workbook module retrieves 
the associated workbook path.


Array Functions
---------------

By default, xlOil-Python converts Excel array arguments to numpy arrays. The conversion
happens entirely in C++ and is very fast.  Where possible you should write functions
which support array processing (vectorising) to take advantage of this, for example
the following works when it's arguments are arrays or numbers:

::

    @xlo.func
    def cubic(x, a, b, c, d)
        return a * x ** 3 + b * x ** 2 + c * x  + d

You can take this further to evaluate polynominals of n-th degree:

::

    @xlo.func
    def poly(x, coeffs: xlo.Array(float)):
        return np.sum(coeffs * x[:,None] ** range(coeffs.T.shape[0]), axis=1)

Specifing that we expect an array argument and the data type of that array avoids the
overhead of xlOil determining the type.  There is a problem with this function:
what happens if ``x`` is two-dimensional?  To avoid this possibility we can specify:

::

    @xlo.func
    def poly(x: xlo.Array(dims=1), coeffs: xlo.Array(float)):
        return np.sum(coeffs * X[:,None] ** range(coeffs.T.shape[0]), axis=1)


Events
------

Events allow for a callback on user interaction. If you are familiar with VBA, you may have used 
Excel's event model already.  Most of the workbook events described in 
`Excel.Appliction <https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)#events>`_
are available in xlOil. 

See :ref:`xlOil_Python/ModuleReference:Events` for more details on python events and :doc:`Events`
for a description of the available Excel events.

Excel events do not use return values.  However, some events take reference parameters. 
For example, `WorkbookBeforeSave` has a boolean `cancel` parameter. Setting this to True cancels the 
save.  As references to primitive types aren't supported in python, in xlOil you need to set this 
value using `cancel.value=True`.

Event handlers are (currently) global to the Excel instance, so you may need to filter by workbook name 
when handling events even if you have hooked the event in a local workbook module.

Examples
~~~~~~~~

::

    def greet(workbook, worksheet):
        xlo.Range(f"[{workbook}]{worksheet}!A1") = "Hello!"

    xlo.event.WorkbookNewSheet += greet


Registering functions in other modules
--------------------------------------

xlOil automatically scans modules when they are imported or reloaded via a
hook in python's import mechanism.  This ensures any :any:`xloil.func` 
decorated functions are registered. 

If you load a module outside the normal ``import`` mechanism, you can tell 
xlOil to look for functions to register with :any:`xloil.scan_module`. 

Also see :any:`xlOil_Python/Functions:Dynamic Registration`, which explains
how any python callable can be registered as an Excel function.


Multiple addins and event loops
-------------------------------

*xlOil_Python* can be used by multiple add-ins, that is, more than one XLL
loader with its own settings and python codebase can exist in the same Excel
session.  

   * Each add-in / XLL is loaded in a background thread equipped with an `asyncio`  
     event loop.  Get the loop using :any:`xloil.get_event_loop`.
   * You can find the addin associated with the currently running code with 
     :any:`xloil.source_addin` .
   * All add-ins share the same python interpreter
   * All add-ins share the python object cache
   * Worksheet functions are executed in Excel's main thread or one of its 
     worker threads for thread safe functions
   * Async / RTD worksheet functions are executed in a dedicated xlOil Core
     event loop which you can access with ``xloil.get_async_loop()``
   * You can ask xlOil to create a separate thread & event loop for an addin.     

Although CPython supports subinterpreters, most C-based extensions, particularly
*numpy* do not, so there are no plans to add subinterpreter support at this stage.


================================================
FILE: docs/source/xlOil_Python/CustomGUI.rst
================================================
==============================
xlOil Python GUI Customisation
==============================

.. contents::
    :local:


Status Bar
----------

Possibly the simplest Excel GUI interaction: writing messages to Excel's status bar:

::

    from xloil import StatusBar

    with StatusBar(1000) as status:
        status.msg('Doing slow thing')
        ...
        status.msg('Done slow thing')

The :any:`xloil.StatusBar` object clears the status bar after the specified number of milliseconds
once the `with` context ends


Ribbon
------

xlOil allows dynamic creation of Excel Fluent Ribbon components. See :any:`concepts-ribbon` for 
background.

::

    gui = xlo.ExcelGUI(r'''<customUI xmlns=...>....</<customUI>''', 
        funcmap={
            'onClick1': run_click,
            'onClick2': run_click,
            'onUpdate': update_text,
        })

The ``gui`` object :any:`xloil.ExcelGUI` holds a handle to a COM addin created to support
the ribbon customisation.  If the object goes out of scope and is deleted by python or if you call 
``gui.disconnect()``, the add-in is unloaded along with the ribbon customisation and any custom task 
panes.

The ``funcmap`` dictionary (or function) links callbacks named in the ribbon XML to python functions. 
Each handler should have a signature like the following:

::

    def ribbon_button_press(ctrl: RibbonControl)
        ...
    def ribbon_callback2(ctrl: RibbonControl, arg1, arg2)
        ...
    def ribbon_get_text_label(ctrl: RibbonControl, *args)
        return "something"
    async def ribbon_callback4(ctrl: RibbonControl, *args)
        ...    

The ``ctrl`` argument points to the control which raised the callback. The number of additional
arguments is callback dependent.  Some callbacks are expected to return a value. 
See `Customizing the Office Fluent Ribbon <https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2007/aa338199(v=office.12)>`_
for a description of the appropriate callback signature.

.. note::

    Callbacks are executed in Excel's main thread unless declared *async*, in which case they will be 
    executed in the addin's event loop.  Async callbacks cannot return values.


Instead of a dictionary, the `funcmap` object can be a function which takes any string and returns a 
callback handler.

See :doc:`ExampleGUI` for an example of ribbon customisation, or look at xlOil's own ribbon in the 
`xloil/xloil_ribbon.py` module.

Setting button images
=====================

Any `getImage` callbacks must return a `PIL Image <https://pillow.readthedocs.io/en/stable/reference/Image.html>`_.
This is converted to an appropriate COM object by xlOil. Instead of using a separate `getImage` callback 
per control, a single `loadImage` attribute can be added:

::

    <customUI loadImage="MyImageLoader" xmlns=...>
        ...
        <button id="AButton" image="icon.jpg" />

The `MyImageLoader` function will be called with the argument `icon.jpg` and be expected to return
a *PIL Image*.


Custom Task Panes
-----------------

`Custom task panes <https://docs.microsoft.com/en-us/visualstudio/vsto/custom-task-panes>`_ are user 
interface panels that are usually docked to one side of a window in the Excel application. They can 
contain a *Qt*, *Tk* or *wx* interface, or any suitable custom COM control. 

Custom task panes are created using the :any:`xloil.ExcelGUI` object. There is no need to create a ribbon 
as well, but task panes are normally opened using a ribbon button, because Excel does not provide a 
default way for users to show or hide custom task panes.

Custom task panes are associated with a document frame window, which presents a view of a workbook 
to the user.  If you want to display a custom task pane with multiple workbooks, create a new instance 
of the custom task pane when the user creates or opens a workbook. To do this, either handle the 
`WorkbookOpen` event, or require the user to press a ribbon button to open a task pane for the active
workbook.

Thread-safety
=============

The :any:`xloil.ExcelGUI` object and custom task panes can be created in any thread (internally they 
re-direct calls to Excel's main thread). Typically GUI creation will be done on xlOil's python loader 
thread, which also contains an *asyncio* event loop. The individual GUI toolkits are generally not 
thread-safe and should only be accessed from dedicated threads which xlOil creates.  This is described 
below per toolkit in more detail.

.. caution:

    If another non-xlOil Excel addin uses the same GUI toolkit, it is very likely that Excel will crash.

Qt Custom Task Panes
====================

Qt support uses *qtpy* which auto-detects the Qt bindings (PySide/PyQt) and standardises the 
small syntactic differences between the libraries.

.. caution::
    You *must* import :any:`xloil.gui.qtpy` before any other use of Qt.  This allows xlOil 
    to create and the *QApplication* on its own thread.

It's common in Qt GUIs to inherit from `QWidget`, so xlOil allows you to create a pane
from a `QWidget`:

::

    import xloil.gui.qtpy
    from qtpy.QtWidgets import QWidget     

    class QtTaskPane(QWidget):
        def __init__(self):
            super().__init__() # Don't forget this!
            ... # some code to draw the widget
        def send_signal(self, int):
            ... # some code to emit a Qt signal

    excelui = xlo.create_gui(...)
    pane = excelui.attach_pane('MyPane', pane=QtTaskPane)

    # The widget is in the pane's `widget` attribute
    pane.widget.send_signal(3) 

The :any:`xloil.ExcelGUI.attach_pane` call creates a task pane with the specified name.  If ``pane`` 
is a *type* which inherits from `QWidget`, it is constructed (on the Qt thread, see below)
and placed in a :any:`xloil.gui.qtpy.QtThreadTaskPane` then attached to the Excel window.

To talk to your widget, it's best to set up a system of Qt 
`signals <https://wiki.qt.io/Qt_for_Python_Signals_and_Slots>`_ as these are thread-safe. 
(Note the `syntax differs slightly in PyQt5 <https://www.pythonguis.com/faq/pyqt5-vs-pyside2/>`_
but it is standardised by *qtpy*) 


Qt Thread-safety
________________

All *Qt* interactions other than signals must take place in the same thread, or Qt
will abort.  xlOil creates a special Qt thread which runs the Qt event loop, and 
constructs any task panes on that thread.

To run commands on xlOil's *Qt* thread, use the :any:`xloil.gui.qtpy.Qt_thread` object

::

    from xloil.gui.qtpy import Qt_thread
    future = Qt_thread().submit(func, *args)        # returns a concurrent.futures.Future
    future2 = Qt_thread().submit_async(func, *args) # returns an asyncio.Future
    future.result()                                 # Blocks if result is required now

You can also use `Qt_thread` as a decorator to wrap the function in a `submit` call, for example:

::

    @Qt_thread
    def some_func():
        ...

Tkinter Custom Task Panes
=========================

We create a class which derives from :any:`xloil.gui.tkinter.TkThreadTaskPane` (which in turn 
derives from :any:`xloil.gui.CustomTaskPane`).  Unlike Qt, it's not (I think) as common to derive
from a *tkinter.Frame* object.

We draw the window into the *tkinter.Toplevel* contained in `self.top_level`.

::
    
    from xloil.gui.tkinter import TkThreadTaskPane, Tk_thread

    class TkTaskPane(TkThreadTaskPane):
    
        @Tk_thread
        def set_x(self, x):
            ...
        
        def __init__(self):
            super().__init__() # Don't forget this!
            
            # This name is picked up by ExcelGUI.attach_pane
            self.name = "MyPane"

            import tkinter as tk
            
            top_level = self.top_level
            # Draw into window
            ...
            

    excelui = xlo.ExcelGUI(xml=..., funcmap=...)
    pane = excelui.attach_pane(TkTaskPane())

    pane.set_x(3)

As *tkinter* does not have thread-safe signals, although it does have events which could be used here, 
but for illustration, we ensure `set_x` is run on the *Tk* thread, by decorating it with 
:any:`xloil.gui.tkinter.Tk_thread`.  The `__init__` method is always called on the *tkinter* thread 
so we don't need to decorate it.

Tkinter Thread-safety
_____________________

The :any:`xloil.gui.tkinter.Tk_thread` function behaves the same as `Qt_thread` described
in :ref:`xlOil_Python/CustomGUI:Qt Thread-safety`. 


wxPython Custom Task Panes
==========================

It's common in wx GUIs to inherit from `wx.Frame`, so xlOil allows you to create a pane
from a `wx.Frame`:

::

    from xloil.gui.wx import wx_thread
    import wx

    class OurWxPane(wx.Frame):
        def __init__(self):
            super().__init__(None, title='Hello')
            ...

        @wx_thread
        def set_progress(self, x: int):
            ...

    excelui = xlo.create_gui(...)
    pane = excelui.attach_pane('MyPane', pane=OurWxPane)

    # The frame is in the pane's `frame` attribute
    pane.frame.set_progress(3)

We ensure `set_progress` is run on the *wx* thread, by decorating it with :any:`xloil.gui.wx.wx_thread`.

wxPython Thread-safety
______________________

The :any:`xloil.gui.wx.wx_thread` function behaves the same as `Qt_thread` described
in :ref:`xlOil_Python/CustomGUI:Qt Thread-safety`. 


Task Pane Events
================

Custom task panes have three events which can be handled by defining methods in the subclass of 
:any:`xloil.gui.CustomTaskPane` used to create the pane. The callbacks occur on Excel's main thread.
The events are:

::

    def on_docked(self):
        # Called when the user docks or undocks the pane. The dock position is in 'self.position'
        ...

    def on_visible(self, state: bool):
        # Called when the user closes/shows the pane with the new visibility in 'state'
        ...

    def on_destroy(self):
        # Called just before the pane is destroyed when the parent window is closed
        super().on_destroy() # Important!
        ...

Task Pane registry
==================

The created task panes are automatically stored in a registry so there is no need to hold a
reference to them.  Task panes are attached by default to the active window and it is possible to 
have multiple windows per open workbook.  xlOil will free the panes when the parent workbook ora
addin closes.

We can search the registry by name for a task pane without having the :obj:`xloil.ExcelGUI` object:

::

    pane = xloil.gui.find_task_pane("MyPane")

By default, xlOil looks for a pane attached to the active window, but this can be changed with
arguments.  It is possible to create multiple panes with the same name, in which case this search
could return either one.


Async GUI Calls
---------------

The above examples create the GUI calls in a synchronous fashion but many of the GUI functions
are or can be async.  Because xlOil loads modules in a background thread, it's not necessary
to do this to keep Excel responsive but it could be useful in some circumstances.

::

    async def make_gui():
    
        # With connect=False the ctor does nothing
        excelui = xlo.ExcelGUI(xml=..., funcmap=..., connect=False)

        # The action happens when we call connect, which returns a awaitable future
        await excelui.connect()

        # We can also create the pane async by passing an awaitable but we have 
        # to then pass the name explictly
        await excelui.attach_pane_async(
            name='TkPane',
            pane=Tk_thread().submit_async(TkTaskPane))

        # We need to keep a reference to 'excelui' as deleting it disconnects the UI
        return excelui, pane


================================================
FILE: docs/source/xlOil_Python/Debugging.rst
================================================
==============================
xlOil Python Debugging
==============================

Only python debuggers capable of handling *embedded* python interpreters can be used to debug xlOil
python code.

Visual Studio
-------------

*Visual Studio 2019* and *Visual Studio 2022* with Python Tools installed can break into xlOil python code. 
Attach to the relevant Excel process selecting *only Python Code* debugging.  

Visual Studio will occasionally hang when first hitting a python breakpoint. In the case, restart VS and
Excel and re-try

.. note::
    As of Aug 2022, mixed mode debugging with both Python and Native C code does not work: Python 
    breakpoints are not hit.


VS Code
-------

*VS Code* can break into xlOil python code. You need to tell xlOil to start a `debugpy` server by
selecting it as the debugger in the xlOil ribbon or the ini file. Then use VS Code's python 
remote debugger to connect.  The default port is *5678* but this can be changed in the ini file.

*VS Code* cannot hit breakpoints in async and RTD functions even though tracing is enabled in the
relevant threads.  The reason for this is unknown.

.. note::
    Running the *debugpy* server has some peformance implications, so avoid leaving debugging 
    enabled when not required.

Pdb
---

Pdb can be used for post-mortem debugging, i.e. after an exception occurs. Select *pdb* in as 
the debugger in the xlOil ribbon or the ini file.  Use the command `breakpoint()` in your 
code to trigger the debugger, or wait for an exception.


Selecting the debugger programmatically
---------------------------------------

A debugger can be selected at runtime in the xlOil ribbon but this choice will persist when Excel
is restarted.  Alternatively, the debugger can be choosen in code, which is not persistent. Use
the following python code:

::

    import xloil.debug
    xloil.debug.use_debugger('pdb')

Or the Excel formula:

::

    =xloPyDebug(...)



================================================
FILE: docs/source/xlOil_Python/DistributingAddins.rst
================================================
=======================================
xlOil Python Distribution and Packaging
=======================================

xlOil supports two possiblilities for distribution:
   * Creating an XLL addin to distribute code to existing xlOil users
   * Packaging Python and xlOil to install code for new users


Creating an Addin
=================

The idea of this approach is to create an XLL addin so users don't have to edit
their `xlOil.ini` to load some packaged code.  

Users of XLL will need access to a python distribution which contains
the *xlOil* package, however they do not need the xlOil addin installed.

At a command prompt, run:

::

    xloil create myaddin.xll

This will create a `myaddin.xll` and `myaddin.ini` in the current directory.
By default, the XLL will try to load `myaddin.py` in the same directory, so 
create this file:

::

    import xloil as xlo

    @xlo.func
    def MySum(x, y, z):
        '''Adds up numbers'''
        return x + y + z

Dropping `myaddin.xll` into an Excel session will create the function ``MySum``.

If the python distribution will be in a standard directory on users' machines,
the `PYTHONEXECUTABLE` and `PATH` environment variables in `myaddin.ini` can
be used to point to it, otherwise these variables can read the python location
from the registry.

If you copy `myaddin.xll`, `myaddin.ini` and `myaddin.py` to your `%APPDATA%\\Microsoft\\Excel\\XLSTART` 
directory, Excel attempts to opens the ini file and py files which is not ideal! xlOil will
look for `myaddin.ini` in `%APPDATA%\\xlOil`, so install the ini to there instead. You'll also need 
to choose a directory to hold `myaddin.py` (or other python modules) and ensure `myaddin.ini` points to 
it; `%APPDATA%\\xlOil\\myaddin` could be a sensible choice.

.. important:: 
    If a user of `myaddin.xll` has an ini file at `%APPDATA%\\xlOil\\xlOil.ini``
    the core xlOil.dll is loaded using those settings before `myaddin.xll`.
    The assumption is that the user has the xlOil addin installed in Excel, but 
    since only one instance of xlOil (and one python interpreter) can be hosted in 
    Excel, one settings file must take precedence. You can make your addin take
    precedence with the `LoadBeforeCore` flag in `myaddin.ini`.


Packaging Python
================

xlOil can use `PyInstaller <https://pyinstaller.org/>`_ to package a python distribution and
create an installer executable.  Support for this is fairly rudimentary at present.

You shouuld start with a minimum python distribution (ideally based on the standard distribution)
for the code you want to distribute, otherwise *PyInstaller* may create a very large output.  The
distribution should include xlOil and be able to load your code in Excel.

To package the settings in the file *myaddin.ini* which loads the python module *excel_funcs.py*, 
run the following command:

::

    xloil package myaddin.ini --hidden-import excel_funcs

Note that *--hidden-import* is actually an `argument to PyInstaller <https://pyinstaller.org/en/stable/usage.html#options>`_
and can be specified multiple times.  Any other trailing arguments will be passed directly to *PyInstaller*.

The resulting *dist* directory will contain:

  * install_main.exe (installs xlOil)
  * _internal (contains the python distribution)

The installer does not copy the python distribution, it is used in-situ


Customising the packaging
-------------------------

Calling 

:: 

    xloil package -makespec myaddin.ini
    
stops the packaging process before after creation of the 
`PyInstaller spec files <https://pyinstaller.org/en/stable/spec-files.html>`_.  You can edit this
spec file directly as described in the *PyInstaller* docs, then invoke *PyInstaller* on the spec file
yourself to finish the process.


================================================
FILE: docs/source/xlOil_Python/Dynamic.rst
================================================
========================================
xlOil Python Dynamic Runtime Interaction
========================================

xlOil function registration can be controlled dynamically at runtime.  Also,
the Excel can be controlled from macros or the console.


.. contents::
    :local:

Dynamic Import
--------------

Functions for registration can be specified at runtime without the need to 
add an :any:`xloil.func` decorator.

.. note::
    Although Excel will let you, avoid doing this from (non-async) worksheet functions
    since creating new functions *during* Excel's calculation cycle is likely to cause
    instability.

The :any:`xloil.import_functions` call provides an analogue of ``from X import Y as Z`` 
with Excel UDFs.  A simple usage is:

::

    xloil.import_functions("c:/lib/AnotherFile.py", names=["greet"], as_names=["PyGreet"])


where AnotherFile.py contains:

::

    def greet(x:str):
        return f"Hello {x}!"

We specify the Excel name of the function explicitly, if we omitted this, the function 
would be registered with its python name.  In Excel you can then use the formula 
``=greet("World")``.

Typing annotations are respected, as are doc-strings - the import behaves as if we had 
decorated the function with :any:`xloil.func`.

In a worksheet, :any:`xloil.import_functions` is exposed as ``xloImport`` with the same 
arguments.

Since the import machinery can register *any* callable, including class constructors,
you cane be a little creative.  For example, the following cell formulae will
create a *pandas* *DataFrame* from the range `C1:F5`, sum over rows and take the average
of the result.

::

    [A1] : =xloImport("pandas","DataFrame")

    [A2] : =DataFrame(C1:F5)

    [A3] : =xloAttr(xloAttrObj(A2,"sum",{"axis",1}), "mean")


Notice we used ``xloAttrObj`` - the output of this is always a cache reference.  This stops 
xlOil from trying to convert the result to an Excel value.  Since a *DataFrame* is iterable
it would otherwise output *DataFrame.index* as an array.  Also note the convenient use of
`array constants <https://support.microsoft.com/en-us/office/use-array-constants-in-array-formulas-477443ea-5e71-4242-877d-fcae47454eb8>`_
to specify keyword arguments.


Dynamic Registration
--------------------

Functions can be registed using :any:`xloil.register_functions` and deregistered
with :any:`xloil.deregister_functions`.

For example:

::

    def Greet(x):
        return f"Hello {x}"
    
    xlo.register_functions([Greet])

Any callable can be registered, for example:

::

    class Closure:
        self._total = 0
        def __call__(self, x):
            self._total += x
            return x
    
    xlo.register_functions(Closure())

The name and help of the function can be controlled using :any:`xloil.func`
and the function can be linked to a specific python module, which means
it will be removed if the module is unloaded or reloaded.

::

    xlo.register_functions(
        [xlo.func(fn=Closure(), name=f"Dynamic1", register=False)], 
        module=sys.modules[__name__])

Functions are deregistered by name:

::

    xlo.deregister_functions("Greet")


================================================
FILE: docs/source/xlOil_Python/Example.rst
================================================
======================
xlOil Python Examples
======================

This is code for the xlOil python test spreadsheet. You can find the associated sheet at 
:ref:`core-example-sheets`.

.. literalinclude:: /../../tests/AutoSheets/PythonTest.py



================================================
FILE: docs/source/xlOil_Python/ExampleGUI.rst
================================================
=========================
xlOil Python GUI Examples
=========================

This is code for the xlOil python test spreadsheet. You can find the associated sheet at 
:ref:`core-example-sheets`.

.. literalinclude:: /../../tests/ManualSheets/python/PythonTestUI.py



================================================
FILE: docs/source/xlOil_Python/ExampleRTD.rst
================================================
=========================
xlOil Python RTD Examples
=========================

This is code for the xlOil python test spreadsheet. You can find the associated sheet at 
:ref:`core-example-sheets`.

.. literalinclude:: /../../tests/ManualSheets/python/PythonTestAsync.py



================================================
FILE: docs/source/xlOil_Python/ExcelApplication.rst
================================================
==========================================
xlOil Python: The Excel.Application object
==========================================

.. contents::
    :local:

Introduction
------------

The `Excel.Application` object is the root of Excel's COM interface.  If you have used VBA you 
will likely have come across it.  If xlOil is running embedded in Excel, you can get a reference 
to the parent application with :any:`xloil.app`.  If xlOil has been imported as package, you can 
create an Application with :any:`xloil.Application`.

xlOil mirrors a small part of the `Excel.Application` object model as discussed below. For other calls,
the COM interface can be accessed directly which provides syntax similar to the `Application`` object in 
VBA.

.. important:: 
    All COM calls must be invoked on the main thread!  A function runs in the main thread if is 
    not declared multi-threaded or if it is called from VBA or the GUI. However during Excel's calc
    cycle, much of the Application object model is locked, in particular, writing to the sheet is blocked.
    To schedule a callback to be run on main thread use :any:`xloil.excel_callback`.

The object model is documented extensively at `Excel object model overview <https://docs.microsoft.com/en-us/visualstudio/vsto/excel-object-model-overview>`_
and `Application Object <https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)>`_


Calling Worksheet Functions and Application.Run
-----------------------------------------------

In VBA, ``Application.Run`` takes a function name and a variable argument list and attempts
to call the specified user-defined function.  In xlOil, use :obj:`xloil.run` to make the same 
call or go via the COM library with ``xloil.app().Run(...)``. All COM calls must be invoked
on the main thread, however :obj:`xloil.run` and :obj:`xloil.call` have async flavours 
:obj:`xloil.run_async` and :obj:`xloil.call_async` which return a Future and can be called 
from any thread.

To call a worksheet function, use :obj:`xloil.call`. This can also invoke old-style 
`macro sheet commands <https://docs.excel-dna.net/assets/excel-c-api-excel-4-macro-reference.pdf>`_.
It must be called from **a non-local worksheet function**.  Worksheet functions can be
called from COM, for example, ``xloil.app().WorksheetFunction.Sum(...)``.

+-------------------------------+---------------------------------------------------------+------------------------------+
| Function                      |  Use                                                    | Call from                    |
+===============================+=========================================================+==============================+
| :obj:`xloil.run`              | Calls user-defined functions as per `Application.Run`   | Main thread                  |
+-------------------------------+---------------------------------------------------------+------------------------------+
| :obj:`xloil.run_async`        | (as above but async)                                    | Anywhere                     |
+-------------------------------+---------------------------------------------------------+------------------------------+
| :obj:`xloil.call`             | Calls worksheet functions, UDFs or macro sheet commands | Non-local worksheet function |
+-------------------------------+---------------------------------------------------------+------------------------------+
| :obj:`xloil.run_async`        | (as above but async)                                    | Anywhere                     |
+-------------------------------+---------------------------------------------------------+------------------------------+
| xloil.app().WorksheetFunction | Calls worksheet functions                               | Main thread                  |
+-------------------------------+---------------------------------------------------------+------------------------------+

xlOil's Excel Object Model
--------------------------

xlOil mirrors a small part of the `Excel.Application` object model to faciliate easier access to the commonly 
used :obj:`xloil.Application`, :obj:`xloil.Workbook`, :obj:`xloil.Worksheet`, :obj:`xloil.ExcelWindow`, and 
:obj:`xloil.Range` objects.

Each of xlOil's application objects provides a `to_com` method which accepts an optional *lib* argument. 
Calling this returns a marshalled COM object which supports any method or property in the full Application object 
model. COM support is be provided by `comtypes <https://pythonhosted.org/comtypes/>`_ , a newer pure 
python package or `win32com <http://timgolden.me.uk/pywin32-docs/html/com/win32com/HTML/docindex.html>`_ 
a well-established C++ based library.  If omitted, the default is 'win32com'. The default can be changed 
in the XLL's ini file.

COM methods can be called directly on xlOil's application objects, so the following are equivalent:

::

    xlo.Application().RegisterXLL(...)
    xlo.Application().to_com().RegisterXLL(...)

There is no ambiguity with other methods on the *Application* object as COM methods and properties 
all start with a capital letter.

COM methods can be called with keyword arguments - note COM arguments start with a capital letter.

::

    xloil.app().Selection.PasteSpecial(Paste=xloil.constants.xlPasteFormulas)


Excel Automation
----------------

Excel's COM interface allows the application to be driven externally by a script. This is best explored
by looking at (a simplified version of) xlOil's test runner.  The test runner is started at the command line,
rather than inside an Excel instance like an xlOil-based addin.  You may want to look at the documentation
for Excel's `Name <https://docs.microsoft.com/en-us/office/vba/api/excel.name>`_ object.

::

    import xloil as xlo

    # Create a new Excel instance and make it visible
    app = xlo.Application()
    app.visible = True

    # Load addin
    if not app.RegisterXLL("xloil.xll"):
        raise Exception("xloil load failed")

    test_results = {}
    for filename in ['TestUtils.xlsx, PythonTest.xlsm']:

        # Open the workbook in readonly mode: don't change the test source!
        wb = app.open(filename, read_only=True)
    
        app.calculate(full=True)

        # Loop through all named ranges in the workbook, looking for ones 
        # prefixed with 'Test_'.  We expect those ranges to contain True
        # for a successful test outcome.
        names = wb.to_com().Names
        for named_range in names:
            if named_range.Name.lower().startswith("Test_"):
                # skip one char as RefersTo always starts with '='
                address = named_range.RefersTo[1:]
                test_results[(filename, named_range.Name)] = wb[address].value
        
        wb.close(save=False)

    app.quit()

    if not all(test_results.values()):
        print("-->FAILED<--")


Creating an Application
=======================

The :any:`xloil.Application` object can be created in several ways:

    1) When xloil is embedded, the parent applicaton object is in :any:`xloil.app()`
    2) `xlo.Application()` with no arguments opens an new instance of Excel (but does not make it visible)
    3) `xlo.Application("MyWorkbook.xlsx")` returns an instance of Excel which has *MyWorkbook.xlsx* open (or throws)
    4) `xlo.Application(ComObject)` points an Application at a COM object managed by *win32com* or *comtypes*
    5) `xlo.Application(HWND)` creates a Application given the window handle of Excel's main window as an int

The application object can be :any:`xloil.Application.quit()` manually or since it is a context manager, 
you can write:

::

    with xloil.Application() as app:
        # do stuff
        ...

    # app has been quit without saving any open Workbooks


Accessing Sheets and Ranges
---------------------------

When xlOil is embedded in Excel as an addin, there is a natural default :obj:`xloil.Application` 
object: the parent application, which can be accessed by :any:`xloil.app()`.  Additionally,
when embedded you can unambigiously create :any:`xloil.Range` and :any:`xloil.Worksheet` objects
without needing to specify the application.

Reading from a Range
====================

::

    import xloil as xlo

    # if xlOil is embedded: no need to specify Application.
    # Returns a numpy array
    xlo.Range("A1:C1").value

    # Above is equivalent to
    xlo.app().range("A1:C1").value

    # Using COM (win32com) to access a range with empty index
    # Returns a tuple rather than a numpy array
    xlo.app().Range("A1", "C1").Value

If the range referred to is empty, its `value` array will be populated with `None`. This 
is different to array/range arguments to :any:`xloil.func` worksheet functions where the
array is trimmed to the last non-blank. This behaviour can be replicated with 
:any:`xloil.Range.trim` :

::

    r = xlo.app().range("A1:C1")

    r.clear()
    r.trim().value  # returns the array [None]

    r.set(1)
    r.trim().value # returns the array [1, 1, 1]

The square bracket (getitem) operator for a Range behaves like a numpy array,
in that if the tuple specifies a single cell, it returns the value in that cell, otherwise 
it returns a :any:`xloil.Range` object.  To create a range consisting of a single cell
use the `cells` method.

Writing to a range
==================

::

    # Using the COM object
    xlo.app().Range("A1", "B2").Value = ((1, 2), (3, 4))

    rng = xlo.Range("A1:B2")
    # Using xlOil syntax (can use numpy array)
    rng.value = np.array([[1, 2], [3, 4]])

    # Set the entire range to a single value
    rng.set("hello")

    # Add something
    rng += " world!"


Writing a cell formula
======================

Use the  :any:`xloil.Range.formula` property to set or retrieve the formula in a cell

::

    xlo.app().Range("A1").formula = '=SUM(B1:B10)'
    xlo.log(xlo.app().Range("A1").has_formula)  # Will write True

When write addresses used in formula strings, :any:`xloil.Address` can be useful e.g.:

::
    
    sum_start_row=0
    sum_end_row=9
    address = xlo.Address((sum_start_row, 1, sum_end_row, 1), sheet="Sheet1")
    xlo.app().Range("A1").formula = f'=SUM({address})'  # Will be '=SUM(Sheet1!B1:B10)'


Since the introduction of dynamic arrays, array formulae have become largely obselete, but it
is possible to set them with :any:`xloil.Range.set_formula`.


Using Worksheets and Workbooks
==============================

There are several ways to address or refer to part of a worksheet:

::

    wb = xloil.active_workbook()  # Only available when embedded

    # Specify external Excel range address
    r1 = xlo.app().range[f'{wb.name}Sheet1!B2:D3']

    # Specify workbook Excel range address
    r1 = wb['Sheet1!B2:D3']

    # Specify worksheet, then local Excel range address
    ws = wb['Sheet1']
    r1 = ws['B2:D3']
    
    # The range function, like in Excel includes right and left hand ends
    r2 = ws.range(from_row=1, from_col=1, to_row=2, to_col=3)

    # The slice syntax follows python conventions so only the left
    # hand end is included
    r3 = ws[1:3, 1:4]


The square bracket (getitem) operator for :any:`xloil.Worksheet` always returns
a :any:`xloil.Range`. For :any:`xloil.Workbook` it may return a :any:`xloil.Range`
or a :any:`xloil.Worksheet`.

Writing to a worksheet
~~~~~~~~~~~~~~~~~~~~~~

::

    data = np.array([[1, 2], [3, 4]])

    ws = xloil.worksheets['Sheet1']

    # ws[...] gives a Range, so  
    ws["A1:B2"].value = data

    # However, value is optional when writing to a sheet
    ws["A1:B2"] = data  

    # You can copy another part of the sheet, it's faster to
    # drop the value property here
    ws["A1:B2"] = ws["D1:E2"] 

    # Also works for Workbooks
    wb = xloil.active_workbook()
    wb['Sheet1!B2:D3'] = ws["D1:E2"] 



Pausing Excel Calculations
--------------------------

When writing to worksheets, performance can often be improved by disabling Excel's auto calculation 
and Event model, otherwise calculation cycles and events will be triggered on each write.

This is straightforward using :any:`xloil.PauseExcel`:

::

    with xloil.PauseExcel() as paused:
        for i in range(100):
            worksheet[i, 1].value = i


The context manager can be replicated manually with

::

    try:

        xloil.app().ScreenUpdating = False
        xloil.app().EnableEvents = False
        xloil.app().Calculation = xloil.constants.xlCalculationManual

        ...

    finally:
    
        xloil.app().ScreenUpdating = True
        xloil.app().EnableEvents = True
        xloil.app().Calculation = xloil.constants.xlCalculationAutomatic


Troubleshooting
---------------

Both *comtypes* and *win32com* have caches for the python code backing the Excel object model. If 
these caches somehow become corrupted, it can result in strange COM errors.  It is safe to delete 
these caches and let the library regenerate them. The caches are located at:

   * *comtypes*: `<your python install>/site-packages/comtypes/gen`
   * *win32com*: run ``import win32com; print(win32com.__gen_path__)``

See `for example <https://stackoverflow.com/questions/52889704/>`_

Note: as of 25-Jan-2022, *comtypes* has been observed to give the wrong answer for a call to
`xloil.app().Workbooks(...)` so it is no longer used as the default whilst this is investigated.


================================================
FILE: docs/source/xlOil_Python/ExternalPackages.rst
================================================
=============================
xlOil Python Package Support
=============================

xlOil has built-in converters for several external libraries

.. contents::
    :local:


Pandas
------

Pandas support can be enabled in *xlOil* with:

::

    import xloil.pandas

This registers a return converter which allows pandas dataframes to be returned
from Excel functions in a natural table format.  Not if a function always returns 
a dataframe it is more performant to specify  ``pandas.DataFrame`` as the return type
annotation.

The annotation ``pandas.DataFrame`` can also be used for arguments. The converter by 
default expects a two dimensional array with headings in the first row.

To gain more control over the *DataFrame* conversion, use the annotion 
`xloil.pandas.PDFrame`.  Examples:

::

    @xlo.func
    def getDataField(data: PDFrame(headings=True), columns) -> PDFrame(headings=False):
        return data[columnName]

    @xlo.func
    def readDatedData(df: PDFrame(headings=True, index=['Date', 'Type'], dates=['Date'])):
        # df will have a pandas.MultiIndex index
        return df


The parameters have slightly different interpretations when reading or outputting arguments.

The `headings`` parameter when reading, if True, interprets the first row as column heading or 
if it is an int inperets the first *N* rows as a *pandas.MultiIndex* heading.  When outputting, 
if it is True/False outputs column headings or not.

The `index`` parameter when reading specifies column(s) which should be set as the index: xloil 
calls `DataFrame.set_index(<index>)`, so a column name or list-like of columns names can be 
given.  When writing: if *index* is set to False, the index is not output, otherwise it is.

The `dates` parameters specifies which columns to convert from from Excel serial date numbers 
to *numpy.datetime64*. Since Excel stores dates as floating points it is not possible for
xlOil to identify date columns automatically.  This parameter has no effect when outputting as 
*datetime* arrays are converted automatically.

We can call the *PDFrame* converter in the function itself if we want to control the arguments
passed to it based on the function's inputs (this isn't possible if it is used as a decorator).

::

    @xlo.func
    def dFrameMultiHeadings(
            df: PDFrame(headings=2),
            outputHeadings=False):
        return PDFrame(headings=outputHeadings)(df)


See :doc:`Example` for more examples.

Matplotlib
----------

Importing ``xloil.matplotlib`` defines a return converter so matplotlib figures
can be returned from worksheet functions.  By default they are resized to the cell.
Subseqent figures returned from the same cell overwrite previous ones.
Returning a figure requires setting ``macro=True`` in the :obj:`xloil.func` declaration.

::

    import xloil.matplotlib
    from matplotlib import pyplot
    
    @xlo.func(macro=True)
    def pyTestPlot(x, y, **kwargs):
        fig = pyplot.figure()
        ax.plot(x, y, **kwargs)
        return fig

    @xlo.func(macro=True)
    def pyTestPlot(x, y, width, height, **kwargs):
        fig = pyplot.figure()
        ax.plot(x, y, **kwargs)
        return xloil.matplotlib.ReturnFigure(size=(width, height), pos='top')(fig)

PIL / pillow
------------

Importing ``xloil.pillow`` defines a return converter so PIL images
can be returned from worksheet functions.  By default they are resized to the cell.
Subseqent images returned from the same cell overwrite previous ones.
Returning an image requires setting ``macro=True`` in the :obj:`xloil.func` declaration.

::

    import xloil.pillow
    from PIL import Image

    @xlo.func(macro=True)
    def pyTestPic():
        im = Image.open("MyPic.jpg")
        return im


================================================
FILE: docs/source/xlOil_Python/FAQ.rst
================================================
======================
xlOil Python Questions
======================

.. contents::
    :local:


ImportError: Typelib different than module
------------------------------------------

When using `comtypes` for COM support, then auto-generated modules can go out of sync, for example, if
you upgrade `comtypes`.  Fix this at a command prompt with 

.. highlight:: dosbatch

:: 

    C:\ > where clear_comtypes_cache.py
    C:\MyPythonDist\Scripts\clear_comtypes_cache.py
    C:\ > python C:\MyPythonDist\Scripts\clear_comtypes_cache.py -y

You'll probably need to restart Excel.


Intellisense / Function Context Help
------------------------------------

To activate pop-up function help, follow the instructions here: :any:`concepts-intellisense`.


Auto-reload doesn't reload a module
-----------------------------------

xlOil only watches for changes in modules which contain :any:`xloil.func` regisrations: it does
not do a deep scan / reload of all dependent modules as this could include large portions of your
python distribution!

Dynamically Resized Arrays
--------------------------

This is available in Office 365.  It would be possible to replicate this behaviour in older Excel 
versions however it is somewhat tricky, as the output ranges are not 'protected' as they are with 
array formulae or with the Office 365 support.  The code would need to:
 
    1. Hook the *AfterCalculate* event.
    2. Remember which functions output arrays in the current calc cycle and their calling cell.
    3. Remember which functions output arrays in the previous calc cycle and their calling cell.
    4. On *AfterCalculate*, loop through the functions in (2) writing their array to the worksheet.
    5. When writing the array, take care to clear any previous result from (3) but not to overwrite
       any other non-empty cells.
    6. Clear the ranges for functions in (3) but not in (2).
    7. Carefully handle the case where the output range for a function in (3) has been edited, for example
       it may now contain a function in (2)!

Unlike the built-in support in Office 365, the written arrays would be static data so, for example,
function dependency tracing would not work on them (except the top left entry).


This application failed to start because it could not find or load the Qt platform plugin "windows"
---------------------------------------------------------------------------------------------------

Under Anaconda (and possibly other distributions), Qt is installed outside the usual site-packages 
location.  A *qt.conf* file in the root dir directs Qt to the correct place. However under Windows, 
Qt will only look for this file in the directory returned by GetModuleFileName or in :/qt/etc/ which 
is unlikely to exist or be easily creatable on Windows.  (See https://doc.qt.io/qt-6/qt-conf.html)
In our case GetModuleFileName always returns Excel.exe.

xlOil attempts to work around this by passing the correct location to Qt on start up, however for 
non-standard locations like virtual environments it may be necessary to set the 
`QT_QPA_PLATFORM_PLUGIN_PATH` environment variable explicitly in xlOil.ini.  If `QT_QPA_PLATFORM_PLUGIN_PATH`
is set, xlOil will not try to workaround this issue, so verify the value of this variable in the
lauching environment.


win32com / pythoncom: <some CLSID> has no attribute 'CLSIDToClassMap' 
----------------------------------------------------------------------

The cache used by *win32com* has somehow gone wrong. Deleting the cache dir will cause a rebuild
which usually resolves the issue.  The location of this directory can be discovered with

::

    python -c "import win32com; print(win32com.__gen_path__)"

Either delete the entire *gen_py* directory or just the subdirectory corresponding to the CLSID
which is indicated in the error.


Could not connect COM: trying again in 1 second
-----------------------------------------------

If this appears frequently in your log file, it may be because Excel is not opening a blank 
workbook on load.  It is a long-standing Excel bug that the COM server is not properly 
started until a workbook is opened: xlOil needs this COM server to register ribbon components,
so waits in a loop until is is available.  To make Excel open a blank workbook on load (the
pre-Office 2016 behaviour), go to the *File* menu, then *Options*, under *General*, find
*Start up options*, uncheck the "Show the Start screen when this application starts" box.


================================================
FILE: docs/source/xlOil_Python/Functions.rst
================================================
==================================
xlOil Python Registering Functions
==================================

.. contents::
    :local:

There are several ways a python function can be registered with Excel via arguments to 
:any:`xloil.func` decorator.

::

    @xloil.func
    def Greeting(who):
        return "Hello  " + who


Local Functions
---------------

When registering functions from :ref:`xlOil_Python/Concepts:Workbook Modules`, xlOil defaults to making
any declared functions "local": this means their scope is limited to the workbook.
It also means the function is automatically macro-type (xlOil achieves this by creating 
a VBA stub to invoke them).

This behaviour can be overriden by `local` argument:

::

    @xloil.func(local=False)
    def Greeting(who):
        return "Hello  " + who


Local functions have some limitations compared to global scope ones:
- No native async or threadsafe, but RTD async is OK
- Slower due to the VBA redirect
- Associated workbook must be saved as macro-enabled (xlsm extension)
- No function wizard help, but CTRL+SHIFT+A to show argument names is available

(Technical note: It is possible to use the Application.MacroOptions call to add help to the 
function wizard for VBA, but identically named functions will conflict which rather defeats 
the purpose of local functions).


Async and RTD Functions
-----------------------

RTD (real time data) functions are able to return values independently of Excel's 
calculation cycle and correspond to `async generators <https://www.python.org/dev/peps/pep-0525/>`_
in python.  For example, the function below returns the time every two seconds:

::

    import xloil, datetime, asyncio

    @xloil.func
    async def pyClock():
        while True:
            await asyncio.sleep(2)
            yield datetime.datetime.now()

This is discussed in detail in :ref:`xlOil_Python/Rtd:Introduction`.


Commands, Macros & Subroutines
------------------------------

'Macros' in VBA are declared as subroutines (``Sub``/``End Sub``) and do not return a value. 
These functions run outside the calculation cycle, triggered by some user interaction such
as a button.  They run on Excel's main thread and have full permissions on the Excel object 
model.  In the XLL interface, these are called 'commands' in the XLL interface and xlOil uses 
this terminology.

Programs which heavily use the :ref:`xlOil_Python/ExcelApplication:Introduction` object model are usually written as 
commands.

::

    @xloil.func(command=True)
    def pressRunTests():

        r = xloil.Range("TestArea")
        r.clear()
        r.set("Foo")

        ...

If not :ref:`xlOil_Python/Functions:Local Functions`, XLL commands are hidden and not displayed in 
dialog boxes for running macros, such as Excel's macro viewer (Alt+F8). However their 
names can be entered anywhere a valid command name is required, including in the macro
viewer.


Multi-threaded functions
------------------------

Declaring a function re-entrant tells Excel it can be called on all of its calculation
threads simultaneously - any other function is invoked on the main thread.  

:ref:`xlOil_Python/Functions:Local Functions` cannot be declared re-entrant.

Since python (at least CPython) is single-threaded there is no direct performance
benefit from enabling this. However, if you make frequent calls to C-based libraries 
speed gains may be possible.

::

    import xloil, ctypes

    @xloil.func(local=False, threaded=True)
    def threadsafe(x: float) -> int:
        # Do lots of calculations
        ...
        # Return the thread ID to prove the functions were executed on different threads
        return ctypes.windll.kernel32.GetCurrentThreadId(None)


Dynamic Registration
--------------------

Functions for registration can be specified at runtime without the need to decorate them
with :any:`xloil.func`. 

.. note::
    Although Excel will let you, avoid doing this from (non-async) worksheet functions
    since creating new functions *during* Excel's calculation cycle is likely to cause
    instability.

The :any:`xloil.import_functions` call provides an analogue of ``from X import Y as Z`` 
with Excel UDFs.  A simple usage is:

::

    xloil.import_functions("c:/lib/AnotherFile.py", names=["greet"], as_names=["PyGreet"])


where AnotherFile.py contains:

::

    def greet(x:str):
        return f"Hello {x}!"

We specify the Excel name of the function explicitly, if we omitted this, the function 
would be registered with its python name.  In Excel you can then use the formula 
``=greet("World")``.

Typing annotations are respected, as are doc-strings - the import behaves as if we had 
decorated the function with :any:`xloil.func`.

In a worksheet, :any:`xloil.import_functions` is exposed as ``xloImport`` with the same 
arguments.

Since the import machinery can register *any* callable, including class constructors,
you cane be a little creative.  For example, the following cell formulae will
create a *pandas* *DataFrame* from the range `C1:F5`, sum over rows and take the average
of the result.

::

    [A1] : =xloImport("pandas","DataFrame")

    [A2] : =DataFrame(C1:F5)

    [A3] : =xloAttr(xloAttrObj(A2,"sum",{"axis",1}), "mean")


Notice we used ``xloAttrObj`` - the output of this is always a cache reference.  This stops 
xlOil from trying to convert the result to an Excel value.  Since a *DataFrame* is iterable
it would otherwise output *DataFrame.index* as an array.  Also note the convenient use of
`array constants <https://support.microsoft.com/en-us/office/use-array-constants-in-array-formulas-477443ea-5e71-4242-877d-fcae47454eb8>`_
to specify keyword arguments.

More controlled registration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:any:`xloil.register_functions`

::

    class Closure:
        self._total = 0
        def __call__(self, x):
            self._total += x
            return x
    
    funcs.append(
        xlo.func(fn=Closure(), name=f"dynamic1", register=False)
        )

    xlo.register_functions(funcs, sys.modules[__name__])

  Loads functions from the specified source and registers them in Excel. The functions
        do not have to be decorated, but are imported as if they were decorated with ``xloil.func``.
        So if the functions have typing annotations, they are respected where possible.

        This function is intended 

    Imports the specifed python module and registers any it for xloil 
    functions it contains.  Leaving the argument blank loads or reloads the
    workbook module for the calling sheet, i.e. the file `WorkbookName.py`.

================================================
FILE: docs/source/xlOil_Python/GettingStarted.rst
================================================
=========================
xlOil Python Introduction
=========================

.. contents::
    :local:

Introduction
------------

The Python plugin for xlOil primarily allows creation of Excel functions and macros 
backed by Python code. In addition it offers full control over GUI objects and an 
interface for Excel automation: driving the application in code.

When loaded by xlOil, *xlOil_Python* loads specified python modules, looking for functions 
to add to Excel's global name scope, like an Excel addin.  The plugin can also look for modules 
of the form <workbook_name>.py and load these too, this is like creating a VBA code module for 
a workbook. Any python module which contains Excel functions is watched for file modifications so 
code changes are reflected immediately in Excel.

*xlOil_Python* is tightly integrated with numpy, allowing creation of fast Excel array 
functions.

*xlOil_Python* can be imported in python code to allow remote control of an Excel application.
See :doc:`ExcelApplication`

For examples of worksheet functions and GUI controls have a look at :doc:`Example` and
:ref:`core-example-sheets`.

Getting Started
---------------

**You must use the same bit-ness of python and Excel**.  So if your Excel is 32-bit, you must
install xloil using a 32-bit python distibution.

Run the following at a command prompt with python environment settings:

::

    pip install xlOil
   
xlOil can now be imported to allow remote control of an Excel application.  See :doc:`ExcelApplication`

To install the addin which allows you to create python-based Excel functions, type:

::

     xloil install

This call registers the xlOil addin with Excel and places a settings file at
`%APPDATA%/xlOil/xlOil.ini`.  The settings file describes the python modules 
which will be loaded and sets the paths to the python distribution. xlOil should 
set the python paths automatically, but they can be overriden if required.

To test the setup, you can try the python example sheet: :ref:`core-example-sheets`.

.. note:: 
    It's not necessary for ``xlOil.xll`` to be registered in this way: you can just
    drop it into your Excel session when required. 

You now have three ways to get xlOil to load your python code.


My first xlOil module
~~~~~~~~~~~~~~~~~~~~~

Create a `MyTest.py` file with the following lines:

::

    import xloil as xlo

    @xlo.func
    def Greeting(who):
        return "Hello  " + who

Open Excel and use the *xlOil* ribbon toolbar to ensure the search paths include
the directory containing `MyTest.py`.  Then add 'MyTest' to the *Load Modules* 
field, separating entries with a comma. The order of these steps matters because 
editing the *Load Modules* field triggers a load of all newly added modules.

Call the `=Greeting("world")` function in a cell.


My first workbook module
~~~~~~~~~~~~~~~~~~~~~~~~

Create an Excel workbook called `MyBook`. In the same directory, create a
file `MyBook.py` containing the following:

::

    import xloil as xlo

    @xlo.func
    def Adder(x, y):
        return x + y

You need to open and close `MyBook` in Excel for xlOil to find the python file.
Now try invoking the `=Adder()` function - it can also add arrays!

If this isn't working, ensure that "Trust access to the VBA object model" is
checked in *Excel Options -> Trust Centre -> Macro Settings* - this setting
is off by default.

Using the Ribbon
----------------

xlOil's Ribbon toolbar can:

    * Change the python environment (reqires restart)
    * Select modules to load at startup and *sys.path* to set
    * Open the log file
    * Open a console to interact with the embedded python environment
    * Choose a debugger, see :ref:'xlOil_Python/Debugging'
    * Select date formats to use when parsing strings

The toolbar edits the settings file so that changes persist.  The ribbon is enabled by
but can be disabled by removing it from the specified *Load Modules*.

.. note::

    If you have an old ini file (prior to v0.15), you will need to upgrade it to use the  
    ribbon toolbar. Remove the old ini file and remove/install xlOil.

Troubleshooting
---------------

If xlOil detects a serious load error, it pops up a log window to alert you (this can
be turned off). If it succesfully loaded the core DLL a log file will also be created
in `%APPDATA%/xlOil` next to `xlOil.ini`.  The worksheet function `=xloLog()` will tell 
you where this file is.

Normally a python distribution or environment can be loaded with only the location of 
*python.exe* passed via the `PYTHONEXECUTABLE` environment varaible.  For more complex
setups, you may need to set the python paths, i.e. `PATH` and `PYTHONPATH` and maybe even 
`PYTHONHOME`, in the `xlOil.ini` file for xlOil to load your python distribution.

If the xlOil ribbon does not appear, check that `xloil.xloil_ribbon` appears in the
*LoadModules* key in the ini file.

Intellisense / Function Context Help
------------------------------------

To activate pop-up function help, follow the instructions here: :any:`concepts-intellisense`.


================================================
FILE: docs/source/xlOil_Python/Jupyter.rst
================================================
=========================
xlOil Jupyter Interaction
=========================

.. contents::
    :local:
    
Introduction
------------

xlOil can connect to a Jupyter python kernel, allowing interaction between a Jupyter notebook 
and Excel.  To use this functionality, either run `=xloPyLoad("xloil.jupyter")` in a cell or
load the `xloil.jupyter` module by specifying it in the `xlOil.ini` file:

::

    ...

    [xlOil_Python]
    LoadModules=["xloil.jupyter"]

To establish the connection, call the `xloJpyConnect` function. You pass it one of the following:

   1. The name of a notebook e.g. `MyBook.ipynb`. In this case all local jupyter instances
      will be searched to find which one has this notebook open.
   2. The full URL to the notebook, e.g. 
      `http://localhost:8888/notebooks/MyBook.ipynb?token=ac3894ab667fa1f3e4f7fe473fa89566a1580cdb49a2649b`
   3. The `kernel-xxxx-xxx-xxx.json` file which is specified in the output of running 
      the magic `%connect_info` in a Jupyter cell (no file path is required).

The `xloJpyConnect` function will return a cache reference.

.. note:: 

    The targeted jupyter kernel can be running any version of Python 3 and does not need to
    to have the `xloil` package installed.


Registering an Excel function from Jupyter
------------------------------------------

After the connection is estabilished, any function created in the kernel and decorated with
`@xloil.func` will be registed in Excel just as if it had been loaded by xlOil in the normal way.
The function will be run in the context of the kernel and the result returned asynchronously 
to Excel.

.. note:: 

    Any `@xloil.func` declarations prior to connection will be ignored, so part of the 
    jupyter notebook may need to be re-calculated to ensure functions are registed


Watching a variable in a Jupyter notebook
-----------------------------------------

The function `=xloJpyWatch(Connection, VarName)` can dynamically capture the value of any 
global variable in the kernel.  It is an RTD function so automatically updates when the variable
is changed.

Running code in the kernel
--------------------------

Calling `xloJpyRun` executes the provided string as python code in the kernel, captures the 
result and returns it to Excel.  xloJpyRun processes the code string as a `format` string using  
passing the *repr* of any additional arguments, that is, it executes 
`code_string.format(repr(arg1), repr(arg2), ...)`

Examples
--------

In an Excel cell enter:

::

    =xloJpyRun(<connection>, "{} + {}", 3, 4)


Execute the following in a jupyter cell in a connected notebook:

::

    @xloil.func
    def jptest(x):
        return f"Jupyter says {x}"

When xlOil connects to the kernel it will automatically import xlOil, although it does 
not cause a problem if re-imported.

Now try entering `=jptest("hi")` in Excel!


Using COM Automation
--------------------

If the *jupyter* kernel has the *xloil* package installed, we can turn the tables on the 
connected Excel application and control it using COM automtion. Executing the following
in the jupyter kernel will add a new workbook to the connected Excel:

::

    app = xloil.app()
    app.workbooks.add()

See :ref:`xlOil_Python/ExcelApplication:Introduction` for full details on the :any:`xloil.Application` 
object and COM automation support.


Limitations
-----------

Functions declared in the kernel cannot specify the `async` or `rtd` arguments: they are 
automatically of RTD async type to stop the kernel blocking Excel's calculation cycle!  
They cannot be multi-threaded, although xlOil can connect to more than one kernel 
simultaneously and exection in each kernel will be concurrent.

Registered kernel-based functions have addin/global scope in Excel.  Any `@xloil.func` 
declarations prior to connection will be ignored, even if `xloil` was imported. 

There is reasonable overhead in the machinery required to pass the function arguments to 
jupyter and process the result: all transport is via strings, so peformance degredation 
may be noticable for a large number of calls or for large arrays.



================================================
FILE: docs/source/xlOil_Python/ModuleReference.rst
================================================
=================================
xlOil Python Module Reference
=================================

.. contents::
    :local:

Declaring Worksheet Functions
-----------------------------

.. currentmodule:: xloil

.. autosummary::
	AllowRange
	Arg
	Array
	Cache
	CannotConvert
	CellError
	ExcelArray
	FastArray	
	SingleValue
	func
	converter
	returner
	import_functions
	register_functions
	deregister_functions
	scan_module

.. automodule:: xloil
	:members: Arg,Array,Cache,CannotConvert,CellError,ExcelArray,FastArray,SingleValue,func,converter,returner,import_functions,register_functions,deregister_functions,scan_module
	:imported-members:
	:undoc-members:

.. autodata:: AllowRange

Excel Object Model
------------------

.. currentmodule:: xloil

.. autosummary::
	workbooks
	worksheets
	app
	active_worksheet
	active_workbook
	Application
	Caller
	Range
	Workbook
	Worksheet
	ExcelWindow
	ExcelWindows
	Workbooks
	Worksheets

.. autodata:: workbooks
	
.. autodata:: worksheets
	
.. autofunction:: app

.. autofunction:: active_worksheet

.. autofunction:: active_workbook

.. autoclass:: Application
	:members: 
	:inherited-members:
	:undoc-members:
	:special-members: __enter__, __exit__

.. autoclass:: Caller
	:members: 
	:inherited-members:
	:undoc-members:

.. autoclass:: Range
	:members: 
	:inherited-members:
	:undoc-members:
	:special-members: __getitem__

.. autoclass:: Workbook
	:members: 
	:inherited-members:
	:undoc-members:
	:special-members: __getitem__

.. autoclass:: Worksheet
	:members: 
	:inherited-members:
	:undoc-members:
	:special-members: __getitem__, __setitem__

.. autoclass:: ExcelWindow
	:members: 
	:inherited-members:
	:undoc-members:

.. autoclass:: ExcelWindows
	:members: 
	:inherited-members:
	:undoc-members:

.. autoclass:: Workbooks
	:members: 
	:inherited-members:
	:undoc-members:

.. autoclass:: Worksheets
	:members: 
	:inherited-members:
	:undoc-members:

.. autoclass:: PauseExcel
	:members: 

.. automodule:: xloil
	:members: SpecialCells
	:imported-members:
	:undoc-members:


RTD Functions
-------------

.. currentmodule:: xloil

.. autosummary::
	RtdPublisher
	RtdServer
	xloil.rtd.subscribe
	xloil.rtd.RtdSimplePublisher

.. autoclass:: RtdPublisher
	:members:
	
.. autoclass:: RtdServer
	:members:

.. automodule:: xloil.rtd
	:members:


GUI Interaction
---------------

.. currentmodule:: xloil

.. autosummary::
	StatusBar
	ExcelGUI
	TaskPaneFrame
	RibbonControl
	xloil.gui.CustomTaskPane
	xloil.gui.find_task_pane
	xloil.gui.qtpy.Qt_thread
	xloil.gui.qtpy.QtThreadTaskPane
	xloil.gui.tkinter.Tk_thread
	xloil.gui.tkinter.TkThreadTaskPane
	xloil.gui.wx.wx_thread
	xloil.gui.wx.WxThreadTaskPane

.. autoclass:: StatusBar
	:members:

.. autoclass:: ExcelGUI
	:members:
.. autoclass:: TaskPaneFrame
	:members:
.. autoclass:: RibbonControl
	:members:

.. automodule:: xloil.gui
	:members: CustomTaskPane 

.. autofunction:: find_task_pane

.. automodule:: xloil.gui.qtpy
	:members: Qt_thread, QtThreadTaskPane
	:inherited-members:

.. automodule:: xloil.gui.tkinter
	:members: Tk_thread, TkThreadTaskPane	
	:inherited-members:

.. automodule:: xloil.gui.wx
	:members: wx_thread, WxThreadTaskPane	
	:inherited-members:

Events
------

.. currentmodule:: xloil.event

.. automodule:: xloil.event

.. autoclass:: Event
	:members:
	:special-members: __iadd__, __isub__

.. autofunction:: pause
.. autofunction:: allow

.. autodata:: AfterCalculate
.. autodata:: WorkbookOpen
.. autodata:: NewWorkbook
.. autodata:: SheetSelectionChange
.. autodata:: SheetBeforeDoubleClick
.. autodata:: SheetBeforeRightClick
.. autodata:: SheetActivate
.. autodata:: SheetDeactivate
.. autodata:: SheetCalculate
.. autodata:: SheetChange
.. autodata:: WorkbookAfterClose
.. autodata:: WorkbookRename
.. autodata:: WorkbookActivate
.. autodata:: WorkbookDeactivate
.. autodata:: WorkbookBeforeClose
.. autodata:: WorkbookBeforeSave
.. autodata:: WorkbookAfterSave
.. autodata:: WorkbookBeforePrint
.. autodata:: WorkbookNewSheet
.. autodata:: WorkbookAddinInstall
.. autodata:: WorkbookAddinUninstall
.. autodata:: XllAdd
.. autodata:: XllRemove
.. autodata:: ComAddinsUpdate
.. autodata:: PyBye
.. autodata:: UserException


Everything else
---------------

.. currentmodule:: xloil

.. autosummary::
	in_wizard
	get_async_loop
	get_event_loop
	from_excel_date
	date_formats
	linked_workbook
	excel_state
	check_abort
	Address
	run
	run_async
	call
	call_async
	excel_callback
	cache
	Addin
	source_addin
	xloil_addins
	core_addin
	xloil._core._AddinsDict
	xloil._core._DateFormatList
	xloil._core._LogWriter
	xloil.logging.log
	xloil.debug.use_debugger

.. autoclass:: ObjectCache
	:members: 

.. autodata:: cache
	:annotation: = ObjectCache
	:no-value:

.. automodule:: xloil
	:members: in_wizard,get_async_loop,get_event_loop,from_excel_date,linked_workbook,source_addin,excel_state,run,run_async,call,call_async,excel_callback,source_addin,xloil_addins,core_addin,check_abort
	:imported-members:
	:undoc-members:

.. autoclass:: Address
	:members:

.. autodata:: date_formats
	:annotation: = _DateFormatList
	:no-value:

.. autoclass:: ExcelState
	:members: 
	:inherited-members:
	:undoc-members:

.. autoclass:: Addin
	:members:

.. autodata:: xloil_addins
	:annotation: = _AddinsDict
	:no-value:

.. automodule:: xloil._core
	:members: _AddinsDict, _DateFormatList, _LogWriter

.. automodule:: xloil.logging
	:members: 

.. automodule:: xloil.debug
	:members:



External libraries
------------------

.. currentmodule:: xloil

.. autosummary::
	insert_cell_image
	xloil.pandas.PDFrame
	xloil.pillow.ReturnImage
	xloil.matplotlib.ReturnFigure

.. autofunction:: insert_cell_image

.. automodule:: xloil.pandas
	:members: PDFrame
.. automodule:: xloil.pillow
	:members: ReturnImage
.. automodule:: xloil.matplotlib
	:members: ReturnFigure



================================================
FILE: docs/source/xlOil_Python/Rtd.rst
================================================
======================
xlOil Python Async/Rtd
======================

Introduction
------------

RTD (real time data) functions are able to return values independently of Excel's calculation
cycle. The classic example of this is a stock ticker with live prices.  It is easy to create
an RTD function in *xlOil_Python* -- the following gives a ticking clock:

::

    import xloil, datetime, asyncio

    @xloil.func
    async def pyClock():
        while True:
            yield datetime.datetime.now()
            await asyncio.sleep(2)
            

Note that calculation must be on automatic mode or you will not see the updates. 
Whatever parameter is passed to `sleep` the clock will not tick faster than 2 seconds - this due 
to the `RTD throttle interval <https://docs.microsoft.com/en-us/previous-versions/office/developer/office-xp/aa140060(v=office.10)>`_
Which can bed changed via `xlo.app().RTD.ThrottleInterval = <milliseconds>`, however 
reducing it below the default of 2000 may impair performance.  The change is global and
persists when Excel is restarted, so give some consideration to altering the value.

Any `async def` function is handled in xlOil as using RTD by default.  It is possible to 
use Excel's native async support, but this has some drawbacks, discussed in :any:`concepts-rtd-async`

There is another advantage of RTD: RTD functions can be 'local', i.e. called through a 
VBA stub associated with the workbook, which avoids cluttering the global function namespace.

Improving RTD performance (specifying topics)
---------------------------------------------

Registering an `async def` function as described above has a certain overhead: excel will 
call the function multiple times to fetch the result, so xlOil must store and compare all 
the function arguments to figure out if Excel wants the result of a previous calculation 
or to starta new calculation with new arguments.

If an RTD `topic`, i.e. a unique string identifier, is easy to determine we can take over
responsibility for generating it manually.

::

    # First create a new RTD COM server so the `topic` strings don't collide
    _rtdServer = xlo.RtdServer()
    
    @xloil.func
    def pyClock2(secs):

        async def fetch() -> dt.datetime:
            while True:
                await asyncio.sleep(secs)
                yield dt.datetime.now()
            
        return xloil.rtd.subscribe(_rtdServer, "Time:" + str(secs), fetch)

The `subscribe` call will look for an existing publisher, i.e. a clock with `secs` interval,
and return the value if one is found.  Otherwise it will run the coroutine and publish
the value.  Note the coroute specifies a return type: this is handled with a return converter
just like functions decorated with :any:`xloil.func`.

The instance of the :obj:`xloil.RtdServer` object creates and registers a COM class. When xlOil is
unloaded, the server will be unregistered and destroyed.  Since we created our own server the 
server, we can choose the convention for these topic strings (i.e. the unique publisher ID).

Note that we do not need to declare the outer function async, the `subscribe()` call notifies 
Excel that this function should be treated as RTD.

xlOil's RTD Interface
---------------------

If even finer-grained control of the RTD mechanism is required (such as in the `xloil_jupyter`
module, :doc:`Jupyter`), we can specify the publisher as described below.

We will follow the *UrlGetter* example in :doc:`ExampleRTD`.  In this case we make the topics URLs. 
The RTD workflow is to first check if a given topic has a publisher using `peek()`. If not, 
we spin one up with :any:`xloil.RtdServer.start`. Then we :any:`xloil.RtdServer.subscribe` to 
the topic which tells xlOil to call Excel's RTD function.

:: 

    _rtdServer = xlo.RtdServer()

    @xlo.func
    def pyGetUrlLive(url):
        if _rtdServer.peek(url) is None:
            publisher = UrlGetter(url)
            _rtdServer.start(publisher)
        return _rtdServer.subscribe(url)


The publisher is the class which does the work. Its `connect()` method is called when a 
worksheet function calls `subscribe()` for its topic.  The publisher should then start
an async task to publish values.

If the worksheet function is subsequently changed or deleted, then `disconnect()` is called. 
When a publisher has no subscribers it should save CPU cycles by stopping its task.  A 
publisher should also stop when requested by the `stop()` method.

Apart from `connect()` the remaining methods are boilerplate at least for a simple publisher.
The boilerplate can be avoided by use of the `RtdSimplePublisher` class, then only the
`run()` method in the below requires definition. 

::

    class UrlGetter(xlo.RtdPublisher):

        def __init__(self, url):
            # You *must* call this ctor explicitly or the python binding library will crash
            super().__init__()  
            self._url = url
            self._task = None
           
        def connect(self, num_subscribers):
            if self.done():
                async def run():
                    try:
                        while True:
                            data = await getUrlAsync(self._url);
                            _rtdServer.publish(self._url, data)
                            await asyncio.sleep(4)                     
                    except Exception as e:
                        _rtdServer.publish(self._url, e)
                        
                self._task = xlo.get_event_loop().create_task(run())
                
        def disconnect(self, num_subscribers):
            if num_subscribers == 0:
                self.stop()
                # Returning True schedules the publisher for destruction
                return True 
                
        def stop(self):
            if self._task is not None: 
                self._task.cancel()
        
        def done(self):
            return self._task is None or self._task.done()
            
        def topic(self):
            return self._url

The final task, left as an exercise, is to write `getUrlAsync()`: an async function which 
fetches a URL.  It is straightforward with the `aiohttp` library.


================================================
FILE: docs/source/xlOil_Python/TypeConversion.rst
================================================
============================
xlOil Python Type Conversion
============================

.. contents::
    :local:


Argument Types
--------------

xlOil function declarations in python look like:

::

    @xlo.func
    def DoSomething(x, y:float):
      return x

If no type is specified for an argument, xlOil will dynamically choose a type based
on the argument provied by Excel, this can be one of:

    * *bool*
    * *int*
    * *str*
    * *float*
    * *numpy.ndarray* (if an array or range is passed)
    * :py:class:`xloil.CellError`

Using ``typing`` annotations improves performance at the expense of static
typing.  Annonations also allow for user-defined conversion to any python type. 
xlOil has built-in support for the following annotations:

.. list-table:: Supported argument annotations
    :widths: 20 50
    :header-rows: 1

    * - Type
      - Comment
    * - *bool*
      - 
    * - *int*
      -
    * - *str*
      -
    * - *float*
      -
    * - *numpy.ndarray*
      - Use the :py:class:`xloil.Array` annotation rather than ndarray directly
    * - *dict*
      - Requires a 2-column input array. The first column is interpreted as keys
    * - *tuple*
      - Gives a tuple of tuple-of-tuples depending on number of input dimensions
    * - *datetime.date*
      - See :ref:`xlOil_Python/TypeConversion:Dates`
    * - *datetime.datetime*
      - See :ref:`xlOil_Python/TypeConversion:Dates`
    * - *pandas.DataFrame*
      - Can use the :py:class:`xloil.pandas.PDFrame` annotation for more conversion options. 
        Need to `import xloil.pandas` before use.
    * - *pandas.Timestamp*
      - Need to `import xloil.pandas` before use.
    * - :py:class:`xloil.Range`
      - See :ref:`xlOil_Python/TypeConversion:Range Arguments`
    * - :py:class:`xloil.AllowRange`
      - See :ref:`xlOil_Python/TypeConversion:Range Arguments` 
    * - <AnyType>
      - See :ref:`xlOil_Python/TypeConversion:Custom Type Conversion`

Annotations which xlOil does not understand are ignored.

Example:

::

    @xlo.func
    def pySumNums(x: float, y: float, a: int = 2, b: int = 3) -> float:
        return x * a + y * b


Return Types
------------

Like argument types, xlOil can read return type annotations. If no annotation
is specified xlOil tries the following conversions:
   
   * *None*
   * *int*
   * *float*
   * *numpy.ndarray*
   * *datetime*
   * :py:class:`xloil.CellError`
   * *str*
   * Registered custom return converters, see :ref:`xlOil_Python/TypeConversion:Custom Return Conversion`
   * iterable

If none of these succeeds, the object is placed in the cache, see :ref:`xlOil_Python/TypeConversion:Cached Objects`

.. list-table:: Supported return type annotations
    :widths: 20 50
    :header-rows: 1

    * - Type
      - Comment
    * - *bool*
      - 
    * - *int*
      -
    * - *str*
      -
    * - *float*
      -
    * - *numpy.ndarray*
      - Use the :py:class:`xloil.Array` annotation rather than ndarray directly
    * - *dict*
      - Outputs a 2-column array of key, value pairs
    * - *tuple*
      - A tuple of tuple-of-tuples produces a 1 or 2 dim array
    * - *datetime.date*
      - See :ref:`xlOil_Python/TypeConversion:Dates`
    * - *datetime.datetime*
      - See :ref:`xlOil_Python/TypeConversion:Dates`
    * - *pandas.DataFrame*
      - Can use the :py:class:`xloil.pandas.PDFrame` annotation for more conversion options. 
        Need to `import xloil.pandas` before use.
    * - *pandas.Timestamp*
      - Need to `import xloil.pandas` before use.
    * - *PIL.Image*
      - See :ref:`xlOil_Python/TypeConversion:Returning Images and Plots`
    * - *matplotlib.pyplot.Figure*
      - See :ref:`xlOil_Python/TypeConversion:Returning Images and Plots`
    * - :py:class:`xloil.Cache`
      - Placed the return value in the python object cache, see :ref:`xlOil_Python/TypeConversion:Cached Objects`.
    * - :py:class:`xloil.SingleValue`
      - Ensures the output will be a single cell value, not an array.
    * - <AnyType>
      - See :ref:`xlOil_Python/TypeConversion:Custom Return Conversion`

Cached Objects
--------------

If xlOil cannot convert a returned python object to Excel, it will place it in 
an object dictionary and return a reference string of the form

``<UniqueChar>[SheetID]!CellNumber,#``

xlOil automatically resolves cache string passed function arguments to their
objects.  With this mechanism you can pass python objects opaquely between 
functions.  You should not attempt to construct a cache string directly.

For example:

::

    @xlo.func
    def make_lambda(pow):
        return lambda x: x ** pow

    @xlo.func
    def apply_lambda(f, x):
        return f(x)

Since xlOil cannot convert a lambda function to an Excel object, it outputs a 
cache reference string.  That string is automatically turned back into a lambda 
if passed as an argument to the second function.

The python cache is separate to the Core object cache accessed using `xloRef`
and `xloVal`.  The Core cache stores native Excel objects such as arrays.
When reading functions arguments xlOil tries to lookup strings in both of these
caches. 

The leading *<UniqueChar>* means xlOil can very quickly determine that a string
isn't a cache reference, so the overhead of checking if every string argument
is a cache object is very low in practice. 

Using :any:`xloil.cache` it is possible to place objects into the cache. This 
can be used an alternative to the :py:class:`xloil.Cache` decorator to allow
the function to choose whether or not to return a cache object.  It could 
also be used to return cached objects from commands or subroutines, but 
understand the object lifecycle before doing this

Cache Object Lifecycle
~~~~~~~~~~~~~~~~~~~~~~

xlOil uses the caller infomation provided by Excel to construct the cache 
string. When invoked from a worksheet function, the caller info contains 
the sheet and cell reference and so on each calculation cycle the same
cache reference appears and the new cache object automatically overwrites 
the previous one.

When invoked from a source other than a worksheet function (there are several
possibilies for this, see the help for `xlfCaller`), xlOil again generates a 
reference string based on the caller info. However, this may not be unique. 
In addition, objects with the same caller info will replace those created 
during a previous calculation cycle. For example, creating cache objects 
from a button clicked repeatedly will behave differently if Excel recalculates 
in between the clicks. To override this behaviour, the exact cache `key` can 
be specified.  For example, use Python's `id` function or the cell address 
being written to.  When `key` is specified the user is responsible for managing
the lifecycle of their cache objects using `remove` in :any:`xloil.cache`.


Dates
-----

Applying the argument annotation ``datetime.datetime`` requests a date conversion. Returning 
a ``datetime`` is allowed without a return annotation: the datetime will be converted to
an Excel date number:

::

    from datetime import datetime, timedelta
    @func
    def AddDay(date: datetime):
        return date + timedelta(days = 1)


xlOil can interpret strings as dates. In the settings file, the key ``DateFormats`` 
specifies an array of date formats to try when parsing strings. Naturally, adding more 
formats decreases performance. The formats use the C++ ``std::get_time`` syntax,
see https://en.cppreference.com/w/cpp/io/manip/get_time.

Since ``std::get_time`` is **case-sensitive** on Windows, so is xlOil's date parsing
(this may be fixed in a future release as it is quite annoying for month names).

Excel has limited internal support for dates. There is no primitive date object 
but cells containing numbers can be formatted as dates. This means that worksheet 
functions cannot tell whether numerical values are intended as dates - this applies
to Excel built-in date functions as well. (It is possible to check for date formatting
via the COM interface but this would give behaviour inconsistent with the built-ins)

Excel does not understand timezones and neither does ``std::get_time``, so these
are currently unsupported.


Dicts
-----

When the ``dict`` *argument type* annotation is specified, xlOil expects a two-column 
array of(*string*, *value*) to be passed.

Using a ``dict`` *return type* annotation allows a ``dict`` to be returned as as a 
two column array. Without the annotation, the default iterable converter would be invoked, 
resulting in only the keys being output.

Variable and Keyword Arguments
-------------------------------

If keyword args (`**kwargs`) are specified, xlOil expects a two-column array of 
(*string*, *value*) to be passed, the same as using a ``dict`` annotation. For variable
args (`*args`) xlOil adds a large number of trailing optional arguments. The variable
argument list is ended by the first missing argument.  If both *kwargs* and *args* are 
specified, their order is reversed in the Excel function declaration.

The following example shows dictionary and keyword aruments:

::

  @xlo.func
  def pyTestKwargs(lookup: dict, **kwargs) -> dict:
      lookup.update(kwargs)
      return lookup

The number of trailing optional arguments is limited by the maxiumum number of arguments 
allowed by Excel, which is 255 for a worksheet function and 60 for a local function.

Range Arguments
---------------

Range arguments allow a function to directly access a part of the worksheet. This 
allows macro functions to write to the worksheet or it can be used for optimisation
if a function only requires a few values from a large input range.

A function can only receive range arguments if it is declared as *macro-type*. In 
addition, attempting to write to a Range during Excel's calculation cycle will fail.

Annotating an argument with :py:class:`xlo.Range` will tell xlOil to pass the function an
:py:class:`Range` object, or fail if this is not possible.  An :py:class:`Range` 
can only be created when the input argument explicitly points to a part of the worksheet, not 
an array output from another function.

Annotating an argument with :py:class:`xlo.AllowRange` will tell xlOil to pass an 
:py:class:`Range` object if possible, otherwise one of the other basic data types
(int, str, array, etc.).


Custom Type Conversion
----------------------

A custom type converter is a function or a class which serialises between a set 
of simple types understood by Excel and general python types.

A type converter class is expected to implement at least one of ``read(self, val)`` 
and ``write(self, val)`` and be decorated with :py:func:`xloil.converter`.
It may take parameters in its constructor and hold state. 

A function can be interpreted as a type reader or writer depending on the parameters
passed to the :py:func:`xloil.converter` decorator.

The ``read(self, val)`` method or a function decorated as a reader or argument converter 
should be able to accept a value of: 

    *int*, *bool*, *float*, *str*, :py:class:`xloil.ExcelArray`, :py:class:`CellError`, 
    :py:class:`xloil.Range` (optional) 

and return a python object or raise an exception (ideally :py:class:`xloil.CannotConvert`).

An :py:class:`xloil.ExcelArray` represents an un-processed array argument, a
handle to the raw Excel object not yet converted to a *numpy* array.  The converter
may opt to process only a part of this array for efficiency. 

A converter may be used by name in *typing* annotations for :py:func:`xloil.func` 
functions.  In addition, the converter can register as the handler for a specific type 
which enables that type to be used in annotations.  For registration, the converter must
be default-constructible (or be a function).

By decorating with ``@xloil.converter(range=True)``, the type converter can opt to
receive :py:class:`Range` arguments in addition to the other types.


::

    @xlo.converter()
    def arg_doubler(x):
      if isinstance(x, xlo.ExcelArray):
        x = x.to_numpy()
      return 2 * x

    @xlo.func
    def pyTestCustomConv(x: arg_doubler):
      return x

    @xlo.converter(typeof=bytes, register=True)
    class StrToBytes:
      def __init__(self, encoding='utf-8'):
        self._encoding = encoding
      def read(self, val):
        return val.encode(self._encoding)
      def write(self, val):
        return val.decode(self._encoding)
      
    @xlo.func
    def Pad(text: bytes, size: int) -> StrToBytes('utf-8'):
      return text.center(size) 

Custom Return Conversion
------------------------

A return type converter should take a python object and return a simple type
which xlOil knows how to return to Excel. It should raise :py:class:`xloil.CannotConvert` 
if it cannot handle the given object.

It can be a class implementing ``write(self, val)`` and decorated with 
:py:class:`xloil.converter` or a function decorated with :py:class:`xloil.returner`
or :py:class:`xloil.converter`.

A return converter can register as the handler for a specific type which enables that 
type to be used in return annotations *and* allows xlOil to try to call 
the converter for Excel functions with no return annotation, see :ref:`xlOil_Python/TypeConversion:Return Types`.
        

::

    @xlo.returner(typeof=MyType, register=True)
    def mytypename(val):
      return val.__name__
    
    @xlo.func
    def MakeMyType():
      return MyType()
  

Returning Images and Plots
--------------------------

By using custom return converters you can return `PIL` or `pillow` image 
objects from worksheet functions. The returned image can be automatically 
sized to the calling range, or any offset from it, but it floats like a 
normal picture in Excel.  Calling the worksheet function again removes
the previous image and replaces it with a new one.

::

    import xloil.pillow
    from PIL import Image
    
    @xlo.func(macro=True) # macro permissions required
    def ShowPic(filename):
        return Image.open(filename)


Importing ``xloil.pillow`` registers a custom return converter for ``PIL.Image``.
To gain control over the image size and position, use the :py:class:`xloil.pillow.ReturnImage`
return annotation.

Similarly a matplotlib figure can be returned directly

::

    import xloil.matplotlib

    @func(macro=True)
    def Plot(x, y):
        fig = pyplot.figure(figsize=(5,5))
        fig.add_subplot(111).plot(x, y)
        return fig

Importing ``xloil.matplotlib`` registers a custom return converter for 
``matplotlib.pyplot.Figure``. To gain control over the plot size and position, 
use the :py:class:`xloil.matplotlib.ReturnFigure` return annotation.

Both of these converters use :py:class:`xloil.insert_cell_image`.


================================================
FILE: docs/source/xlOil_Python/index.rst
================================================
============
xlOil Python
============

.. toctree::
    :maxdepth: 4
    :caption: Contents

    GettingStarted
    Concepts
    Functions
    TypeConversion
    ExcelApplication
    CustomGUI
    Dynamic
    ExternalPackages
    BuiltInUDFs
    Jupyter
    Rtd
    Debugging
    DistributingAddins
    Example
    ExampleGUI
    ExampleRTD
    FAQ
    ModuleReference


================================================
FILE: docs/source/xlOil_SQL/index.rst
================================================
=========
xlOil SQL
=========

The SQL plugin uses sqlite3 to provide functions which query Excel arrays (or
ranges) as if they were tables in a database. Multiple tables can be queried 
and joined.

.. contents::
    :local:

.. _sql-getting-started:

SQL Getting Started
-------------------

xlOil_SQL does not require any settings and is automatically loaded in a default 
xlOil installation.  It should appear in the plugin list in
`%APPDATA%/xlOil/xlOil.ini`:

::

    Plugins=["xlOil_SQL.dll"]

You can open the example spreadsheet at :ref:`core-example-sheets` to see it in action.

For a quick demo, create a 3 column table of data in an new Excel workbook. 
Make the headings 'Foo', 'Bar' and 'Baz'.  The contents of the data can be 
anything you like.

Suppose the table is in cells A1:C5, then in another cell type 

::

    =xloSql("SELECT Bar, Baz FROM Table1", A1:C5)

Make the output an array formula with Ctrl-Shift-Enter and size it 
appropriately.

.. _xloSql:

xloSql
------

Executes a query on multiples data arrays

.. function:: xloSql(Query, [Meta], [Table1], [Table2], [Table3], ...)

    Excecutes the SQL query on the provided tables, returning the 
    result in an array. The tables will be named Table1, Table2, etc in the 
    query but this can overrided by the `meta` parameter

        Query:
            a string or array of string (which will be concatenated) 
            describing a query in SQL (sqlite3). 

        Meta: 
            optional array of string. The first column contains the 
            names of the tables. Subsequent columns are interpreted
            as column headings for the table. Providing a blank table
            name or few names than tables results in the un-named
            tables retaining their default name of tableN
        
        TableN:
            each table argument should point to an array of data with
            columns as fields and records as rows. Unless column
            names are specified in the meta, the first row is interpreted as column names


    **Examples**
    
    (Arguments pointing to array data are surrouned by `{}`)

    ::

        =xloSql("SELECT table1.A, B, C FROM table1 ",  { A    B  } , { A     C } )
                "INNER JOIN table2                 "   { Foo  1  }   { Bar   2 } )
                "ON table1.A == table2.A           "   { Baz  7  }   { Foo   3 } )

        --> Foo 1 3

Stateful Database Functions
---------------------------

This family of functions can be used to build up and repeatedly query an 
in-memory database for cases where building the database on the fly using 
:ref:`xlOil_SQL/index:xloSql` is not performant.

xloSqlDB
~~~~~~~~

.. function:: xloSqlDB()

    Returns a reference to a new database object. The functions :ref:`xlOil_SQL/index:xloSqlDB`, :ref:`xlOil_SQL/index:xloSqlTable`
    and :ref:`xlOil_SQL/index:xloSqlQuery` can be used to build up an in-memory database for the cases where
    building these objects on the fly using :ref:`xlOil_SQL/index:xloSql` is not performant.

xloSqlTable
~~~~~~~~~~~

.. function:: xloSqlTable(Database, Data, Name, [Headings], [Query])

    Creates a table in a database created with :ref:`xlOil_SQL/index:xloSqlDB`.  The function returns a reference 
    to the database: it is recommended to chain xloSqlTable calls to force execution order
    in Excel. This ensures tables are added to the database before any queries are run

        Database:
            a reference to a database created with `xloSqlDB`. 

        Data: 
            an array of data with columns as fields and records as rows. Unless column
            headings are specified, the first row is interpreted as column names

        Name:
            The name of the table in the database. This must be unique.
        
        Headings:
            optional column headings for the data. If these are specified, data is read
            from the first input row
        
        Query:
            An optional query to process the data as it is copied into the database.
            If ommitted, "SELECT * FROM name" is used.

xloSqlQuery
~~~~~~~~~~~
.. function:: xloSqlQuery(Database, Query)

        Database:
            A reference to a database originally created with :ref:`xlOil_SQL/index:xloSqlDB` but which has
            passed through calls to :ref:`xlOil_SQL/index:xloSqlTable`.

        Query:
            A SQL query to execute. Tables referenced in the query must have been added 
            to the database by :ref:`xlOil_SQL/index:xloSqlTable` before this function is called.


   **Examples**

    ::

        .              A                               B       C       D   
        1 =xloSqlDB()                                  MyTab   Foo     Bar
        2                                                      7       2
        3 =xloSqlTable(A1, C1:D4, B1)                          4       1
        4                                                      8       4
        5
        6 =xloSqlQuery(A3, "SELECT Bar FROM MyTab")

        Cell A6 will contain the array [2, 1, 4]

xloSqlTables
~~~~~~~~~~~~

.. function:: xloSqlTables(Database)

    Returns an array of all table names in the database


================================================
FILE: docs/source/xlOil_Utils.rst
================================================
===========
xlOil Utils
===========

The Utils plugin contains general purpose tools to manipulate data,
particularly arrays.

.. contents:: Contents
	:local:
    
xloBlock: creates an array from blocks
----------------------------------------

.. function:: xloBlock(layout, arg1, arg2, arg3,...)

    Creates a block matrix given a layout specification.

    Layout has the form `1, 2, 3; 4, 5, 6` where numbers refer to
    argument numbers provided (note indexing is 1-based). Commas
    divide argument numbers, semi-colons indicate a new row. xlOil 
    expands the blocks row by row.

    Omiting the argument number, i.e. two consecutive commas gives an
    auto-sized padded space. You can only have one per row.

    Whitespace is ignored in the layout specification.

    Arguments may be an array or a single value, which is interpreted as
    a 1x1 array.

    Any holes in the result are filled with #N/A - this is preferrable 
    over Excel's 'empty' value which is transformed to a zero when 
    written to the sheet.

    **Examples**

    ::

        =xloBlock("1, 2; 3, 4", A A, B B, C C, D D)
                                A A  B B

        --> A A B B
            A A B B
            C C D D


        =xloBlock("1, 2; 3,, 4", A A, B B, C, D)
                                 A A  B B

        --> A A B B
            A A B B
            C - - D

xloFill: gives an array filled with a single value
--------------------------------------------------

.. function:: xloFill(value, numRows, numColumns)

    Creates an array of size numRows by numColumns filled with value.

    Throws if value is not a single value.

xloFillNA: replaces Empy or #N/A with a specified value
----------------------------------------------------------

.. function:: xloFillNA(value, array, [trim])

    Replaces any #N/A or Empty with a specified value. #N/As in Excel 
    result from holes, e.g. from xloBlock or array which does not fill
    the space allocated in an array formula.  Empty values are particularly
    problematic: they correpond to Excel reading an empty cell in an array
    but are transformed to a zero when written to the sheet.

    Throws if value is not a single value.

    The optional trim parameter can be used to disable xlOil's default
    array-trimming behaviour of resizing to the last non-empty, non-NA 
    row and column.


xloSort: sorts an array by multiple columns
----------------------------------------------------------

.. function:: xloSort(Array, Order, [colOrHeading1], [colOrHeading2], ...)

    Sorts data by one or more column keys. The function behaves similarly
    to Excel's sort command, but works as a sheet function.

    The `Order` parameter should be a string with a descriptor character
    for each column to used as a sort key.  The character described how 
    the column data will be compared. Allowed characters and their meaning 
    are:

        *a*: ascending

        *A*: ascending case-sensitive,

        *d*: descending

        *D*: descending case-sensitive

        *whitespace*: ignored

    Each subsequent argument should be the (1-based) number of a column
    or string.  If any strings are specified, the first row of `Array`
    is interpreted as column headers and the strings are matched against
    these headers.

    The order of the column specifiers indicates the prescendence in the
    sort order.

    xloSort works in-place for speed but uses Excel's variant types. This 
    means it will not be 

    **Examples**

    ::

        =xloSort( { Baz    4 } , "a d", 2, 1)
                  { Bar    4 }              
                  { Boz    2 }             

        -> 2    Boz
           4    Baz
           4    Bar    



xloPad: pads an array to have at least two rols and columns
-----------------------------------------------------------

.. function:: xloPad(array)

    xloPad works around the Excel 'feature' that duplicates arrays
    with only one row or column when they are used in an array formula with 
    a larger target size.  This can be frustrating for display of variable 
    sized array results.  xloPad simply ensures the array has at least two
    rows and columsn, adding #N/A where required to fill the space.


xloConcat: concatenates strings
--------------------------------

.. function:: xloConcat([separator], valOrArray1, valOrArray2, ...)

    Concatenates strings or other values with an optional separator.
    Concatenation is in argument order. The separator may be blank or any
    value which can be converted to a string.  Non string arguments are 
    converted to string before concatenation.  Arrays are concatenated
    along rows using the sparator if specified.


xloSplit: splits strings at a separator
---------------------------------------

.. function:: xloSplit(stringOrArray, separators, [consecutiveAsOne])

    Splits a string at one or more separator characters, returning an array.
    A separators can only be a single character, but multiple separators
    can be specified. If `consecutiveAsOne` is omitted or TRUE, consecutive
    separators are treated as one, otherwise they generate empty cells.

    If a array of strings is passed, splitting will occur on each array
    element and the array orientation wil be preserved. The array must be 
    1-dimensional

    Any non string values are ignored - no coercision is performed.

    The `separators` input can be a string containing any number of characters;
    each will be treated as a distinct separator - multi-character separators
    are not supported.

    **Examples**

    ::

        =xloSplit("Foo:Bar,,Baz", ":,")

        -> Foo      Bar     Baz


xloIndex: gets values or sub-arrays for arrays and ranges
---------------------------------------------------------

.. function:: xloIndex(ArrayOrRef, [FromRow], [FromCol], [ToRow], [ToCol])

    Extends the Excel INDEX function to support xloRefs and sub-arrays. With
    the first three arguments, `xloIndex` behaves like INDEX but can be passed
    an xloRef. This is an efficient way to fetch data from xloRef objects as it 
    avoids copying the entire object to Excel.

    If *ToRow* and *ToCol* are provided they specify the right-hand end (not 
    inclusive) of a sub-array from (*FromRow*, *FromCol*) to (*ToRow*, *ToCol*).

    **The row and column indices are 1-based**.  If any of the indices is zero or 
    negative it is interpreted as an offset from the number of rows or columns 
    in the parent array.

    **Examples**

    ::

        =xloIndex(A1:D5,1,3) -> returns C1
        =xloIndex(A1:D5,-1,-1) -> returns D5
        =xloIndex(A1:D5,1,3,3,4) -> returns C1:D3
        =xloIndex(A1:D5,-2,-2,0,0) -> returns C4:D5


================================================
FILE: docs/source/xloil.doxyfile
================================================
# Doxyfile 1.8.18

# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").

#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------

# This tag specifies the encoding used for all characters in the configuration
# file that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.

DOXYFILE_ENCODING      = UTF-8

# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.

PROJECT_NAME           = xlOil

# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER         = 1

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.

PROJECT_BRIEF          =

# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.

PROJECT_LOGO           =

# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.

OUTPUT_DIRECTORY       = $(XLO_SOLN_DIR)/build/docs/doxygen

# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# The default value is: NO.

CREATE_SUBDIRS         = NO

# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.

ALLOW_UNICODE_NAMES    = NO

# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# The default value is: English.

OUTPUT_LANGUAGE        = English

# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all generated output in the proper direction.
# Possible values are: None, LTR, RTL and Context.
# The default value is: None.

OUTPUT_TEXT_DIRECTION  = None

# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.

BRIEF_MEMBER_DESC      = YES

# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.

REPEAT_BRIEF           = YES

# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.

ABBREVIATE_BRIEF       = "The $name class" \
                         "The $name widget" \
                         "The $name file" \
                         is \
                         provides \
                         specifies \
                         contains \
                         represents \
                         a \
                         an \
                         the

# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.

ALWAYS_DETAILED_SEC    = NO

# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Construct
Download .txt
gitextract__p1idbhy/

├── .gitattributes
├── .gitignore
├── .readthedocs.yml
├── .runsettings
├── FUNDING.yml
├── LICENSE
├── README.md
├── Version.txt
├── config/
│   ├── xloil.ini
│   ├── xloil_local.ini
│   └── xloil_local_32.ini
├── docs/
│   ├── Excel Function Numbers.xlsx
│   ├── make.cmd
│   ├── requirements.txt
│   ├── source/
│   │   ├── Concepts.rst
│   │   ├── Core.rst
│   │   ├── Developer.rst
│   │   ├── Events.rst
│   │   ├── Introduction.rst
│   │   ├── conf.py
│   │   ├── index.rst
│   │   ├── xlOil_Core_Functions.rst
│   │   ├── xlOil_Cpp/
│   │   │   ├── COM.rst
│   │   │   ├── CppRtd.rst
│   │   │   ├── CustomGUI.rst
│   │   │   ├── DynamicRegistration.rst
│   │   │   ├── Events.rst
│   │   │   ├── GettingStarted.rst
│   │   │   ├── ObjectHandles.rst
│   │   │   ├── SpecialArgs.rst
│   │   │   ├── StaticXLLs.rst
│   │   │   └── index.rst
│   │   ├── xlOil_Python/
│   │   │   ├── BuiltInUDFs.rst
│   │   │   ├── Concepts.rst
│   │   │   ├── CustomGUI.rst
│   │   │   ├── Debugging.rst
│   │   │   ├── DistributingAddins.rst
│   │   │   ├── Dynamic.rst
│   │   │   ├── Example.rst
│   │   │   ├── ExampleGUI.rst
│   │   │   ├── ExampleRTD.rst
│   │   │   ├── ExcelApplication.rst
│   │   │   ├── ExternalPackages.rst
│   │   │   ├── FAQ.rst
│   │   │   ├── Functions.rst
│   │   │   ├── GettingStarted.rst
│   │   │   ├── Jupyter.rst
│   │   │   ├── ModuleReference.rst
│   │   │   ├── Rtd.rst
│   │   │   ├── TypeConversion.rst
│   │   │   └── index.rst
│   │   ├── xlOil_SQL/
│   │   │   └── index.rst
│   │   ├── xlOil_Utils.rst
│   │   └── xloil.doxyfile
│   └── xlOil-Sphinx.code-workspace
├── external/
│   ├── Excel2013SDK/
│   │   ├── INCLUDE/
│   │   │   └── XLCALL.H
│   │   ├── LIB/
│   │   │   ├── WIn32/
│   │   │   │   └── XLCALL32.LIB
│   │   │   └── x64/
│   │   │       └── XLCALL32.LIB
│   │   └── SRC/
│   │       ├── ReadMe.txt
│   │       └── XLCALL.CPP
│   ├── Sources.txt
│   └── boost-1.67/
│       └── boost/
│           └── preprocessor/
│               ├── arithmetic/
│               │   ├── add.hpp
│               │   ├── dec.hpp
│               │   ├── detail/
│               │   │   └── div_base.hpp
│               │   ├── div.hpp
│               │   ├── inc.hpp
│               │   ├── mod.hpp
│               │   ├── mul.hpp
│               │   └── sub.hpp
│               ├── arithmetic.hpp
│               ├── array/
│               │   ├── data.hpp
│               │   ├── detail/
│               │   │   └── get_data.hpp
│               │   ├── elem.hpp
│               │   ├── enum.hpp
│               │   ├── insert.hpp
│               │   ├── pop_back.hpp
│               │   ├── pop_front.hpp
│               │   ├── push_back.hpp
│               │   ├── push_front.hpp
│               │   ├── remove.hpp
│               │   ├── replace.hpp
│               │   ├── reverse.hpp
│               │   ├── size.hpp
│               │   ├── to_list.hpp
│               │   ├── to_seq.hpp
│               │   └── to_tuple.hpp
│               ├── array.hpp
│               ├── assert_msg.hpp
│               ├── cat.hpp
│               ├── comma.hpp
│               ├── comma_if.hpp
│               ├── comparison/
│               │   ├── equal.hpp
│               │   ├── greater.hpp
│               │   ├── greater_equal.hpp
│               │   ├── less.hpp
│               │   ├── less_equal.hpp
│               │   └── not_equal.hpp
│               ├── comparison.hpp
│               ├── config/
│               │   ├── config.hpp
│               │   └── limits.hpp
│               ├── control/
│               │   ├── deduce_d.hpp
│               │   ├── detail/
│               │   │   ├── dmc/
│               │   │   │   └── while.hpp
│               │   │   ├── edg/
│               │   │   │   └── while.hpp
│               │   │   ├── msvc/
│               │   │   │   └── while.hpp
│               │   │   └── while.hpp
│               │   ├── expr_if.hpp
│               │   ├── expr_iif.hpp
│               │   ├── if.hpp
│               │   ├── iif.hpp
│               │   └── while.hpp
│               ├── control.hpp
│               ├── debug/
│               │   ├── assert.hpp
│               │   ├── error.hpp
│               │   └── line.hpp
│               ├── debug.hpp
│               ├── dec.hpp
│               ├── detail/
│               │   ├── auto_rec.hpp
│               │   ├── check.hpp
│               │   ├── dmc/
│               │   │   └── auto_rec.hpp
│               │   ├── is_binary.hpp
│               │   ├── is_nullary.hpp
│               │   ├── is_unary.hpp
│               │   ├── null.hpp
│               │   └── split.hpp
│               ├── empty.hpp
│               ├── enum.hpp
│               ├── enum_params.hpp
│               ├── enum_params_with_a_default.hpp
│               ├── enum_params_with_defaults.hpp
│               ├── enum_shifted.hpp
│               ├── enum_shifted_params.hpp
│               ├── expand.hpp
│               ├── expr_if.hpp
│               ├── facilities/
│               │   ├── apply.hpp
│               │   ├── detail/
│               │   │   └── is_empty.hpp
│               │   ├── empty.hpp
│               │   ├── expand.hpp
│               │   ├── identity.hpp
│               │   ├── intercept.hpp
│               │   ├── is_1.hpp
│               │   ├── is_empty.hpp
│               │   ├── is_empty_or_1.hpp
│               │   ├── is_empty_variadic.hpp
│               │   └── overload.hpp
│               ├── facilities.hpp
│               ├── for.hpp
│               ├── identity.hpp
│               ├── if.hpp
│               ├── inc.hpp
│               ├── iterate.hpp
│               ├── iteration/
│               │   ├── detail/
│               │   │   ├── bounds/
│               │   │   │   ├── lower1.hpp
│               │   │   │   ├── lower2.hpp
│               │   │   │   ├── lower3.hpp
│               │   │   │   ├── lower4.hpp
│               │   │   │   ├── lower5.hpp
│               │   │   │   ├── upper1.hpp
│               │   │   │   ├── upper2.hpp
│               │   │   │   ├── upper3.hpp
│               │   │   │   ├── upper4.hpp
│               │   │   │   └── upper5.hpp
│               │   │   ├── finish.hpp
│               │   │   ├── iter/
│               │   │   │   ├── forward1.hpp
│               │   │   │   ├── forward2.hpp
│               │   │   │   ├── forward3.hpp
│               │   │   │   ├── forward4.hpp
│               │   │   │   ├── forward5.hpp
│               │   │   │   ├── reverse1.hpp
│               │   │   │   ├── reverse2.hpp
│               │   │   │   ├── reverse3.hpp
│               │   │   │   ├── reverse4.hpp
│               │   │   │   └── reverse5.hpp
│               │   │   ├── local.hpp
│               │   │   ├── rlocal.hpp
│               │   │   ├── self.hpp
│               │   │   └── start.hpp
│               │   ├── iterate.hpp
│               │   ├── local.hpp
│               │   └── self.hpp
│               ├── iteration.hpp
│               ├── library.hpp
│               ├── limits.hpp
│               ├── list/
│               │   ├── adt.hpp
│               │   ├── append.hpp
│               │   ├── at.hpp
│               │   ├── cat.hpp
│               │   ├── detail/
│               │   │   ├── dmc/
│               │   │   │   └── fold_left.hpp
│               │   │   ├── edg/
│               │   │   │   ├── fold_left.hpp
│               │   │   │   └── fold_right.hpp
│               │   │   ├── fold_left.hpp
│               │   │   └── fold_right.hpp
│               │   ├── enum.hpp
│               │   ├── filter.hpp
│               │   ├── first_n.hpp
│               │   ├── fold_left.hpp
│               │   ├── fold_right.hpp
│               │   ├── for_each.hpp
│               │   ├── for_each_i.hpp
│               │   ├── for_each_product.hpp
│               │   ├── rest_n.hpp
│               │   ├── reverse.hpp
│               │   ├── size.hpp
│               │   ├── to_array.hpp
│               │   ├── to_seq.hpp
│               │   ├── to_tuple.hpp
│               │   └── transform.hpp
│               ├── list.hpp
│               ├── logical/
│               │   ├── and.hpp
│               │   ├── bitand.hpp
│               │   ├── bitnor.hpp
│               │   ├── bitor.hpp
│               │   ├── bitxor.hpp
│               │   ├── bool.hpp
│               │   ├── compl.hpp
│               │   ├── nor.hpp
│               │   ├── not.hpp
│               │   ├── or.hpp
│               │   └── xor.hpp
│               ├── logical.hpp
│               ├── max.hpp
│               ├── min.hpp
│               ├── punctuation/
│               │   ├── comma.hpp
│               │   ├── comma_if.hpp
│               │   ├── detail/
│               │   │   └── is_begin_parens.hpp
│               │   ├── is_begin_parens.hpp
│               │   ├── paren.hpp
│               │   ├── paren_if.hpp
│               │   └── remove_parens.hpp
│               ├── punctuation.hpp
│               ├── repeat.hpp
│               ├── repeat_2nd.hpp
│               ├── repeat_3rd.hpp
│               ├── repeat_from_to.hpp
│               ├── repeat_from_to_2nd.hpp
│               ├── repeat_from_to_3rd.hpp
│               ├── repetition/
│               │   ├── deduce_r.hpp
│               │   ├── deduce_z.hpp
│               │   ├── detail/
│               │   │   ├── dmc/
│               │   │   │   └── for.hpp
│               │   │   ├── edg/
│               │   │   │   └── for.hpp
│               │   │   ├── for.hpp
│               │   │   └── msvc/
│               │   │       └── for.hpp
│               │   ├── enum.hpp
│               │   ├── enum_binary_params.hpp
│               │   ├── enum_params.hpp
│               │   ├── enum_params_with_a_default.hpp
│               │   ├── enum_params_with_defaults.hpp
│               │   ├── enum_shifted.hpp
│               │   ├── enum_shifted_binary_params.hpp
│               │   ├── enum_shifted_params.hpp
│               │   ├── enum_trailing.hpp
│               │   ├── enum_trailing_binary_params.hpp
│               │   ├── enum_trailing_params.hpp
│               │   ├── for.hpp
│               │   ├── repeat.hpp
│               │   └── repeat_from_to.hpp
│               ├── repetition.hpp
│               ├── selection/
│               │   ├── max.hpp
│               │   └── min.hpp
│               ├── selection.hpp
│               ├── seq/
│               │   ├── cat.hpp
│               │   ├── detail/
│               │   │   ├── binary_transform.hpp
│               │   │   ├── is_empty.hpp
│               │   │   ├── split.hpp
│               │   │   └── to_list_msvc.hpp
│               │   ├── elem.hpp
│               │   ├── enum.hpp
│               │   ├── filter.hpp
│               │   ├── first_n.hpp
│               │   ├── fold_left.hpp
│               │   ├── fold_right.hpp
│               │   ├── for_each.hpp
│               │   ├── for_each_i.hpp
│               │   ├── for_each_product.hpp
│               │   ├── insert.hpp
│               │   ├── pop_back.hpp
│               │   ├── pop_front.hpp
│               │   ├── push_back.hpp
│               │   ├── push_front.hpp
│               │   ├── remove.hpp
│               │   ├── replace.hpp
│               │   ├── rest_n.hpp
│               │   ├── reverse.hpp
│               │   ├── seq.hpp
│               │   ├── size.hpp
│               │   ├── subseq.hpp
│               │   ├── to_array.hpp
│               │   ├── to_list.hpp
│               │   ├── to_tuple.hpp
│               │   ├── transform.hpp
│               │   └── variadic_seq_to_seq.hpp
│               ├── seq.hpp
│               ├── slot/
│               │   ├── counter.hpp
│               │   ├── detail/
│               │   │   ├── counter.hpp
│               │   │   ├── def.hpp
│               │   │   ├── shared.hpp
│               │   │   ├── slot1.hpp
│               │   │   ├── slot2.hpp
│               │   │   ├── slot3.hpp
│               │   │   ├── slot4.hpp
│               │   │   └── slot5.hpp
│               │   └── slot.hpp
│               ├── slot.hpp
│               ├── stringize.hpp
│               ├── tuple/
│               │   ├── detail/
│               │   │   └── is_single_return.hpp
│               │   ├── eat.hpp
│               │   ├── elem.hpp
│               │   ├── enum.hpp
│               │   ├── insert.hpp
│               │   ├── pop_back.hpp
│               │   ├── pop_front.hpp
│               │   ├── push_back.hpp
│               │   ├── push_front.hpp
│               │   ├── rem.hpp
│               │   ├── remove.hpp
│               │   ├── replace.hpp
│               │   ├── reverse.hpp
│               │   ├── size.hpp
│               │   ├── to_array.hpp
│               │   ├── to_list.hpp
│               │   └── to_seq.hpp
│               ├── tuple.hpp
│               ├── variadic/
│               │   ├── detail/
│               │   │   └── is_single_return.hpp
│               │   ├── elem.hpp
│               │   ├── size.hpp
│               │   ├── to_array.hpp
│               │   ├── to_list.hpp
│               │   ├── to_seq.hpp
│               │   └── to_tuple.hpp
│               ├── variadic.hpp
│               ├── while.hpp
│               └── wstringize.hpp
├── include/
│   └── xloil/
│       ├── AppObjects.h
│       ├── ArrayBuilder.h
│       ├── Async.h
│       ├── AutoBind.h
│       ├── Caller.h
│       ├── Date.h
│       ├── DynamicRegister.h
│       ├── EnumHelper.h
│       ├── Events.h
│       ├── ExcelArray.h
│       ├── ExcelCall.h
│       ├── ExcelObj.h
│       ├── ExcelObjCache.h
│       ├── ExcelRef.h
│       ├── ExcelThread.h
│       ├── ExcelTypeLib.h
│       ├── ExcelUI.h
│       ├── ExportMacro.h
│       ├── FPArray.h
│       ├── FuncSpec.h
│       ├── Interface.h
│       ├── Limits.h
│       ├── Log.h
│       ├── LogWindow.h
│       ├── NumericTypeConverters.h
│       ├── ObjectCache.h
│       ├── PString.h
│       ├── Plugin.h
│       ├── Preprocessor.h
│       ├── Range.h
│       ├── Register.h
│       ├── RtdServer.h
│       ├── State.h
│       ├── StaticRegister.h
│       ├── StringUtils.h
│       ├── Throw.h
│       ├── TypeConverters.h
│       ├── Version.h
│       ├── WindowsSlim.h
│       ├── XlCallSlim.h
│       ├── XllEntryPoint.h
│       └── xlOil.h
├── libs/
│   ├── SetRoot.props
│   ├── xlOilPlugin.props
│   ├── xlOilStaticLib.props
│   ├── xlOil_Python/
│   │   ├── ArrayHelpers.h
│   │   ├── AsyncFunctions.cpp
│   │   ├── AsyncFunctions.h
│   │   ├── CPython.h
│   │   ├── EventLoop.cpp
│   │   ├── EventLoop.h
│   │   ├── Loader/
│   │   │   ├── StubLoader.cpp
│   │   │   └── xlOil_Python.vcxproj
│   │   ├── Main.cpp
│   │   ├── Package/
│   │   │   ├── TestConfig.py
│   │   │   ├── generate_stubs.py
│   │   │   ├── setup.py
│   │   │   ├── test_JupyterConnection.py
│   │   │   ├── test_PythonAutomation.py
│   │   │   ├── test_SpreadsheetRunner.py
│   │   │   ├── xlOil_Python_Package.pyproj
│   │   │   └── xloil/
│   │   │       ├── __init__.py
│   │   │       ├── _core.py
│   │   │       ├── _event_loop.py
│   │   │       ├── _paths.py
│   │   │       ├── _pyinstaller/
│   │   │       │   ├── __init__.py
│   │   │       │   └── hook-xloil.py
│   │   │       ├── _superreload.py
│   │   │       ├── com.py
│   │   │       ├── command_line.py
│   │   │       ├── debug.py
│   │   │       ├── excelfuncs.py
│   │   │       ├── func_inspect.py
│   │   │       ├── gui/
│   │   │       │   ├── __init__.py
│   │   │       │   ├── qt_console.py
│   │   │       │   ├── qtpy.py
│   │   │       │   ├── tk_console.py
│   │   │       │   ├── tkinter.py
│   │   │       │   └── wx.py
│   │   │       ├── importer.py
│   │   │       ├── jupyter.py
│   │   │       ├── jupyter_kernel.py
│   │   │       ├── logging.py
│   │   │       ├── matplotlib.py
│   │   │       ├── pandas.py
│   │   │       ├── pillow.py
│   │   │       ├── register.py
│   │   │       ├── rtd.py
│   │   │       ├── stubs/
│   │   │       │   ├── __init__.py
│   │   │       │   └── xloil_core/
│   │   │       │       ├── __init__.py
│   │   │       │       └── event/
│   │   │       │           └── __init__.py
│   │   │       ├── type_converters.py
│   │   │       └── xloil_ribbon.py
│   │   ├── PyAddin.cpp
│   │   ├── PyAddin.h
│   │   ├── PyAddress.cpp
│   │   ├── PyAddress.h
│   │   ├── PyAppCallRun.cpp
│   │   ├── PyAppCallRun.h
│   │   ├── PyAppObjects.cpp
│   │   ├── PyCOM.cpp
│   │   ├── PyCOM.h
│   │   ├── PyCache.cpp
│   │   ├── PyCache.h
│   │   ├── PyCore.cpp
│   │   ├── PyCore.h
│   │   ├── PyEvents.cpp
│   │   ├── PyEvents.h
│   │   ├── PyFunctionRegister.cpp
│   │   ├── PyFunctionRegister.h
│   │   ├── PyFuture.h
│   │   ├── PyHelpers.cpp
│   │   ├── PyHelpers.h
│   │   ├── PyImage.cpp
│   │   ├── PyImage.h
│   │   ├── PyLogWriter.cpp
│   │   ├── PyObjectGC.cpp
│   │   ├── PyRibbon.cpp
│   │   ├── PyRtd.cpp
│   │   ├── PyRtd.h
│   │   ├── PyRunLater.cpp
│   │   ├── PySettings.props
│   │   ├── PySettings310.props
│   │   ├── PySettings311.props
│   │   ├── PySettings312.props
│   │   ├── PySettings313.props
│   │   ├── PySettings314.props
│   │   ├── PySettings36.props
│   │   ├── PySettings37.props
│   │   ├── PySettings38.props
│   │   ├── PySettings39.props
│   │   ├── PySource.cpp
│   │   ├── PySource.h
│   │   ├── PyStatusBar.cpp
│   │   ├── TypeConversion/
│   │   │   ├── BasicTypes.cpp
│   │   │   ├── BasicTypes.h
│   │   │   ├── ConverterInterface.h
│   │   │   ├── Numpy.h
│   │   │   ├── NumpyDatetime.cpp
│   │   │   ├── NumpyDatetime.h
│   │   │   ├── NumpyFromExcel.cpp
│   │   │   ├── NumpyHelpers.cpp
│   │   │   ├── NumpyHelpers.h
│   │   │   ├── NumpyPandas.cpp
│   │   │   ├── NumpyToExcel.cpp
│   │   │   ├── PyCustomType.cpp
│   │   │   ├── PyDateType.cpp
│   │   │   ├── PyDateType.h
│   │   │   ├── PyDictType.cpp
│   │   │   ├── PyDictType.h
│   │   │   ├── PyExcelArrayType.cpp
│   │   │   ├── PyExcelArrayType.h
│   │   │   ├── PyRangeType.cpp
│   │   │   ├── PyTupleType.cpp
│   │   │   └── PyTupleType.h
│   │   ├── xlOil_Python310.vcxproj
│   │   ├── xlOil_Python311.vcxproj
│   │   ├── xlOil_Python312.vcxproj
│   │   ├── xlOil_Python313.vcxproj
│   │   ├── xlOil_Python314.vcxproj
│   │   ├── xlOil_Python36.vcxproj
│   │   ├── xlOil_Python37.vcxproj
│   │   ├── xlOil_Python38.vcxproj
│   │   ├── xlOil_Python39.vcxproj
│   │   └── xlOil_Python39.vcxproj.filters
│   ├── xlOil_SQL/
│   │   ├── Cache.cpp
│   │   ├── Cache.h
│   │   ├── Common.cpp
│   │   ├── Common.h
│   │   ├── Main.cpp
│   │   ├── XlArrayTable.cpp
│   │   ├── XlArrayTable.h
│   │   ├── xlOil_SQL.vcxproj
│   │   ├── xlOil_SQL.vcxproj.filters
│   │   ├── xloSql.cpp
│   │   ├── xloSqlDB.cpp
│   │   ├── xloSqlQuery.cpp
│   │   ├── xloSqlTable.cpp
│   │   └── xloSqlTables.cpp
│   └── xlOil_Utils/
│       ├── Main.cpp
│       ├── RegexHelpers.h
│       ├── xlOil_Utils.vcxproj
│       ├── xloBlock.cpp
│       ├── xloConcat.cpp
│       ├── xloFill.cpp
│       ├── xloFillNA.cpp
│       ├── xloIndex.cpp
│       ├── xloPad.cpp
│       ├── xloRegex.cpp
│       ├── xloSearch.cpp
│       ├── xloSort.cpp
│       └── xloSplit.cpp
├── src/
│   ├── BuildPaths.props
│   ├── Common.props
│   ├── Debug.props
│   ├── Release.props
│   ├── external/
│   │   ├── asmjit.vcxproj
│   │   ├── rdcfswatcher.vcxproj
│   │   └── spdlog.vcxproj
│   ├── xlOil/
│   │   ├── Interface.cpp
│   │   ├── Loaders/
│   │   │   ├── AddinLoader.cpp
│   │   │   ├── AddinLoader.h
│   │   │   ├── CoreEntryPoint.cpp
│   │   │   ├── CoreEntryPoint.h
│   │   │   ├── PluginLoader.cpp
│   │   │   └── PluginLoader.h
│   │   ├── Log.cpp
│   │   ├── xlOil.vcxproj
│   │   └── xlOil.vcxproj.filters
│   ├── xlOil-COM/
│   │   ├── API/
│   │   │   ├── ComUtils.cpp
│   │   │   ├── Events.cpp
│   │   │   ├── ExcelRange.cpp
│   │   │   ├── ExcelThread.cpp
│   │   │   └── RtdServer.cpp
│   │   ├── AppObjects.cpp
│   │   ├── ClassFactory.cpp
│   │   ├── ClassFactory.h
│   │   ├── ComAddin.cpp
│   │   ├── ComAddin.h
│   │   ├── ComEventSink.cpp
│   │   ├── ComEventSink.h
│   │   ├── ComVariant.cpp
│   │   ├── ComVariant.h
│   │   ├── Connect.cpp
│   │   ├── Connect.h
│   │   ├── CustomTaskPane.cpp
│   │   ├── CustomTaskPane.h
│   │   ├── RibbonExtensibility.cpp
│   │   ├── RibbonExtensibility.h
│   │   ├── RtdAsyncManager.cpp
│   │   ├── RtdAsyncManager.h
│   │   ├── RtdManager.cpp
│   │   ├── RtdManager.h
│   │   ├── RtdServerWorker.h
│   │   ├── TaskPaneHostControl.cpp
│   │   ├── TaskPaneHostControl.h
│   │   ├── WorkbookScopeFunctions.cpp
│   │   ├── WorkbookScopeFunctions.h
│   │   ├── XllContextInvoke.cpp
│   │   ├── XllContextInvoke.h
│   │   ├── xlOil-COM.vcxproj
│   │   └── xlOil-COM.vcxproj.filters
│   ├── xlOil-Dynamic/
│   │   ├── DynamicRegistration.cpp
│   │   ├── ExternalRegionAllocator.h
│   │   ├── LocalFunctions.cpp
│   │   ├── LocalFunctions.h
│   │   ├── PEHelper.cpp
│   │   ├── PEHelper.h
│   │   ├── Thunker.cpp
│   │   ├── Thunker.h
│   │   ├── xlOil-Dynamic.vcxproj
│   │   └── xlOil-Dynamic.vcxproj.filters
│   ├── xlOil-Funcs/
│   │   ├── ExcelObjCache.cpp
│   │   ├── xlOil-Funcs.vcxproj
│   │   ├── xlOil-Funcs.vcxproj.filters
│   │   ├── xloHelp.cpp
│   │   ├── xloLog.cpp
│   │   ├── xloReload.cpp
│   │   └── xloVersion.cpp
│   ├── xlOil-Loader/
│   │   ├── LoaderEntryPoint.cpp
│   │   ├── xlOil-Loader.vcxproj
│   │   └── xlOilAddin.def
│   ├── xlOil-XLL/
│   │   ├── ArrayBuilder.cpp
│   │   ├── Async.cpp
│   │   ├── Caller.cpp
│   │   ├── Date.cpp
│   │   ├── ExcelArray.cpp
│   │   ├── ExcelCall.cpp
│   │   ├── ExcelCallMapping.h
│   │   ├── ExcelObj.cpp
│   │   ├── ExcelRef.cpp
│   │   ├── FPArray.cpp
│   │   ├── FuncRegistry.cpp
│   │   ├── FuncRegistry.h
│   │   ├── Intellisense.cpp
│   │   ├── Intellisense.h
│   │   ├── Log.cpp
│   │   ├── LogWindow.cpp
│   │   ├── LogWindowSink.cpp
│   │   ├── LogWindowSink.h
│   │   ├── State.cpp
│   │   ├── StaticRegister.cpp
│   │   ├── Throw.cpp
│   │   ├── XlCall.cpp
│   │   ├── XllEvents.cpp
│   │   ├── xlOil-XLL.vcxproj
│   │   └── xlOil-XLL.vcxproj.filters
│   └── xlOilHelpers/
│       ├── Environment.cpp
│       ├── Environment.h
│       ├── Exception.h
│       ├── GuidUtils.cpp
│       ├── GuidUtils.h
│       ├── Settings.cpp
│       ├── Settings.h
│       ├── Utils.h
│       └── xlOilHelpers.vcxproj
├── tests/
│   ├── AutoSheets/
│   │   ├── PythonTest.py
│   │   ├── PythonTest.xlsx
│   │   ├── TestModule.py
│   │   ├── TestSQL.xlsx
│   │   ├── TestUtils.ipynb
│   │   └── TestUtils.xlsx
│   ├── CodePageConversion.cpp
│   ├── Date.cpp
│   ├── Environment.cpp
│   ├── ManualSheets/
│   │   ├── python/
│   │   │   ├── PySpeedTest.py
│   │   │   ├── PySpeedTest.xlsm
│   │   │   ├── PythonRTDTest.py
│   │   │   ├── PythonRTDTest.xlsx
│   │   │   ├── PythonTestAsync.py
│   │   │   ├── PythonTestAsync.xlsm
│   │   │   ├── PythonTestUI.py
│   │   │   ├── PythonTestUI.xlsm
│   │   │   ├── TestJupyter.xlsx
│   │   │   └── TestJupyterConnection.ipynb
│   │   └── rtd/
│   │       └── RtdTest.xlsx
│   ├── PString.cpp
│   ├── TestAddin/
│   │   ├── AutoBind.cpp
│   │   ├── CacheTest.cpp
│   │   ├── CacheTest2.cpp
│   │   ├── CallbackTest.cpp
│   │   ├── ExoticArgTest.cpp
│   │   ├── Main.cpp
│   │   ├── RtdServerTest.cpp
│   │   ├── TestAddin.vcxproj
│   │   ├── TestAddin.vcxproj.filters
│   │   └── TestTestAddin.xlsx
│   ├── TestArrayBuilder.cpp
│   ├── TestCOM.cpp
│   ├── TestCache.cpp
│   ├── TestExcelCall.cpp
│   ├── TestExcelObj.cpp
│   ├── TestGuid.cpp
│   ├── TestRange.cpp
│   ├── TestSimpleAllocator.cpp
│   ├── TestStringUtils.cpp
│   ├── TestTempFile.cpp
│   ├── TestThunker.cpp
│   ├── Tests.vcxproj
│   └── Tests.vcxproj.filters
├── tools/
│   ├── BuildRelease.cmd
│   ├── DownloadDependencies.cmd
│   ├── WriteInclude.ps1
│   ├── WriteVersion.ps1
│   ├── stage.py
│   ├── xlOil_Install.ps1
│   ├── xlOil_NewAddin.ps1
│   ├── xlOil_RegistryClean.ps1
│   └── xlOil_Remove.ps1
└── xlOil.sln
Download .txt
Showing preview only (213K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2704 symbols across 265 files)

FILE: external/Excel2013SDK/INCLUDE/XLCALL.H
  type INT32 (line 24) | typedef INT32 BOOL;
  type WCHAR (line 25) | typedef WCHAR XCHAR;
  type INT32 (line 26) | typedef INT32 RW;
  type INT32 (line 27) | typedef INT32 COL;
  type DWORD_PTR (line 28) | typedef DWORD_PTR IDSHEET;
  type XLREF (line 36) | typedef struct xlref
  type XLMREF (line 53) | typedef struct xlmref
  type XLREF12 (line 66) | typedef struct xlref12
  type XLMREF12 (line 83) | typedef struct xlmref12
  type FP (line 96) | typedef struct _FP
  type FP12 (line 109) | typedef struct _FP12
  type XLOPER (line 125) | typedef struct xloper
  type XLOPER12 (line 187) | typedef struct xloper12
  type FMLAINFO (line 456) | typedef struct _fmlainfo
  type MOUSEINFO (line 466) | typedef struct _mouseinfo

FILE: external/Excel2013SDK/SRC/XLCALL.CPP
  function FetchExcel12EntryPt (line 36) | __forceinline void FetchExcel12EntryPt(void)
  function SetExcel12EntryPt (line 62) | __declspec(dllexport)
  function Excel12 (line 72) | int _cdecl Excel12(int xlfn, LPXLOPER12 operRes, int count, ...)
  function Excel12v (line 103) | int pascal Excel12v(int xlfn, LPXLOPER12 operRes, int count, LPXLOPER12 ...

FILE: include/xloil/AppObjects.h
  type IDispatch (line 12) | struct IDispatch
  type IUnknown (line 13) | struct IUnknown
  type IEnumUnknown (line 14) | struct IEnumUnknown
  type IEnumVARIANT (line 15) | struct IEnumVARIANT
  function namespace (line 17) | namespace Excel
  function namespace (line 30) | namespace xloil
  function namespace (line 43) | namespace xloil
  function T (line 188) | T operator*()
  function operator (line 230) | auto operator[](const std::wstring_view& name) const
  function count (line 236) | size_t count() const;

FILE: include/xloil/ArrayBuilder.h
  function namespace (line 7) | namespace xloil
  function class (line 103) | class ArrayBuilderElement
  function assign (line 151) | void assign(const ExcelObj& x)
  function take (line 170) | void take(ExcelObj&& x)
  function emplace_pstr (line 182) | void emplace_pstr(wchar_t* pstr)
  function copy_string (line 187) | void copy_string(const wchar_t* str, size_t len)
  function class (line 216) | class ArrayBuilderIterator
  function operator (line 267) | const auto& operator*() const { return _current; }
  function reference (line 268) | reference operator*() { return _current; }
  function pointer (line 269) | pointer operator->() { return &_current; }
  function class (line 289) | class ExcelArrayBuilder
  function namespace (line 408) | namespace detail
  function class (line 466) | class SequentialArrayBuilder
  function emplace (line 506) | void emplace(ExcelObj&& obj)
  function emplaceNilString (line 542) | void emplaceNilString()
  function emplace (line 549) | void emplace(const PStringRef& pstr)
  function ExcelObj (line 557) | ExcelObj* last()
  function ExcelObj (line 562) | ExcelObj* next()

FILE: include/xloil/Async.h
  function namespace (line 6) | namespace xloil { class ExcelObj; }
  function namespace (line 7) | namespace xloil
  function class (line 32) | class AsyncHelper
  function virtual (line 44) | virtual ~AsyncHelper()
  function virtual (line 48) | virtual void cancel()
  function result (line 52) | void result(const ExcelObj& value)

FILE: include/xloil/AutoBind.h
  function namespace (line 9) | namespace xloil
  type DefaultConverters (line 161) | struct DefaultConverters

FILE: include/xloil/Caller.h
  function namespace (line 10) | namespace xloil

FILE: include/xloil/Date.h
  function namespace (line 8) | namespace std { struct tm; }
  function namespace (line 9) | namespace xloil

FILE: include/xloil/DynamicRegister.h
  function namespace (line 5) | namespace xloil
  function namespace (line 73) | namespace detail
  function XLOIL_EXPORT (line 142) | XLOIL_EXPORT std::shared_ptr<RegisteredWorksheetFunc> registerFunc() con...
  function ExcelObj (line 153) | inline ExcelObj* LambdaSpec<int>::call(const ExcelObj** args) const
  function ExcelObj (line 159) | inline ExcelObj* LambdaSpec<void>::call(const ExcelObj** args) const

FILE: include/xloil/EnumHelper.h
  function namespace (line 4) | namespace xloil

FILE: include/xloil/Events.h
  function namespace (line 13) | namespace xloil { class ExcelRange; }
  function namespace (line 17) | namespace std {
  function namespace (line 21) | namespace xloil
  function catch (line 38) | struct VoidCollector
  function namespace (line 66) | namespace Event
  function R (line 166) | R fire(Args... args) const
  function clear (line 187) | void clear()
  function FileAction (line 333) | enum class FileAction

FILE: include/xloil/ExcelArray.h
  function namespace (line 6) | namespace xloil
  function operator (line 112) | bool operator!=(iterator other) const { return !(*this == other); }
  function operator (line 114) | const auto& operator*() const { return *_p; }
  function operator (line 115) | auto& operator*() { return *_p; }
  function ExcelArrayIterator (line 124) | struct std::iterator_traits<xloil::ExcelArrayIterator>
  function namespace (line 142) | namespace xloil
  function XLOIL_EXPORT (line 393) | XLOIL_EXPORT ExcelObj toExcelObj() const;
  function checkRange (line 431) | void checkRange(size_t row, size_t col) const
  function checkRange (line 437) | void checkRange(size_t n) const

FILE: include/xloil/ExcelCall.h
  function namespace (line 8) | namespace xloil

FILE: include/xloil/ExcelObj.h
  function namespace (line 13) | namespace xloil
  function ExcelObj (line 253) | ExcelObj(nullptr_t)
  function reset (line 387) | void reset() noexcept;
  function that (line 426) | bool operator==(const std::wstring_view& that) const
  function isNonEmpty (line 497) | bool isNonEmpty() const
  function isNA (line 518) | bool isNA() const
  function isType (line 537) | bool isType(ExcelType type) const
  function maxStringLength (line 570) | uint16_t maxStringLength() const noexcept;
  type ArrayVal (line 709) | struct ArrayVal
  type RefVal (line 716) | struct RefVal
  type MissingVal (line 722) | struct MissingVal
  function namespace (line 731) | namespace detail
  function XLOIL_XLOPER (line 856) | inline const XLOIL_XLOPER* ExcelObj::cast() const
  function _visitor (line 910) | ApplyVisitor(TVisitor visitor)

FILE: include/xloil/ExcelObjCache.h
  function namespace (line 6) | namespace xloil

FILE: include/xloil/ExcelRef.h
  function namespace (line 8) | namespace xloil
  function explicit (line 127) | explicit ExcelRef(const wchar_t* address)
  function operator (line 163) | operator const ExcelObj& () const noexcept { return _obj; }
  function ExcelObj (line 179) | const ExcelObj& obj() const noexcept { return _obj; }
  function reset (line 189) | void reset() noexcept
  function msxll (line 270) | const msxll::XLREF12& ref() const
  function ExcelObj (line 295) | const ExcelObj& obj() const noexcept { return *this; }
  function class (line 304) | class XllRange : public Range

FILE: include/xloil/ExcelThread.h
  function namespace (line 7) | namespace xloil

FILE: include/xloil/ExcelUI.h
  type VARIANT (line 8) | typedef struct tagVARIANT VARIANT;
  type IDispatch (line 9) | struct IDispatch
  function namespace (line 11) | namespace Excel { struct Window; }
  function namespace (line 12) | namespace xloil { class ExcelWindow; }
  function namespace (line 13) | namespace xloil
  function class (line 67) | class ICustomTaskPaneEvents
  function class (line 89) | class ICustomTaskPane
  function class (line 178) | class IComAddin

FILE: include/xloil/FPArray.h
  function namespace (line 7) | namespace xloil

FILE: include/xloil/FuncSpec.h
  function namespace (line 7) | namespace xloil

FILE: include/xloil/Interface.h
  function namespace (line 9) | namespace toml { class table; }
  function namespace (line 10) | namespace xloil {
  function namespace (line 17) | namespace xloil
  function class (line 161) | class AddinContext
  type PluginContext (line 255) | struct PluginContext

FILE: include/xloil/Limits.h
  function namespace (line 4) | namespace xloil

FILE: include/xloil/Log.h
  function namespace (line 32) | namespace xloil

FILE: include/xloil/LogWindow.h
  type UINT_PTR (line 18) | typedef UINT_PTR WPARAM;
  type LONG_PTR (line 19) | typedef LONG_PTR LPARAM;
  type LONG_PTR (line 20) | typedef LONG_PTR LRESULT;
  type WPARAM (line 21) | typedef LRESULT(CALLBACK* WNDPROC)(HWND, unsigned int, WPARAM, LPARAM);
  function namespace (line 24) | namespace xloil

FILE: include/xloil/NumericTypeConverters.h
  function namespace (line 5) | namespace xloil

FILE: include/xloil/ObjectCache.h
  function namespace (line 11) | namespace xloil
  function TObj (line 112) | const TObj* fetch(size_t i) const
  type detail (line 152) | typedef detail::CellCache<TObj> CellCache;
  function onAfterCalculate (line 162) | void onAfterCalculate()
  function TObj (line 193) | const TObj* fetch(const std::wstring_view& key) const
  function ExcelObj (line 208) | ExcelObj add(
  function ExcelObj (line 217) | ExcelObj add(
  function erase (line 234) | bool erase(const std::wstring_view& key)
  function onWorkbookClose (line 246) | void onWorkbookClose(const wchar_t* wbName)
  function valid (line 282) | bool valid(const std::wstring_view& cacheString)
  function readCount (line 328) | size_t readCount(wchar_t count) const
  function writeCount (line 334) | void writeCount(wchar_t* key, uint16_t iPos) const
  function cache_type (line 347) | static cache_type& cache() {

FILE: include/xloil/PString.h
  function namespace (line 5) | namespace xloil
  function explicit (line 298) | explicit BasicPString(const std::basic_string_view<TChar>& str, TAlloc a...
  function operator (line 354) | operator PStringImpl<TChar>() const
  function operator (line 359) | operator PStringImpl<TChar>()
  function TChar (line 411) | TChar* release()
  function resize (line 422) | void resize(size_type sz)
  function resize (line 496) | void resize(size_type sz)
  function namespace (line 557) | namespace detail

FILE: include/xloil/Plugin.h
  function namespace (line 6) | namespace xloil

FILE: include/xloil/Preprocessor.h
  function namespace (line 10) | namespace xloil { class ExcelObj; }
  function namespace (line 62) | namespace xloil

FILE: include/xloil/Range.h
  function namespace (line 5) | namespace Excel { struct Range; }
  function namespace (line 7) | namespace xloil

FILE: include/xloil/Register.h
  function namespace (line 8) | namespace xloil { class ExcelObj; }
  function namespace (line 10) | namespace xloil

FILE: include/xloil/RtdServer.h
  function namespace (line 7) | namespace xloil
  type IRtdPublisher (line 66) | struct IRtdPublisher
  function IRtdTask (line 113) | struct IRtdAsyncTask : public IRtdTask
  type RtdNotifier (line 123) | struct RtdNotifier
  function noexcept (line 142) | const noexcept
  function namespace (line 155) | namespace detail
  function class (line 204) | class RtdTask : public detail::RtdTaskBase<IRtdTask>
  type RtdAsyncTask (line 225) | struct RtdAsyncTask
  function class (line 273) | class IRtdServer

FILE: include/xloil/State.h
  function namespace (line 4) | namespace xloil

FILE: include/xloil/StaticRegister.h
  function namespace (line 7) | namespace xloil {
  function namespace (line 63) | namespace xloil
  function namespace (line 288) | namespace detail

FILE: include/xloil/StringUtils.h
  function namespace (line 6) | namespace xloil
  function const (line 75) | size_t operator()(
  type ConvertUTF32ToUTF16 (line 85) | struct ConvertUTF32ToUTF16
  function const (line 110) | size_t operator()(
  function const (line 139) | size_t operator()(
  function strlen32 (line 156) | inline size_t strlen32(const char32_t* str, const size_t max)
  function const (line 221) | bool operator()(
  function const (line 227) | bool operator()(const TChar* lhs, const TChar* rhs) const
  function namespace (line 237) | namespace detail
  function unsignedToString (line 381) | inline size_t unsignedToString(size_t value, TChar(&result)[TResultSize])
  function namespace (line 386) | namespace detail
  type StandardAlphabet (line 426) | struct StandardAlphabet
  type DecimalAlphabet (line 443) | struct DecimalAlphabet
  function boost_hash_combine (line 477) | inline size_t boost_hash_combine(size_t seed) { return seed; }
  function const (line 487) | size_t operator()(std::pair<A, B> p) const noexcept

FILE: include/xloil/Throw.h
  function namespace (line 15) | namespace xloil

FILE: include/xloil/TypeConverters.h
  function namespace (line 10) | namespace xloil { class ExcelRef; }
  function namespace (line 11) | namespace xloil

FILE: include/xloil/XlCallSlim.h
  type BYTE (line 27) | typedef unsigned char BYTE;
  type WORD (line 28) | typedef unsigned short WORD;
  type DWORD (line 29) | typedef unsigned long DWORD;
  type __int32 (line 31) | typedef __int32 BOOL;
  type wchar_t (line 32) | typedef wchar_t XCHAR;
  type __int32 (line 33) | typedef __int32 RW;
  type __int32 (line 34) | typedef __int32 COL;
  type DWORD (line 35) | typedef DWORD* IDSHEET;
  type XLREF (line 44) | typedef struct xlref
  type XLMREF (line 61) | typedef struct xlmref
  type XLREF12 (line 74) | typedef struct xlref12
  type XLMREF12 (line 91) | typedef struct xlmref12
  type FP (line 104) | typedef struct _FP
  type FP12 (line 117) | typedef struct _FP12
  type XLOPER (line 133) | typedef struct xloper
  type XLOPER12 (line 195) | typedef struct xloper12
  type FMLAINFO (line 452) | typedef struct _fmlainfo

FILE: include/xloil/XllEntryPoint.h
  function namespace (line 11) | namespace xloil { class RegisteredWorksheetFunc; }
  function namespace (line 13) | namespace XllInfo
  function setDllPath (line 27) | void setDllPath(HMODULE handle)
  function namespace (line 51) | namespace xloil
  function DllMain (line 118) | XLO_ENTRY_POINT(int) DllMain(
  function xlAutoOpen (line 138) | XLO_ENTRY_POINT(int) xlAutoOpen(void)
  function xlAutoClose (line 149) | XLO_ENTRY_POINT(int) xlAutoClose(void)
  function xlHandleCalculationCancelled (line 162) | XLO_ENTRY_POINT(int) xlHandleCalculationCancelled()
  function xlAddInManagerInfo12 (line 174) | XLO_ENTRY_POINT(msxll::XLOPER12*) xlAddInManagerInfo12(msxll::XLOPER12* ...
  function xlAutoAdd (line 205) | XLO_ENTRY_POINT(int) xlAutoAdd()
  function xlAutoRemove (line 217) | XLO_ENTRY_POINT(int) xlAutoRemove()
  function namespace (line 229) | namespace detail

FILE: libs/xlOil_Python/ArrayHelpers.h
  function namespace (line 5) | namespace xloil

FILE: libs/xlOil_Python/AsyncFunctions.cpp
  type xloil (line 27) | namespace xloil
    type Python (line 29) | namespace Python
      type AsyncReturn (line 36) | struct AsyncReturn : public AsyncHelper
        method AsyncReturn (line 38) | AsyncReturn(
        method set_task (line 57) | void set_task(const py::object& task)
        method set_result (line 62) | void set_result(const py::object& value)
        method set_done (line 69) | void set_done()
        method cancel (line 72) | void cancel() override
        method CallerInfo (line 83) | const CallerInfo& caller() const noexcept
      function pythonAsyncCallback (line 94) | void pythonAsyncCallback(
      type RtdAsyncTask (line 148) | struct RtdAsyncTask : public IRtdAsyncTask
        method RtdAsyncTask (line 155) | RtdAsyncTask(const PyFuncInfo& info, const ExcelObj** xlArgs)
        method start (line 169) | void start(IRtdPublish& publisher) override
        method done (line 199) | bool done() noexcept override
        method wait (line 203) | void wait() noexcept override
        method cancel (line 208) | void cancel() override
      function ExcelObj (line 243) | ExcelObj* pythonRtdCallback(

FILE: libs/xlOil_Python/AsyncFunctions.h
  function namespace (line 3) | namespace xloil

FILE: libs/xlOil_Python/EventLoop.cpp
  type xloil (line 9) | namespace xloil
    type Python (line 11) | namespace Python

FILE: libs/xlOil_Python/EventLoop.h
  function namespace (line 6) | namespace ctpl {
  function namespace (line 10) | namespace xloil

FILE: libs/xlOil_Python/Loader/StubLoader.cpp
  function find_home_value (line 21) | int find_home_value(const char* buffer, const char** start, size_t* length)
  type xloil (line 53) | namespace xloil
    type Python (line 55) | namespace Python
      function findPythonHomeDir (line 59) | std::string findPythonHomeDir()
      function XLO_PLUGIN_INIT (line 91) | XLO_PLUGIN_INIT(AddinContext* context, const PluginContext& plugin)

FILE: libs/xlOil_Python/Package/TestConfig.py
  function _set_test_environment (line 9) | def _set_test_environment():

FILE: libs/xlOil_Python/Package/setup.py
  class BinaryDistribution (line 64) | class BinaryDistribution(Distribution):
    method has_ext_modules (line 66) | def has_ext_modules(self):

FILE: libs/xlOil_Python/Package/test_JupyterConnection.py
  function _test_func1 (line 7) | def _test_func1():
  function _test_func2 (line 10) | def _test_func2(x):
  function _test_func3 (line 13) | def _test_func3(x: str, y:int, **kwargs):
  class Test_JupyterConnection (line 16) | class Test_JupyterConnection(unittest.TestCase):
    method test_RegisterFunc (line 18) | def test_RegisterFunc(self):

FILE: libs/xlOil_Python/Package/test_PythonAutomation.py
  class Test_PythonAutomation (line 9) | class Test_PythonAutomation(unittest.TestCase):
    method __init__ (line 10) | def __init__(self, methodName: str = "runTest") -> None:
    method test_range_trim (line 19) | def test_range_trim(self):
    method test_specialcells (line 60) | def test_specialcells(self):
    method test_formula (line 76) | def test_formula(self):
  class Test_PythonUtils (line 86) | class Test_PythonUtils(unittest.TestCase):
    method test_convert_address_a1 (line 88) | def test_convert_address_a1(self):
    method test_convert_address_rc (line 119) | def test_convert_address_rc(self):
    method test_convert_address_tuple (line 138) | def test_convert_address_tuple(self):

FILE: libs/xlOil_Python/Package/test_SpreadsheetRunner.py
  class Test_SpreadsheetRunner (line 11) | class Test_SpreadsheetRunner(unittest.TestCase):
    method test_RunSheets (line 12) | def test_RunSheets(self):

FILE: libs/xlOil_Python/Package/xloil/_core.py
  function _fix_module_for_docs (line 75) | def _fix_module_for_docs(namespace, target, replace):
  class _ActiveWorksheets (line 89) | class _ActiveWorksheets:
    method __getattr__ (line 90) | def __getattr__(self, name):
    method __getitem__ (line 93) | def __getitem__(self, name):
    method __iter__ (line 96) | def __iter__(self):
  class _ActiveWorkbooks (line 100) | class _ActiveWorkbooks:
    method _obj (line 105) | def _obj(self):
    method __getattr__ (line 110) | def __getattr__(self, name):
    method __getitem__ (line 113) | def __getitem__(self, name):
    method __iter__ (line 116) | def __iter__(self):
  function create_gui (line 149) | def create_gui(*args, **kwargs) -> ExcelGUI:
  class Singleton (line 160) | class Singleton(type):
    method __call__ (line 162) | def __call__(cls, *args, **kwargs):
  class StatusBarExecutor (line 168) | class StatusBarExecutor:
    method __init__ (line 173) | def __init__(self, timeout):
    method map (line 176) | def map(self, func, *args, message, job_name: str):

FILE: libs/xlOil_Python/Package/xloil/_event_loop.py
  function _logged_wrapper (line 3) | def _logged_wrapper(func):
  function _logged_wrapper_async (line 14) | async def _logged_wrapper_async(coro):

FILE: libs/xlOil_Python/Package/xloil/_paths.py
  class _SetPathContext (line 10) | class _SetPathContext:
    method __init__ (line 12) | def __init__(self, path):
    method __enter__ (line 16) | def __enter__(self):
    method close (line 20) | def close(self):
    method __exit__ (line 23) | def __exit__(self, *args):
  function add_dll_path (line 26) | def add_dll_path(path):
  function _get_environment_strings (line 38) | def _get_environment_strings():

FILE: libs/xlOil_Python/Package/xloil/_pyinstaller/__init__.py
  function get_hook_dirs (line 3) | def get_hook_dirs():

FILE: libs/xlOil_Python/Package/xloil/_superreload.py
  function update_function (line 67) | def update_function(old, new):
  function update_instances (line 76) | def update_instances(old, new):
  function update_class (line 88) | def update_class(old, new):
  function update_property (line 130) | def update_property(old, new):
  function isinstance2 (line 137) | def isinstance2(a, b, typ):
  function update_generic (line 156) | def update_generic(a, b):
  class StrongRef (line 164) | class StrongRef:
    method __init__ (line 165) | def __init__(self, obj):
    method __call__ (line 168) | def __call__(self):
  function append_obj (line 184) | def append_obj(module, d, name, obj, autoload=False):
  function superreload (line 202) | def superreload(module, reload=reload, old_objects=None, shell=None):

FILE: libs/xlOil_Python/Package/xloil/com.py
  class _Win32ComConstants (line 4) | class _Win32ComConstants:
    method __getattr__ (line 5) | def __getattr__(self, name):
  class PauseExcel (line 23) | class PauseExcel():
    method __enter__ (line 50) | def __enter__(self, events=False, calculation=False, screen_updating=F...
    method __exit__ (line 73) | def __exit__(self, type, value, traceback):
  function fix_name_errors (line 90) | def fix_name_errors(workbook):

FILE: libs/xlOil_Python/Package/xloil/command_line.py
  function _excel_regpath (line 15) | def _excel_regpath(version):
  function _find_excel_version (line 18) | def _find_excel_version():
  function _check_VBA_access (line 25) | def _check_VBA_access(version):
  function _get_xloil_bin_dir (line 42) | def _get_xloil_bin_dir():
  function _remove_from_resiliancy (line 52) | def _remove_from_resiliancy(filename, version):
  function _remove_addin (line 70) | def _remove_addin(excel_version, addin_path):
  function _toml_lit_string (line 83) | def _toml_lit_string(s:str):
  function _get_python_paths (line 87) | def _get_python_paths():
  function _write_python_path_to_ini (line 96) | def _write_python_path_to_ini(ini_txt, bin_dir:str, comment_reg_keys:boo...
  function install_xloil (line 131) | def install_xloil(ini_template:str=None,
  function _remove_xloil (line 182) | def _remove_xloil():
  function _clean_xloil (line 193) | def _clean_xloil():
  function _create_addin (line 209) | def _create_addin(filename):
  function _package_pyinstaller (line 239) | def _package_pyinstaller(ini_template: str,
  function main (line 294) | def main():

FILE: libs/xlOil_Python/Package/xloil/debug.py
  class _Handler_pdb_window (line 3) | class _Handler_pdb_window:
    method __init__ (line 5) | def __init__(self):
    method call (line 8) | def call(self, type, value, trace):
    method _open_console (line 21) | def _open_console(tk_root, trace):
  function debugpy_listen (line 50) | def debugpy_listen(port=None):
  function _is_debugpy_listening (line 91) | def _is_debugpy_listening() -> bool:
  function _debugpy_activate_thread (line 99) | def _debugpy_activate_thread():
  function _debugpy_activate_thread_decorator (line 107) | def _debugpy_activate_thread_decorator(fn):
  function use_debugger (line 135) | def use_debugger(debugger, **kwargs):

FILE: libs/xlOil_Python/Package/xloil/excelfuncs.py
  function xloImport (line 16) | async def xloImport(ModuleName:str, From=None, As=None):
  function _xlo_attr_helper (line 43) | def _xlo_attr_helper(Object, Name:str, *Args, **Kwargs):
  function xloAttr (line 61) | def xloAttr(Object, Name:str, *Args, **Kwargs):
  function xloAttrObj (line 74) | def xloAttrObj(Object, Name:str, *Args, **Kwargs) -> xlo.Cache:
  function xloPyDebug (line 81) | def xloPyDebug(Debugger:str = ""):

FILE: libs/xlOil_Python/Package/xloil/func_inspect.py
  class Arg (line 1) | class Arg:
    class _EMPTY (line 20) | class _EMPTY:
    method __init__ (line 28) | def __init__(self, name, help="", typeof=None, default=_EMPTY, kind=PO...
    method __str__ (line 55) | def __str__(self):
    method has_default (line 66) | def has_default(self):
    method from_signature (line 74) | def from_signature(cls, name, param):
    method full_argspec (line 101) | def full_argspec(cls, func):
    method override_arglist (line 113) | def override_arglist(arglist, replacements):

FILE: libs/xlOil_Python/Package/xloil/gui/__init__.py
  class CustomTaskPane (line 14) | class CustomTaskPane:
    method __init__ (line 33) | def __init__(self):
    method _attach_frame_async (line 36) | async def _attach_frame_async(self, frame: typing.Awaitable[TaskPaneFr...
    method _attach_frame (line 48) | def _attach_frame(self, frame: typing.Awaitable[TaskPaneFrame]):
    method _get_hwnd (line 60) | def _get_hwnd(self) -> typing.Awaitable[typing.Tuple[int, bool]]:
    method on_destroy (line 68) | def on_destroy(self):
    method pane (line 76) | def pane(self) -> TaskPaneFrame:
    method visible (line 81) | def visible(self) -> bool:
    method visible (line 86) | def visible(self, value: bool):
    method size (line 90) | def size(self) -> typing.Tuple[int, int]:
    method size (line 95) | def size(self, value: typing.Tuple[int, int]):
    method position (line 99) | def position(self) -> str:
  function find_task_pane (line 105) | def find_task_pane(title:str=None, workbook=None, window=None) -> Custom...
  function _try_create_from_qwidget (line 148) | def _try_create_from_qwidget(obj) -> CustomTaskPane:
  function _try_create_from_wxframe (line 165) | def _try_create_from_wxframe(obj) -> CustomTaskPane:
  function _get_pane_name (line 173) | def _get_pane_name(pane):
  function _attach_task_pane_async (line 180) | async def _attach_task_pane_async(
  function _attach_task_pane (line 213) | def _attach_task_pane(
  class _GuiExecutor (line 241) | class _GuiExecutor(futures.Executor):
    method __init__ (line 249) | def __init__(self, name):
    method _make_ready (line 262) | def _make_ready(self):
    method _do_work (line 268) | def _do_work(self):
    method submit (line 281) | def submit(self, fn, *args, **kwargs) -> futures.Future:
    method submit_async (line 302) | async def submit_async(self, fn, *args, **kwargs):
    method shutdown (line 309) | def shutdown(self, wait=True, cancel_futures=False):
    method _main_loop (line 317) | def _main_loop(self):
    method _wrap (line 330) | def _wrap(self, fn, sync=True, discard=False):
  class _ConstructInExecutor (line 353) | class _ConstructInExecutor(type):
    method __new__ (line 362) | def __new__(cls, name, bases, namespace, executor:futures.Executor = T...
    method __init__ (line 365) | def __init__(cls, name, bases, namespace, executor:futures.Executor = ...
    method __call__ (line 374) | def __call__(cls, *args, **kwargs):

FILE: libs/xlOil_Python/Package/xloil/gui/qt_console.py
  function create_qtconsole_inprocess (line 4) | def create_qtconsole_inprocess():

FILE: libs/xlOil_Python/Package/xloil/gui/qtpy.py
  function _create_Qt_app (line 18) | def _create_Qt_app():
  class QtExecutor (line 71) | class QtExecutor(_GuiExecutor):
    method __init__ (line 73) | def __init__(self):
    method app (line 79) | def app(self):
    method submit (line 85) | def submit(self, fn, *args, **kwargs):
    method _main (line 91) | def _main(self):
    method _shutdown (line 116) | def _shutdown(self):
  function Qt_thread (line 123) | def Qt_thread(fn=None, discard=False) -> QtExecutor:
  class QtThreadTaskPane (line 162) | class QtThreadTaskPane(CustomTaskPane, metaclass=_ConstructInExecutor, e...
    method __init__ (line 169) | def __init__(self, widget=None):
    method widget (line 179) | def widget(self):
    method _get_hwnd (line 186) | def _get_hwnd(self):
    method on_destroy (line 201) | def on_destroy(self):

FILE: libs/xlOil_Python/Package/xloil/gui/tk_console.py
  class TkConsole (line 11) | class TkConsole(tkinter.Frame):
    method __init__ (line 37) | def __init__(self, parent, invoke, **kwargs):
    method destroy (line 72) | def destroy(self):
    method _press_enter (line 77) | def _press_enter(self, event):
    method _press_updown (line 95) | def _press_updown(self, step:int):
    method _press_left (line 108) | def _press_left(self, event):
    method _press_up (line 114) | def _press_up(self, event):
    method _press_down (line 117) | def _press_down(self, event):
    method _create_text_widget (line 120) | def _create_text_widget(self, options):
    method write (line 145) | def write(self, string):
    method flush (line 155) | def flush(self):
    method readline (line 158) | def readline(self):

FILE: libs/xlOil_Python/Package/xloil/gui/tkinter.py
  class TkExecutor (line 12) | class TkExecutor(_GuiExecutor):
    method __init__ (line 14) | def __init__(self):
    method root (line 19) | def root(self):
    method _do_work (line 22) | def _do_work(self):
    method _main (line 26) | def _main(self):
    method _shutdown (line 46) | def _shutdown(self):
  function Tk_thread (line 57) | def Tk_thread(fn=None, discard=False) -> TkExecutor:
  class TkThreadTaskPane (line 90) | class TkThreadTaskPane(CustomTaskPane, metaclass=_ConstructInExecutor, e...
    method __init__ (line 95) | def __init__(self):
    method top_level (line 100) | def top_level(self) -> tkinter.Toplevel:
    method _get_hwnd (line 107) | def _get_hwnd(self):
    method on_destroy (line 116) | def on_destroy(self):

FILE: libs/xlOil_Python/Package/xloil/gui/wx.py
  class WxExecutor (line 14) | class WxExecutor(_GuiExecutor):
    method __init__ (line 16) | def __init__(self):
    method app (line 21) | def app(self):
    method _do_work (line 24) | def _do_work(self):
    method _main (line 29) | def _main(self):
    method _shutdown (line 57) | def _shutdown(self):
  function wx_thread (line 68) | def wx_thread(fn=None, discard=False) -> WxExecutor:
  class wx (line 101) | class wx:
    class Frame (line 102) | class Frame:
  class WxThreadTaskPane (line 106) | class WxThreadTaskPane(CustomTaskPane, metaclass=_ConstructInExecutor, e...
    method __init__ (line 111) | def __init__(self, frame=None):
    method frame (line 121) | def frame(self) -> wx.Frame:
    method _get_hwnd (line 128) | def _get_hwnd(self):
    method on_destroy (line 137) | def on_destroy(self):

FILE: libs/xlOil_Python/Package/xloil/importer.py
  class ImportHelper (line 22) | class ImportHelper(metaclass=Singleton):
    method __init__ (line 28) | def __init__(self):
    method watched_modules (line 48) | def watched_modules(self) -> Dict[str, str]:
    method module_addin (line 55) | def module_addin(self) -> Dict[str, str]:
    method ignore_paths (line 63) | def ignore_paths(self) -> List[str]:
    method reload (line 69) | def reload(self, module, *args, **kwargs):
    method watch_module (line 73) | def watch_module(self, module: ModuleType):
    method _on_file_modified (line 100) | def _on_file_modified(self, filepath):
  function linked_workbook (line 114) | def linked_workbook() -> str:
  function source_addin (line 124) | def source_addin() -> Addin:
  function get_event_loop (line 146) | def get_event_loop():
  function _import_file (line 155) | def _import_file(path, addin=None, workbook_name:str=None):
  function _import_and_scan (line 201) | def _import_and_scan(module_names, addin):
  function _import_file_and_scan (line 250) | def _import_file_and_scan(path, addin=None, workbook_name:str=None):
  function import_functions (line 276) | def import_functions(source:str, names=None, as_names=None, addin:Addin=...
  class _LoadAndScanHook (line 365) | class _LoadAndScanHook(SourceFileLoader):
    method __init__ (line 367) | def __init__(self, fullname: str, path: str) -> None:
    method exec_module (line 371) | def exec_module(self, module):
  class _UrlLoader (line 386) | class _UrlLoader(importlib.abc.FileLoader, importlib.abc.SourceLoader):
    method get_data (line 390) | def get_data(self, path):
    method exec_module (line 409) | def exec_module(self, module):
  class _SpecifiedPathFinder (line 417) | class _SpecifiedPathFinder(importlib.abc.MetaPathFinder):
    method find_spec (line 426) | def find_spec(self, fullname, path, target=None):
    method find_module (line 441) | def find_module(self, fullname, path):
    method add_path (line 444) | def add_path(self, name, path):
  function _install_import_hook (line 449) | def _install_import_hook():

FILE: libs/xlOil_Python/Package/xloil/jupyter.py
  function _remove_ansi_escapes (line 20) | def _remove_ansi_escapes(s):
  class _FuncDescriptionDecoder (line 26) | class _FuncDescriptionDecoder(json.JSONDecoder):
    method __init__ (line 34) | def __init__(self, *args, **kwargs):
    method object_hook (line 37) | def object_hook(self, dct):
  function _register_func_description (line 54) | def _register_func_description(desc: _FuncDescription, connection):
  class _VariableWatcher (line 81) | class _VariableWatcher(xlo.RtdPublisher):
    method __init__ (line 87) | def __init__(self, var_name, topic_name, connection):
    method connect (line 93) | def connect(self, num_subscribers):
    method disconnect (line 104) | def disconnect(self, num_subscribers):
    method stop (line 109) | def stop(self):
    method done (line 112) | def done(self):
    method topic (line 115) | def topic(self):
  function _file_to_string (line 118) | def _file_to_string(filepath, indent="  "):
  class JupyterNotReadyError (line 131) | class JupyterNotReadyError(Exception):
  function _rtd_server (line 136) | def _rtd_server():
  class _JupyterConnection (line 143) | class _JupyterConnection:
    method __init__ (line 150) | def __init__(self, connection_file):
    method connect (line 162) | async def connect(self):
    method close (line 228) | def close(self):
    method wait_for_restart (line 250) | async def wait_for_restart(self):
    method execute (line 268) | def execute(self, *args, **kwargs):
    method aexecute (line 282) | async def aexecute(self, command:str, **kwargs):
    method invoke (line 298) | async def invoke(self, func_name, *args, **kwargs):
    method _watch_prefix (line 315) | def _watch_prefix(self, name):
    method watch_variable (line 320) | def watch_variable(self, name):
    method stop_watch_variable (line 338) | def stop_watch_variable(self, name):
    method publish_variables (line 344) | def publish_variables(self, updates:dict):
    method process_messages (line 348) | async def process_messages(self):
    method _process_xloil_message (line 409) | def _process_xloil_message(self, message_type, payload, pending=None):
  class _JupyterTopic (line 443) | class _JupyterTopic(xlo.RtdPublisher):
    method __init__ (line 445) | def __init__(self, topic, connection_file):
    method connect (line 451) | def connect(self, num_subscribers):
    method disconnect (line 480) | def disconnect(self, num_subscribers):
    method stop (line 490) | def stop(self):
    method done (line 495) | def done(self):
    method topic (line 498) | def topic(self):
  function _find_kernel_for_notebook (line 502) | def _find_kernel_for_notebook(server, token, filename):
  function _find_connection_for_notebook (line 512) | def _find_connection_for_notebook(filename):
  class JupyterConnectionLookup (line 522) | class JupyterConnectionLookup:
    method read (line 523) | def read(self, x):
  function xloJpyConnect (line 539) | def xloJpyConnect(ConnectInfo: str):
  function xloJpyWatch (line 578) | def xloJpyWatch(Connection: JupyterConnectionLookup, Name):
  function xloJpyRun (line 590) | async def xloJpyRun(Connection:JupyterConnectionLookup,

FILE: libs/xlOil_Python/Package/xloil/jupyter_kernel.py
  class _xlOilJupyterImpl (line 4) | class _xlOilJupyterImpl:
    method __init__ (line 6) | def __init__(self, ipy_shell, excel_hwnd):
    method _pickle (line 13) | def _pickle(obj):
    method _unpickle (line 18) | def _unpickle(dump:str):
    method _serialise (line 22) | def _serialise(self, obj):
    class _MonitoredVariables (line 34) | class _MonitoredVariables:
      method __init__ (line 39) | def __init__(self, ipy_shell):
      method post_execute (line 48) | def post_execute(self):
      method watch (line 65) | def watch(self, name):
      method stop_watch (line 71) | def stop_watch(self, name):
      method unhook (line 75) | def unhook(self):
    class _FuncDescription (line 78) | class _FuncDescription:
      method __init__ (line 82) | def __init__(self, func_name, name, help, args, return_type):
    method _function_invoke (line 89) | def _function_invoke(self, func, args_data, kwargs_data):
    method func (line 99) | def func(self,
    method app (line 131) | def app(self):

FILE: libs/xlOil_Python/Package/xloil/logging.py
  function _log_warnings (line 16) | def _log_warnings(message, category, filename, lineno, file=None, line=N...
  function log_except (line 21) | def log_except(msg, level='error'):

FILE: libs/xlOil_Python/Package/xloil/matplotlib.py
  class pyplot (line 8) | class pyplot:
    class Figure (line 9) | class Figure:
  function xloPyPlot (line 16) | def xloPyPlot(x, y, width:float=None, height:float=None, **kwargs):
  class ReturnFigure (line 26) | class ReturnFigure:
    method __init__ (line 46) | def __init__(self, size=None,  pos=(0, 0), origin:str=None):
    method write (line 49) | def write(self, fig:pyplot.Figure):

FILE: libs/xlOil_Python/Package/xloil/pandas.py
  class pd (line 8) | class pd:
    class DataFrame (line 9) | class DataFrame:
    class Timestamp (line 13) | class Timestamp:
  class PDFrame (line 23) | class PDFrame:
    method __init__ (line 80) | def __init__(self, headings=True, index=None, cache_objects=False,
    method read (line 90) | def read(self, x):
    method _convert_timezone (line 127) | def _convert_timezone(self, x: pd.Series):
    method write (line 130) | def write(self, frame: pd.DataFrame):
  class PandasTimestamp (line 187) | class PandasTimestamp:
    method read (line 193) | def read(self, val):
    method write (line 196) | def write(self, val):

FILE: libs/xlOil_Python/Package/xloil/pillow.py
  class ReturnImage (line 5) | class ReturnImage:
    method __init__ (line 25) | def __init__(self, size=None,  pos=(0, 0), origin:str=None):
    method write (line 28) | def write(self, val):

FILE: libs/xlOil_Python/Package/xloil/register.py
  function _add_pending_funcs (line 32) | def _add_pending_funcs(module, objects):
  function arg_to_funcarg (line 37) | def arg_to_funcarg(arg: Arg) -> _FuncArg:
  function find_return_converter (line 115) | def find_return_converter(ret_type: type):
  class Caller (line 140) | class Caller:
    method sheet (line 146) | def sheet(self):
    method workbook (line 152) | def workbook(self):
    method address (line 158) | def address(self, a1style=False):
    method __new__ (line 164) | def __new__(self, *args, **kwargs):
  function async_wrapper (line 170) | def async_wrapper(fn):
  class _WorksheetFunc (line 210) | class _WorksheetFunc:
    method __init__ (line 215) | def __init__(self, func, spec):
    method __call__ (line 220) | def __call__(self, *args, **kwargs):
  function func (line 224) | def func(fn=None,
  function _clear_pending_registrations (line 441) | def _clear_pending_registrations(module):
  function scan_module (line 452) | def scan_module(module, addin=None):
  function register_functions (line 487) | def register_functions(funcs, module=None, append=True):

FILE: libs/xlOil_Python/Package/xloil/rtd.py
  class RtdSimplePublisher (line 3) | class RtdSimplePublisher(xlo.RtdPublisher):
    method __init__ (line 10) | def __init__(self, topic):
    method run_task (line 16) | async def run_task(topic):
    method connect (line 19) | def connect(self, num_subscribers):
    method disconnect (line 23) | def disconnect(self, num_subscribers):
    method stop (line 28) | def stop(self):
    method done (line 32) | def done(self):
    method topic (line 35) | def topic(self):
  function subscribe (line 39) | def subscribe(server:xlo.RtdServer, topic:str, coro):

FILE: libs/xlOil_Python/Package/xloil/stubs/xloil_core/__init__.py
  class Addin (line 66) | class Addin():
    method __repr__ (line 67) | def __repr__(self) -> str: ...
    method __str__ (line 68) | def __str__(self) -> str: ...
    method functions (line 69) | def functions(self) -> list[_FuncSpec]:
    method source_files (line 73) | def source_files(self) -> list[str]: ...
    method async_slice (line 75) | def async_slice(self) -> int:
    method async_slice (line 85) | def async_slice(self, arg1: int) -> None:
    method async_throttle (line 92) | def async_throttle(self) -> int:
    method async_throttle (line 102) | def async_throttle(self, arg1: int) -> None:
    method event_loop (line 109) | def event_loop(self) -> object:
    method pathname (line 117) | def pathname(self) -> str:
    method settings (line 122) | def settings(self) -> object:
    method settings_file (line 132) | def settings_file(self) -> str:
  class Address (line 140) | class Address():
    method __call__ (line 160) | def __call__(self, style: str = 'a1', local: bool = False) -> str:
    method __init__ (line 173) | def __init__(self, address: object, sheet: object = None) -> None: ...
    method __iter__ (line 174) | def __iter__(self) -> typing.Iterator[Address]: ...
    method __str__ (line 175) | def __str__(self) -> str: ...
    method a1 (line 177) | def a1(self) -> str:
    method a1_fixed (line 184) | def a1_fixed(self) -> str:
    method from_col (line 191) | def from_col(self) -> int:
    method from_row (line 196) | def from_row(self) -> int:
    method rc (line 201) | def rc(self) -> str:
    method rc_fixed (line 208) | def rc_fixed(self) -> str:
    method sheet (line 215) | def sheet(self) -> str:
    method to_col (line 220) | def to_col(self) -> int:
    method to_row (line 225) | def to_row(self) -> int:
    method tuple (line 230) | def tuple(self) -> tuple:
  class Application (line 235) | class Application():
    method __enter__ (line 259) | def __enter__(self) -> object: ...
    method __exit__ (line 260) | def __exit__(self, arg0: object, arg1: object, arg2: object) -> None: ...
    method __getattr__ (line 261) | def __getattr__(self, arg0: str) -> object: ...
    method __init__ (line 262) | def __init__(self, com: object = None, hwnd: object = None, workbook: ...
    method __setattr__ (line 281) | def __setattr__(self, arg0: object, arg1: object) -> None: ...
    method calculate (line 282) | def calculate(self, full: bool = False, rebuild: bool = False) -> None:
    method open (line 294) | def open(self, filepath: str, update_links: bool = True, read_only: bo...
    method quit (line 308) | def quit(self, silent: bool = True) -> None:
    method range (line 313) | def range(self, address: str) -> object:
    method run (line 317) | def run(self, func: str, *args) -> object:
    method to_com (line 324) | def to_com(self, lib: str = '') -> object:
    method active_cell (line 333) | def active_cell(self) -> object:
    method active_workbook (line 341) | def active_workbook(self) -> object:
    method active_worksheet (line 349) | def active_worksheet(self) -> object:
    method enable_events (line 357) | def enable_events(self) -> bool:
    method enable_events (line 366) | def enable_events(self, arg1: bool) -> None:
    method has_dynamic_arrays (line 372) | def has_dynamic_arrays(self) -> bool:
    method selection (line 377) | def selection(self) -> object:
    method visible (line 385) | def visible(self) -> bool:
    method visible (line 393) | def visible(self, arg1: bool) -> None:
    method windows (line 398) | def windows(self) -> ExcelWindows:
    method workbook_paths (line 405) | def workbook_paths(self) -> None:
    method workbooks (line 412) | def workbooks(self) -> Workbooks:
  class Caller (line 419) | class Caller():
    method __init__ (line 426) | def __init__(self) -> None: ...
    method __str__ (line 427) | def __str__(self, arg0: str, arg1: bool) -> str: ...
    method address (line 428) | def address(self, style: str = 'a1', local: bool = False) -> str:
    method range (line 442) | def range(self) -> object:
    method sheet_name (line 449) | def sheet_name(self) -> object:
    method workbook (line 456) | def workbook(self) -> object:
  class CannotConvert (line 465) | class CannotConvert(Exception, BaseException):
  class CellError (line 472) | class CellError():
    method __eq__ (line 503) | def __eq__(self, other: object) -> bool: ...
    method __getstate__ (line 504) | def __getstate__(self) -> int: ...
    method __hash__ (line 505) | def __hash__(self) -> int: ...
    method __index__ (line 506) | def __index__(self) -> int: ...
    method __init__ (line 507) | def __init__(self, value: int) -> None: ...
    method __int__ (line 508) | def __int__(self) -> int: ...
    method __ne__ (line 509) | def __ne__(self, other: object) -> bool: ...
    method __repr__ (line 510) | def __repr__(self) -> str: ...
    method __str__ (line 511) | def __str__(self) -> str: ...
    method name (line 513) | def name(self) -> str:
    method value (line 518) | def value(self) -> int:
  class ComBusyError (line 532) | class ComBusyError(Exception, BaseException):
  class ExcelArray (line 534) | class ExcelArray():
    method __getitem__ (line 550) | def __getitem__(self, arg0: tuple) -> object:
    method slice (line 554) | def slice(self, from_row: int, from_col: int, to_row: int, to_col: int...
    method to_numpy (line 558) | def to_numpy(self, dtype: typing.Optional[int] = None, dims: typing.Op...
    method dims (line 566) | def dims(self) -> int:
    method ncols (line 573) | def ncols(self) -> int:
    method nrows (line 580) | def nrows(self) -> int:
    method shape (line 587) | def shape(self) -> tuple:
  class ExcelGUI (line 594) | class ExcelGUI():
    method __init__ (line 608) | def __init__(self, name: object = None, ribbon: object = None, funcmap...
    method _create_task_pane_frame (line 648) | def _create_task_pane_frame(self, name: str, progid: object = None, wi...
    method activate (line 656) | def activate(self, id: str) -> _Future:
    method attach_pane (line 661) | def attach_pane(self, arg0: object, arg1: object, arg2: object, arg3: ...
    method attach_pane_async (line 691) | def attach_pane_async(self, pane: object, name: object = None, window:...
    method connect (line 696) | def connect(self) -> _Future:
    method create_task_pane (line 703) | def create_task_pane(self, name: object, creator: object, window: obje...
    method disconnect (line 708) | def disconnect(self) -> _Future:
    method invalidate (line 714) | def invalidate(self, id: str = '') -> _Future:
    method connected (line 724) | def connected(self) -> bool:
    method name (line 731) | def name(self) -> str:
  class ExcelState (line 738) | class ExcelState():
    method hinstance (line 744) | def hinstance(self) -> int:
    method hwnd (line 751) | def hwnd(self) -> int:
    method main_thread_id (line 758) | def main_thread_id(self) -> int:
    method version (line 765) | def version(self) -> int:
  class ExcelWindow (line 772) | class ExcelWindow():
    method __getattr__ (line 777) | def __getattr__(self, arg0: str) -> object: ...
    method __setattr__ (line 778) | def __setattr__(self, arg0: object, arg1: object) -> None: ...
    method __str__ (line 779) | def __str__(self) -> str: ...
    method to_com (line 780) | def to_com(self, lib: str = '') -> object:
    method app (line 789) | def app(self) -> Application:
    method hwnd (line 797) | def hwnd(self) -> int:
    method name (line 804) | def name(self) -> str:
    method workbook (line 809) | def workbook(self) -> Workbook:
  class ExcelWindows (line 816) | class ExcelWindows():
    method __contains__ (line 823) | def __contains__(self, arg0: str) -> bool: ...
    method __getitem__ (line 824) | def __getitem__(self, arg0: str) -> Worksheet: ...
    method __iter__ (line 825) | def __iter__(self) -> typing.Iterator[Worksheet]: ...
    method __len__ (line 826) | def __len__(self) -> int: ...
    method get (line 827) | def get(self, name: str, default: object = None) -> object:
    method active (line 832) | def active(self) -> object:
  class IPyFromExcel (line 841) | class IPyFromExcel():
    method __call__ (line 842) | def __call__(self, arg0: object) -> None: ...
    method __str__ (line 843) | def __str__(self) -> str: ...
  class IPyToExcel (line 845) | class IPyToExcel():
    method __call__ (line 846) | def __call__(self, arg0: _object) -> _RawExcelValue: ...
    method __str__ (line 847) | def __str__(self) -> str: ...
  class ObjectCache (line 849) | class ObjectCache():
    method __call__ (line 866) | def __call__(self, obj: object, tag: str = '', key: str = '') -> object:
    method __contains__ (line 870) | def __contains__(self, arg0: str) -> bool: ...
    method __getitem__ (line 871) | def __getitem__(self, arg0: str) -> object: ...
    method add (line 872) | def add(self, obj: object, tag: str = '', key: str = '') -> object:
    method contains (line 922) | def contains(self, ref: str) -> bool:
    method get (line 926) | def get(self, ref: str, default: object = None) -> object:
    method keys (line 931) | def keys(self) -> list:
    method remove (line 935) | def remove(self, ref: str) -> bool:
  class Range (line 943) | class Range():
    method __getattr__ (line 971) | def __getattr__(self, arg0: str) -> object: ...
    method __getitem__ (line 972) | def __getitem__(self, arg0: object) -> object:
    method __iadd__ (line 979) | def __iadd__(self, arg0: object) -> object: ...
    method __imul__ (line 980) | def __imul__(self, arg0: object) -> object: ...
    method __init__ (line 981) | def __init__(self, address: str) -> None: ...
    method __isub__ (line 982) | def __isub__(self, arg0: object) -> object: ...
    method __iter__ (line 983) | def __iter__(self) -> typing.Iterator[Range]: ...
    method __itruediv__ (line 984) | def __itruediv__(self, arg0: object) -> object: ...
    method __len__ (line 985) | def __len__(self) -> int: ...
    method __setattr__ (line 986) | def __setattr__(self, arg0: object, arg1: object) -> None: ...
    method __str__ (line 987) | def __str__(self) -> str: ...
    method address (line 988) | def address(self, style: str = 'a1', local: bool = False) -> str:
    method cell (line 1001) | def cell(self, row: int, col: int) -> Range:
    method clear (line 1006) | def clear(self) -> None:
    method offset (line 1010) | def offset(self, from_row: int, from_col: int, num_rows: object = None...
    method range (line 1029) | def range(self, from_row: int = 0, from_col: int = 0, to_row: object =...
    method set (line 1062) | def set(self, arg0: object) -> None:
    method set_formula (line 1070) | def set_formula(self, formula: object, how: str = '') -> None:
    method special_cells (line 1081) | def special_cells(self, kind: object, values: object) -> object:
    method to_com (line 1104) | def to_com(self, lib: str = '') -> object:
    method trim (line 1112) | def trim(self) -> Range:
    method areas (line 1119) | def areas(self) -> object:
    method bounds (line 1128) | def bounds(self) -> tuple[int, int, int, int]:
    method column (line 1137) | def column(self) -> int:
    method formula (line 1142) | def formula(self) -> object:
    method formula (line 1158) | def formula(self, arg1: object) -> None:
    method has_formula (line 1171) | def has_formula(self) -> typing.Optional[bool]:
    method ncols (line 1180) | def ncols(self) -> int:
    method nrows (line 1187) | def nrows(self) -> int:
    method parent (line 1194) | def parent(self) -> Worksheet:
    method row (line 1201) | def row(self) -> int:
    method shape (line 1206) | def shape(self) -> tuple[int, int]:
    method value (line 1213) | def value(self) -> object:
    method value (line 1227) | def value(self, arg1: object) -> None:
  class RibbonControl (line 1238) | class RibbonControl():
    method id (line 1244) | def id(self) -> str:
    method tag (line 1251) | def tag(self) -> str:
  class RtdPublisher (line 1258) | class RtdPublisher():
    method __init__ (line 1273) | def __init__(self) -> None:
    method connect (line 1278) | def connect(self, num_subscribers: int) -> None:
    method disconnect (line 1284) | def disconnect(self, num_subscribers: int) -> bool:
    method done (line 1294) | def done(self) -> bool:
    method stop (line 1298) | def stop(self) -> None:
    method topic (line 1304) | def topic(self) -> str:
  class RtdReturn (line 1311) | class RtdReturn():
    method set_done (line 1312) | def set_done(self) -> None:
    method set_result (line 1317) | def set_result(self, arg0: object) -> None: ...
    method set_task (line 1318) | def set_task(self, task: object) -> None:
    method caller (line 1324) | def caller(self) -> Caller:
    method loop (line 1329) | def loop(self) -> object:
  class RtdServer (line 1334) | class RtdServer():
    method __init__ (line 1350) | def __init__(self) -> None: ...
    method drop (line 1351) | def drop(self, arg0: str) -> None:
    method peek (line 1356) | def peek(self, topic: str) -> object:
    method publish (line 1367) | def publish(self, topic: str, value: object) -> bool:
    method start (line 1378) | def start(self, topic: RtdPublisher) -> None:
    method start_task (line 1383) | def start_task(self, topic: str, func: object, converter: IPyToExcel =...
    method subscribe (line 1388) | def subscribe(self, topic: str) -> object:
    method progid (line 1404) | def progid(self) -> str:
  class SpecialCells (line 1409) | class SpecialCells():
    method __eq__ (line 1433) | def __eq__(self, other: object) -> bool: ...
    method __getstate__ (line 1434) | def __getstate__(self) -> int: ...
    method __hash__ (line 1435) | def __hash__(self) -> int: ...
    method __index__ (line 1436) | def __index__(self) -> int: ...
    method __init__ (line 1437) | def __init__(self, value: int) -> None: ...
    method __int__ (line 1438) | def __int__(self) -> int: ...
    method __ne__ (line 1439) | def __ne__(self, other: object) -> bool: ...
    method __repr__ (line 1440) | def __repr__(self) -> str: ...
    method __str__ (line 1441) | def __str__(self) -> str: ...
    method name (line 1443) | def name(self) -> str:
    method value (line 1448) | def value(self) -> int:
  class StatusBar (line 1464) | class StatusBar():
    method __enter__ (line 1480) | def __enter__(self) -> object: ...
    method __exit__ (line 1481) | def __exit__(self, *args) -> None: ...
    method __init__ (line 1482) | def __init__(self, timeout: int = 0) -> None:
    method msg (line 1487) | def msg(self, msg: str, timeout: int = 0) -> None:
  class TaskPaneFrame (line 1493) | class TaskPaneFrame():
    method attach (line 1502) | def attach(self, handler: object, hwnd: int, as_parent: bool = True) -...
    method com_control (line 1507) | def com_control(self, lib: str = '') -> object:
    method position (line 1515) | def position(self) -> str:
    method position (line 1523) | def position(self, arg1: str) -> None:
    method size (line 1528) | def size(self) -> tuple[int, int]:
    method size (line 1535) | def size(self, arg1: tuple) -> None:
    method title (line 1540) | def title(self) -> str:
    method visible (line 1545) | def visible(self) -> bool:
    method visible (line 1552) | def visible(self, arg1: bool) -> None:
    method window (line 1557) | def window(self) -> ExcelWindow:
  class Workbook (line 1564) | class Workbook():
    method __enter__ (line 1569) | def __enter__(self) -> object: ...
    method __exit__ (line 1570) | def __exit__(self, arg0: object, arg1: object, arg2: object) -> None: ...
    method __getattr__ (line 1571) | def __getattr__(self, arg0: str) -> object: ...
    method __getitem__ (line 1572) | def __getitem__(self, arg0: object) -> object:
    method __setattr__ (line 1577) | def __setattr__(self, arg0: object, arg1: object) -> None: ...
    method __str__ (line 1578) | def __str__(self) -> str: ...
    method add (line 1579) | def add(self, name: object = None, before: object = None, after: objec...
    method close (line 1593) | def close(self, save: bool = True) -> None:
    method range (line 1600) | def range(self, address: str) -> object:
    method save (line 1604) | def save(self, filepath: str = '') -> None:
    method to_com (line 1610) | def to_com(self, lib: str = '') -> object:
    method worksheet (line 1618) | def worksheet(self, name: str) -> Worksheet:
    method app (line 1624) | def app(self) -> Application:
    method name (line 1632) | def name(self) -> str:
    method path (line 1637) | def path(self) -> str:
    method windows (line 1644) | def windows(self) -> ExcelWindows:
    method worksheets (line 1652) | def worksheets(self) -> Worksheets:
  class Workbooks (line 1660) | class Workbooks():
    method __contains__ (line 1667) | def __contains__(self, arg0: str) -> bool: ...
    method __getitem__ (line 1668) | def __getitem__(self, arg0: str) -> Workbook: ...
    method __iter__ (line 1669) | def __iter__(self) -> typing.Iterator[Workbook]: ...
    method __len__ (line 1670) | def __len__(self) -> int: ...
    method add (line 1671) | def add(self) -> Workbook:
    method get (line 1675) | def get(self, name: str, default: object = None) -> object:
    method active (line 1680) | def active(self) -> object:
  class Worksheet (line 1689) | class Worksheet():
    method __getattr__ (line 1697) | def __getattr__(self, arg0: str) -> object: ...
    method __getitem__ (line 1698) | def __getitem__(self, arg0: object) -> object:
    method __setattr__ (line 1707) | def __setattr__(self, arg0: object, arg1: object) -> None: ...
    method __setitem__ (line 1708) | def __setitem__(self, arg0: object, arg1: object) -> None:
    method __str__ (line 1714) | def __str__(self) -> str: ...
    method activate (line 1715) | def activate(self) -> None:
    method at (line 1719) | def at(self, address: str) -> _ExcelRange:
    method calculate (line 1723) | def calculate(self) -> None:
    method cell (line 1727) | def cell(self, row: int, col: int) -> _ExcelRange:
    method range (line 1732) | def range(self, from_row: int = 0, from_col: int = 0, to_row: object =...
    method to_com (line 1761) | def to_com(self, lib: str = '') -> object:
    method app (line 1770) | def app(self) -> Application:
    method name (line 1778) | def name(self) -> str:
    method parent (line 1783) | def parent(self) -> Workbook:
    method used_range (line 1790) | def used_range(self) -> _ExcelRange:
  class Worksheets (line 1797) | class Worksheets():
    method __contains__ (line 1804) | def __contains__(self, arg0: str) -> bool: ...
    method __getitem__ (line 1805) | def __getitem__(self, arg0: str) -> Worksheet: ...
    method __iter__ (line 1806) | def __iter__(self) -> typing.Iterator[Worksheet]: ...
    method __len__ (line 1807) | def __len__(self) -> int: ...
    method add (line 1808) | def add(self, name: object = None, before: object = None, after: objec...
    method get (line 1822) | def get(self, name: str, default: object = None) -> object:
    method active (line 1827) | def active(self) -> object:
  class _AddinsDict (line 1836) | class _AddinsDict():
    method __contains__ (line 1841) | def __contains__(self, arg0: str) -> bool: ...
    method __getitem__ (line 1842) | def __getitem__(self, arg0: str) -> Addin: ...
    method __iter__ (line 1843) | def __iter__(self) -> typing.Iterator[str]: ...
    method __len__ (line 1844) | def __len__(self) -> int: ...
    method items (line 1845) | def items(self) -> typing.Iterator[tuple[str, Addin]]: ...
    method keys (line 1846) | def keys(self) -> typing.Iterator[str]: ...
    method values (line 1847) | def values(self) -> typing.Iterator[Addin]: ...
  class _AsyncReturn (line 1849) | class _AsyncReturn():
    method set_done (line 1850) | def set_done(self) -> None: ...
    method set_result (line 1851) | def set_result(self, arg0: object) -> None: ...
    method set_task (line 1852) | def set_task(self, arg0: object) -> None: ...
    method caller (line 1854) | def caller(self) -> Caller:
    method loop (line 1859) | def loop(self) -> object:
  class _CTPFuture (line 1864) | class _CTPFuture():
    method __await__ (line 1874) | def __await__(self) -> _CTPFutureIter: ...
    method done (line 1875) | def done(self) -> bool:
    method result (line 1879) | def result(self) -> object:
  class _CTPFutureIter (line 1888) | class _CTPFutureIter():
    method __iter__ (line 1889) | def __iter__(self) -> object: ...
    method __next__ (line 1890) | def __next__(self) -> None: ...
  class _CustomConverter (line 1892) | class _CustomConverter(IPyFromExcel):
    method __init__ (line 1897) | def __init__(self, callable: object, check_cache: bool = True, name: s...
  class _CustomReturn (line 1899) | class _CustomReturn(IPyToExcel):
    method __init__ (line 1900) | def __init__(self, callable: object, name: str = 'custom') -> None: ...
    method invoke (line 1901) | def invoke(self, arg0: object) -> object: ...
  class _CustomReturnConverter (line 1903) | class _CustomReturnConverter():
    method value (line 1905) | def value(self) -> IPyToExcel:
    method value (line 1910) | def value(self, arg0: IPyToExcel) -> None:
  class _DateFormatList (line 1913) | class _DateFormatList():
    method __bool__ (line 1918) | def __bool__(self) -> bool:
    method __contains__ (line 1922) | def __contains__(self, x: str) -> bool:
    method __delitem__ (line 1927) | def __delitem__(self, arg0: int) -> None:
    method __delitem__ (line 1934) | def __delitem__(self, arg0: slice) -> None: ...
    method __eq__ (line 1935) | def __eq__(self, arg0: _DateFormatList) -> bool: ...
    method __getitem__ (line 1937) | def __getitem__(self, arg0: int) -> str:
    method __getitem__ (line 1942) | def __getitem__(self, s: slice) -> _DateFormatList: ...
    method __init__ (line 1944) | def __init__(self) -> None:
    method __init__ (line 1949) | def __init__(self, arg0: _DateFormatList) -> None: ...
    method __init__ (line 1951) | def __init__(self, arg0: typing.Iterable) -> None: ...
    method __iter__ (line 1952) | def __iter__(self) -> typing.Iterator[str]: ...
    method __len__ (line 1953) | def __len__(self) -> int: ...
    method __ne__ (line 1954) | def __ne__(self, arg0: _DateFormatList) -> bool: ...
    method __setitem__ (line 1956) | def __setitem__(self, arg0: int, arg1: str) -> None:
    method __setitem__ (line 1961) | def __setitem__(self, arg0: slice, arg1: _DateFormatList) -> None: ...
    method append (line 1962) | def append(self, x: str) -> None:
    method clear (line 1966) | def clear(self) -> None:
    method count (line 1970) | def count(self, x: str) -> int:
    method extend (line 1975) | def extend(self, L: _DateFormatList) -> None:
    method extend (line 1982) | def extend(self, L: typing.Iterable) -> None: ...
    method insert (line 1983) | def insert(self, i: int, x: str) -> None:
    method pop (line 1988) | def pop(self) -> str:
    method pop (line 1995) | def pop(self, i: int) -> str: ...
    method remove (line 1996) | def remove(self, x: str) -> None:
  class _ExcelObjFuture (line 2002) | class _ExcelObjFuture():
    method __await__ (line 2012) | def __await__(self) -> _ExcelObjFutureIter: ...
    method done (line 2013) | def done(self) -> bool:
    method result (line 2017) | def result(self) -> object:
  class _ExcelObjFutureIter (line 2026) | class _ExcelObjFutureIter():
    method __iter__ (line 2027) | def __iter__(self) -> object: ...
    method __next__ (line 2028) | def __next__(self) -> None: ...
  class _ExcelRange (line 2030) | class _ExcelRange(Range):
  class _FuncArg (line 2032) | class _FuncArg():
    method __init__ (line 2033) | def __init__(self, arg0: str, arg1: str, arg2: IPyFromExcel, arg3: str...
    method __str__ (line 2034) | def __str__(self) -> str: ...
    method converter (line 2036) | def converter(self) -> IPyFromExcel:
    method converter (line 2041) | def converter(self, arg0: IPyFromExcel) -> None:
    method default (line 2044) | def default(self) -> object:
    method default (line 2049) | def default(self, arg0: object) -> None:
    method flags (line 2052) | def flags(self) -> str:
    method help (line 2057) | def help(self) -> str:
    method name (line 2062) | def name(self) -> str:
  class _FuncSpec (line 2067) | class _FuncSpec():
    method __init__ (line 2068) | def __init__(self, func: typing.Callable, args: list[_FuncArg], name: ...
    method __str__ (line 2069) | def __str__(self) -> str: ...
    method args (line 2071) | def args(self) -> list[_FuncArg]:
    method error_propagation (line 2076) | def error_propagation(self) -> bool:
    method error_propagation (line 2084) | def error_propagation(self, arg1: bool) -> None:
    method func (line 2089) | def func(self) -> typing.Callable:
    method func (line 2098) | def func(self, arg1: typing.Callable) -> None:
    method help (line 2104) | def help(self) -> str:
    method is_async (line 2109) | def is_async(self) -> bool:
    method is_rtd (line 2117) | def is_rtd(self) -> bool:
    method is_threaded (line 2125) | def is_threaded(self) -> bool:
    method name (line 2133) | def name(self) -> str:
    method name (line 2141) | def name(self, arg1: str) -> None:
    method return_converter (line 2146) | def return_converter(self) -> IPyToExcel:
    method return_converter (line 2151) | def return_converter(self, arg1: IPyToExcel) -> None:
  class _Future (line 2154) | class _Future():
    method __await__ (line 2155) | def __await__(self) -> _FutureIter: ...
    method done (line 2156) | def done(self) -> bool: ...
    method result (line 2157) | def result(self) -> object: ...
  class _FutureIter (line 2159) | class _FutureIter():
    method __iter__ (line 2160) | def __iter__(self) -> object: ...
    method __next__ (line 2161) | def __next__(self) -> None: ...
  class _LogWriter (line 2163) | class _LogWriter():
    method __call__ (line 2172) | def __call__(self, msg: object, *args, **kwargs) -> None:
    method __init__ (line 2179) | def __init__(self) -> None:
    method debug (line 2183) | def debug(self, msg: object, *args) -> None:
    method error (line 2187) | def error(self, msg: object, *args) -> None:
    method flush (line 2191) | def flush(self) -> None:
    method info (line 2196) | def info(self, msg: object, *args) -> None:
    method trace (line 2200) | def trace(self, msg: object, *args) -> None:
    method warn (line 2204) | def warn(self, msg: object, *args) -> None:
    method flush_on (line 2209) | def flush_on(self) -> str:
    method flush_on (line 2218) | def flush_on(self, arg1: object) -> None:
    method level (line 2224) | def level(self) -> str:
    method level (line 2234) | def level(self, arg1: object) -> None:
    method level_int (line 2241) | def level_int(self) -> int:
    method levels (line 2251) | def levels(self) -> list[str]:
    method path (line 2258) | def path(self) -> str:
  class _PyObjectFuture (line 2265) | class _PyObjectFuture():
    method __await__ (line 2275) | def __await__(self) -> _PyObjectFutureIter: ...
    method done (line 2276) | def done(self) -> bool:
    method result (line 2280) | def result(self) -> object:
  class _PyObjectFutureIter (line 2289) | class _PyObjectFutureIter():
    method __iter__ (line 2290) | def __iter__(self) -> object: ...
    method __next__ (line 2291) | def __next__(self) -> None: ...
  class _Read_Array_bool_1d (line 2293) | class _Read_Array_bool_1d(IPyFromExcel):
    method __init__ (line 2294) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_bool_2d (line 2296) | class _Read_Array_bool_2d(IPyFromExcel):
    method __init__ (line 2297) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_datetime_1d (line 2299) | class _Read_Array_datetime_1d(IPyFromExcel):
    method __init__ (line 2300) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_datetime_2d (line 2302) | class _Read_Array_datetime_2d(IPyFromExcel):
    method __init__ (line 2303) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_datetime_1d (line 2305) | class _Read_Array_datetime_1d():
    method __init__ (line 2300) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_datetime_2d (line 2307) | class _Read_Array_datetime_2d():
    method __init__ (line 2303) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_float_1d (line 2309) | class _Read_Array_float_1d(IPyFromExcel):
    method __init__ (line 2310) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_float_2d (line 2312) | class _Read_Array_float_2d(IPyFromExcel):
    method __init__ (line 2313) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_int_1d (line 2315) | class _Read_Array_int_1d(IPyFromExcel):
    method __init__ (line 2316) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_int_2d (line 2318) | class _Read_Array_int_2d(IPyFromExcel):
    method __init__ (line 2319) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_object_1d (line 2321) | class _Read_Array_object_1d(IPyFromExcel):
    method __init__ (line 2322) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_object_2d (line 2324) | class _Read_Array_object_2d(IPyFromExcel):
    method __init__ (line 2325) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_str_1d (line 2327) | class _Read_Array_str_1d(IPyFromExcel):
    method __init__ (line 2328) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Array_str_2d (line 2330) | class _Read_Array_str_2d(IPyFromExcel):
    method __init__ (line 2331) | def __init__(self, trim: bool = True) -> None: ...
  class _Read_Cache (line 2333) | class _Read_Cache(IPyFromExcel):
    method __init__ (line 2334) | def __init__(self) -> None: ...
  class _Read_Range (line 2336) | class _Read_Range(IPyFromExcel):
    method __init__ (line 2337) | def __init__(self) -> None: ...
  class _Read__Uncached_bool (line 2339) | class _Read__Uncached_bool(IPyFromExcel):
    method __init__ (line 2340) | def __init__(self) -> None: ...
  class _Read__Uncached_float (line 2342) | class _Read__Uncached_float(IPyFromExcel):
    method __init__ (line 2343) | def __init__(self) -> None: ...
  class _Read__Uncached_int (line 2345) | class _Read__Uncached_int(IPyFromExcel):
    method __init__ (line 2346) | def __init__(self) -> None: ...
  class _Read__Uncached_object (line 2348) | class _Read__Uncached_object(IPyFromExcel):
    method __init__ (line 2349) | def __init__(self) -> None: ...
  class _Read__Uncached_str (line 2351) | class _Read__Uncached_str(IPyFromExcel):
    method __init__ (line 2352) | def __init__(self) -> None: ...
  class _Read_bool (line 2354) | class _Read_bool(IPyFromExcel):
    method __init__ (line 2355) | def __init__(self) -> None: ...
  class _Read_date (line 2357) | class _Read_date(IPyFromExcel):
    method __init__ (line 2358) | def __init__(self) -> None: ...
  class _Read_datetime (line 2360) | class _Read_datetime(IPyFromExcel):
    method __init__ (line 2361) | def __init__(self) -> None: ...
  class _Read_dict (line 2363) | class _Read_dict(IPyFromExcel):
    method __init__ (line 2364) | def __init__(self) -> None: ...
  class _Read_float (line 2366) | class _Read_float(IPyFromExcel):
    method __init__ (line 2367) | def __init__(self) -> None: ...
  class _Read_int (line 2369) | class _Read_int(IPyFromExcel):
    method __init__ (line 2370) | def __init__(self) -> None: ...
  class _Read_list (line 2372) | class _Read_list(IPyFromExcel):
    method __init__ (line 2373) | def __init__(self) -> None: ...
  class _Read_object (line 2375) | class _Read_object(IPyFromExcel):
    method __init__ (line 2376) | def __init__(self) -> None: ...
  class _Read_str (line 2378) | class _Read_str(IPyFromExcel):
    method __init__ (line 2379) | def __init__(self) -> None: ...
  class _Read_tuple (line 2381) | class _Read_tuple(IPyFromExcel):
    method __init__ (line 2382) | def __init__(self) -> None: ...
  class _Return_Array_bool_1d (line 2384) | class _Return_Array_bool_1d(IPyToExcel):
    method __init__ (line 2385) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_bool_2d (line 2387) | class _Return_Array_bool_2d(IPyToExcel):
    method __init__ (line 2388) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_datetime_1d (line 2390) | class _Return_Array_datetime_1d(IPyToExcel):
    method __init__ (line 2391) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_datetime_2d (line 2393) | class _Return_Array_datetime_2d(IPyToExcel):
    method __init__ (line 2394) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_datetime_1d (line 2396) | class _Return_Array_datetime_1d():
    method __init__ (line 2391) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_datetime_2d (line 2398) | class _Return_Array_datetime_2d():
    method __init__ (line 2394) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_float_1d (line 2400) | class _Return_Array_float_1d(IPyToExcel):
    method __init__ (line 2401) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_float_2d (line 2403) | class _Return_Array_float_2d(IPyToExcel):
    method __init__ (line 2404) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_int_1d (line 2406) | class _Return_Array_int_1d(IPyToExcel):
    method __init__ (line 2407) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_int_2d (line 2409) | class _Return_Array_int_2d(IPyToExcel):
    method __init__ (line 2410) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_object_1d (line 2412) | class _Return_Array_object_1d(IPyToExcel):
    method __init__ (line 2413) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_object_2d (line 2415) | class _Return_Array_object_2d(IPyToExcel):
    method __init__ (line 2416) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_str_1d (line 2418) | class _Return_Array_str_1d(IPyToExcel):
    method __init__ (line 2419) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Array_str_2d (line 2421) | class _Return_Array_str_2d(IPyToExcel):
    method __init__ (line 2422) | def __init__(self, cache: bool = False) -> None: ...
  class _Return_Cache (line 2424) | class _Return_Cache(IPyToExcel):
    method __init__ (line 2425) | def __init__(self) -> None: ...
  class _Return_Single (line 2427) | class _Return_Single(IPyToExcel):
    method __init__ (line 2428) | def __init__(self) -> None: ...
  class _Return_bool (line 2430) | class _Return_bool(IPyToExcel):
    method __init__ (line 2431) | def __init__(self) -> None: ...
  class _Return_date (line 2433) | class _Return_date(IPyToExcel):
    method __init__ (line 2434) | def __init__(self) -> None: ...
  class _Return_datetime (line 2436) | class _Return_datetime(IPyToExcel):
    method __init__ (line 2437) | def __init__(self) -> None: ...
  class _Return_dict (line 2439) | class _Return_dict(IPyToExcel):
    method __init__ (line 2440) | def __init__(self) -> None: ...
  class _Return_float (line 2442) | class _Return_float(IPyToExcel):
    method __init__ (line 2443) | def __init__(self) -> None: ...
  class _Return_int (line 2445) | class _Return_int(IPyToExcel):
    method __init__ (line 2446) | def __init__(self) -> None: ...
  class _Return_tuple (line 2448) | class _Return_tuple(IPyToExcel):
    method __init__ (line 2449) | def __init__(self) -> None: ...
  class _Return_tuple (line 2451) | class _Return_tuple():
    method __init__ (line 2449) | def __init__(self) -> None: ...
  class _Return_str (line 2453) | class _Return_str(IPyToExcel):
    method __init__ (line 2454) | def __init__(self) -> None: ...
  class _Return_tuple (line 2456) | class _Return_tuple():
    method __init__ (line 2449) | def __init__(self) -> None: ...
  class _TomlTable (line 2458) | class _TomlTable():
    method __getitem__ (line 2459) | def __getitem__(self, arg0: str) -> object: ...
  class _XllRange (line 2461) | class _XllRange(Range):
  function _get_onedrive_source (line 2463) | def _get_onedrive_source(arg0: str) -> str:
  function _register_functions (line 2465) | def _register_functions(funcs: list[_FuncSpec], module: object = None, a...
  function _table_converter (line 2467) | def _table_converter(n: int, m: int, columns: object = None, rows: objec...
  function active_cell (line 2488) | def active_cell() -> object:
  function active_workbook (line 2493) | def active_workbook() -> object:
  function active_worksheet (line 2498) | def active_worksheet() -> object:
  function all_workbooks (line 2503) | def all_workbooks() -> Workbooks:
  function app (line 2508) | def app() -> Application:
  function call (line 2513) | def call(func: object, *args) -> object:
  function call_async (line 2527) | def call_async(func: object, *args) -> _ExcelObjFuture:
  function check_abort (line 2538) | def check_abort() -> bool:
  function core_addin (line 2545) | def core_addin() -> Addin:
  function deregister_functions (line 2547) | def deregister_functions(funcs: object, module: object = None) -> None:
  function excel_callback (line 2552) | def excel_callback(func: object, wait: int = 0, retry: int = 500, api: s...
  function excel_state (line 2577) | def excel_state() -> ExcelState:
  function from_excel_date (line 2583) | def from_excel_date(arg0: object) -> object:
  function get_async_loop (line 2587) | def get_async_loop() -> object:
  function in_wizard (line 2593) | def in_wizard() -> bool:
  function insert_cell_image (line 2599) | def insert_cell_image(writer: object, size: object = None, pos: object =...
  function run (line 2623) | def run(func: str, *args) -> object:
  function run_async (line 2633) | def run_async(func: str, *args) -> _ExcelObjFuture:
  function selection (line 2644) | def selection() -> object:
  function to_datetime (line 2649) | def to_datetime(arg0: object) -> object:

FILE: libs/xlOil_Python/Package/xloil/stubs/xloil_core/event/__init__.py
  class Event (line 121) | class Event():
    method __iadd__ (line 122) | def __iadd__(self, arg0: object) -> Event: ...
    method __isub__ (line 123) | def __isub__(self, arg0: object) -> Event: ...
    method add (line 124) | def add(self, handler: object) -> Event:
    method clear (line 129) | def clear(self) -> None:
    method remove (line 133) | def remove(self, handler: object) -> Event:
    method handlers (line 139) | def handlers(self) -> tuple:
  class _bool_ref (line 146) | class _bool_ref():
    method value (line 148) | def value(self) -> bool:
    method value (line 153) | def value(self, arg1: bool) -> None:
  function allow (line 156) | def allow(excel: bool = True) -> None:
  function file_change (line 163) | def file_change(path: str, action: str = 'modify', subdirs: bool = True)...
  function pause (line 195) | def pause(excel: bool = True) -> None:

FILE: libs/xlOil_Python/Package/xloil/type_converters.py
  function get_converter (line 34) | def get_converter(type_name, read=True, cache=True):
  function _make_typeconverter (line 45) | def _make_typeconverter(base_type, reader=None, writer=None, allow_range...
  function unpack_arg_converter (line 77) | def unpack_arg_converter(obj):
  function unpack_return_converter (line 80) | def unpack_return_converter(obj):
  function _make_metaconverter (line 83) | def _make_metaconverter(base_type, impl, is_returner:bool, allow_range=F...
  function _make_tuple (line 152) | def _make_tuple(obj):
  class _ArgConverters (line 159) | class _ArgConverters:
    method add (line 163) | def add(self, converter, arg_type):
    method remove (line 171) | def remove(self, arg_type):
    method get_converter (line 174) | def get_converter(self, arg_type):
  function converter (line 183) | def converter(
  class _ReturnConverters (line 288) | class _ReturnConverters:
    method add (line 293) | def add(self, converter, types):
    method remove (line 320) | def remove(self, return_type):
    method create_returner (line 326) | def create_returner(self, return_type):
    method __call__ (line 334) | def __call__(self, obj):
  function returner (line 351) | def returner(target=None, register=False):
  class FastArray (line 389) | class FastArray(np.ndarray):
  class Array (line 405) | class Array(np.ndarray):
    method __new__ (line 476) | def __new__(cls, dtype=object, dims=2, trim=True, fast=False, cache_re...

FILE: libs/xlOil_Python/Package/xloil/xloil_ribbon.py
  function test_name (line 14) | def test_name(x):
  function test_name2 (line 18) | async def test_name2(x):
  class Settings (line 21) | class Settings:
    method __init__ (line 25) | def __init__(self, path):
    method __getitem__ (line 29) | def __getitem__(self, *args):
    method set_env_var (line 32) | def set_env_var(self, name, value):
    method get_env_var (line 37) | def get_env_var(self, name):
    method set_addin_env_var (line 42) | def set_addin_env_var(self, name, value):
    method get_addin_env_var (line 47) | def get_addin_env_var(self, name):
    method save (line 51) | def save(self):
    method python (line 56) | def python(self):
    method addin (line 60) | def addin(self):
    method path (line 64) | def path(self):
    method _find_table (line 68) | def _find_table(array_of_tables, key):
  function set_log_level (line 90) | async def set_log_level(ctrl, id, index):
  function get_log_level_count (line 96) | def get_log_level_count(ctrl):
  function get_log_level (line 99) | def get_log_level(ctrl, i):
  function get_log_level_selected (line 102) | def get_log_level_selected(ctrl):
  function set_date_formats (line 109) | async def set_date_formats(ctrl, value):
  function get_date_formats (line 118) | def get_date_formats(ctrl):
  function set_user_search_path (line 126) | async def set_user_search_path(ctrl, value):
  function get_user_search_path (line 136) | def get_user_search_path(ctrl):
  function set_python_home (line 146) | async def set_python_home(ctrl, value):
  function get_python_home (line 152) | def get_python_home(ctrl):
  function set_python_path (line 161) | def set_python_path(ctrl, value):
  function get_python_path (line 167) | def get_python_path(ctrl):
  function _find_python_enviroments_from_key (line 177) | def _find_python_enviroments_from_key(pythons_key):
  function _find_conda_environments (line 207) | def _find_conda_environments():
  function _find_env_by_exe (line 235) | def _find_env_by_exe(environments, filename):
  function _find_python_enviroments (line 244) | def _find_python_enviroments():
  function set_python_environment (line 275) | async def set_python_environment(ctrl, id, index):
  function get_python_environment_count (line 306) | def get_python_environment_count(ctrl):
  function get_python_environment (line 310) | def get_python_environment(ctrl, i):
  function get_python_environment_selected (line 314) | def get_python_environment_selected(ctrl):
  function set_load_modules (line 323) | async def set_load_modules(ctrl, value):
  function get_load_modules (line 338) | def get_load_modules(ctrl):
  function get_debugger_count (line 348) | def get_debugger_count(ctrl):
  function get_debugger (line 352) | def get_debugger(ctrl, i):
  function get_debugger_selected (line 356) | def get_debugger_selected(ctrl):
  function set_debugger (line 362) | async def set_debugger(ctrl, id, index):
  function _find_free_port (line 373) | def _find_free_port():
  function _is_port_in_use (line 381) | def _is_port_in_use(port: int) -> bool:
  function get_debugpy_port (line 391) | def get_debugpy_port(ctrl):
  function set_debugpy_port (line 399) | async def set_debugpy_port(ctrl, value):
  function press_open_log (line 409) | async def press_open_log(ctrl):
  function press_open_console (line 418) | async def press_open_console(ctrl):
  function press_open_qtconsole (line 439) | async def press_open_qtconsole(ctrl):
  function restart_notify (line 458) | def restart_notify():
  function get_restart_label_visible (line 463) | def get_restart_label_visible(ctrl):
  function set_error_propagation (line 469) | def set_error_propagation(ctrl, value):
  function get_error_propagation (line 477) | def get_error_propagation(ctrl):
  function _fix_name_errors (line 480) | def _fix_name_errors(ctrl):
  function _ribbon_func_map (line 489) | def _ribbon_func_map(func: str):

FILE: libs/xlOil_Python/PyAddin.cpp
  type xloil (line 23) | namespace xloil
    type Python (line 25) | namespace Python
      function AddinContext (line 67) | AddinContext& PyAddin::context()
      function AddinContext (line 74) | const AddinContext& PyAddin::context() const
      function PyAddin (line 132) | PyAddin& findAddin(const wchar_t* xllPath)
      function getEventLoop (line 145) | std::shared_ptr<EventLoop> getEventLoop()
      function findAllAddinFuncs (line 156) | auto findAllAddinFuncs(PyAddin& addin)
      class PyWrapMap (line 177) | class PyWrapMap
        method PyWrapMap (line 183) | PyWrapMap(const TMap& mapRef) : _map(mapRef) {}
        method keys (line 185) | auto keys() const
        method values (line 189) | auto values() const
        method items (line 193) | auto items() const
        method getItem (line 198) | auto getItem(const typename TMap::key_type& key) const
        method len (line 205) | size_t len() const { return _map.size(); }
        method contains (line 207) | bool contains(const typename TMap::key_type& key) const
        method bind (line 213) | static void bind(py::module& mod, const char* name)
      function tomlNodeToPyObject (line 230) | py::object tomlNodeToPyObject(const toml::node& node)
      function tomlTableGetItem (line 275) | auto tomlTableGetItem(toml::table& table, const char* name)

FILE: libs/xlOil_Python/PyAddin.h
  function namespace (line 7) | namespace xloil
  function namespace (line 13) | namespace xloil

FILE: libs/xlOil_Python/PyAddress.cpp
  type xloil (line 11) | namespace xloil
    type Python (line 13) | namespace Python
      function AddressStyle (line 15) | AddressStyle parseAddressStyle(const std::string_view& style)
      class ParsedAddress (line 39) | class ParsedAddress
        method ParsedAddress (line 44) | ParsedAddress(
        method ParsedAddress (line 52) | ParsedAddress(const msxll::XLREF12& ref)
        method ParsedAddress (line 58) | ParsedAddress(const py::object& address, const py::object& sheetName)
        method fromRow (line 88) | auto fromRow() const { return _ref.rwFirst; }
        method fromCol (line 89) | auto fromCol() const { return _ref.colFirst; }
        method toRow (line 90) | auto toRow()   const { return _ref.rwLast; }
        method toCol (line 91) | auto toCol()   const { return _ref.colLast; }
        method sheet (line 92) | auto sheet()   const { return _sheetName; }
        method tuple (line 94) | auto tuple() const
        method string (line 104) | auto string(AddressStyle style) const
        method address (line 112) | auto address(std::string& style, const bool local) const
      class ParsedAddressIter (line 129) | class ParsedAddressIter
        method ParsedAddressIter (line 136) | ParsedAddressIter(
        method ParsedAddressIter (line 145) | ParsedAddressIter(const ParsedAddress& r)
        method ParsedAddressIter (line 154) | ParsedAddressIter& operator++()
        method ParsedAddress (line 169) | const ParsedAddress& operator*() const

FILE: libs/xlOil_Python/PyAddress.h
  function namespace (line 4) | namespace xloil

FILE: libs/xlOil_Python/PyAppCallRun.cpp
  type xloil (line 18) | namespace xloil
    type Python (line 20) | namespace Python
      type ArgFromPyObj (line 27) | struct ArgFromPyObj
      function argConvertHelper (line 47) | auto argConvertHelper(const py::args& args)
      function callXllAsync (line 64) | auto callXllAsync(const py::object& func, const py::args& args)
      function callXll (line 114) | auto callXll(const py::object& func, const py::args& args)
      function applicationRun (line 119) | py::object applicationRun(Application& app, const wstring& funcName,...
      function ExcelObjFuture (line 135) | ExcelObjFuture applicationRunAsync(Application& app, const wstring& ...
      function appRunAsync (line 153) | auto appRunAsync(const wstring& func, const py::args& args)
      function appRun (line 158) | auto appRun(const wstring& func, const py::args& args)

FILE: libs/xlOil_Python/PyAppCallRun.h
  function namespace (line 6) | namespace xloil { class Application; }
  function namespace (line 8) | namespace xloil

FILE: libs/xlOil_Python/PyAppObjects.cpp
  type xloil (line 20) | namespace xloil
    type Python (line 22) | namespace Python
      function isRangeType (line 26) | bool isRangeType(const PyObject* obj)
      function SpecialCells (line 36) | SpecialCells specialCellsFromString(const std::string& value)
      function range_Construct (line 44) | auto range_Construct(const wchar_t* address)
      function createPyRange (line 57) | py::object createPyRange(F&& f)
      function range_subRange (line 67) | inline auto range_subRange(const T& r,
      function range_offset (line 86) | inline auto range_offset(const Range& r,
      function convertExcelObj (line 96) | inline auto convertExcelObj(ExcelObj&& val)
      function range_GetValue (line 101) | auto range_GetValue(const Range& r)
      function range_SetValue (line 112) | void range_SetValue(Range& r, py::object pyVal)
      function range_Clear (line 132) | void range_Clear(Range& r)
      function range_Address (line 138) | auto range_Address(Range& r, std::string& style, const bool local)
      function range_GetFormula (line 147) | auto range_GetFormula(Range& r)
      function range_SetFormula (line 159) | void range_SetFormula(Range& r, const py::object& pyVal)
      function range_SetFormulaExtra (line 166) | void range_SetFormulaExtra(Range& r, const py::object& pyVal, std::s...
      function range_getItem (line 183) | py::object range_getItem(const Range& range, const py::object& loc)
      function specialCellsValueHelper (line 194) | int specialCellsValueHelper(const py::handle& values, int existing = 0)
      function range_SpecialCells (line 239) | py::object range_SpecialCells(
      function range_Areas (line 261) | py::object range_Areas(Range& r)
      function range_Iter (line 280) | pybind11::typing::Iterator<xloil::Range> range_Iter(Range& r)
      function range_InplaceArithmetic (line 307) | auto range_InplaceArithmetic(
      function Range (line 324) | inline Range* worksheet_subRange(const ExcelWorksheet& ws,
      function Worksheet_sliceHelper (line 333) | auto Worksheet_sliceHelper(
      function worksheet_GetItem (line 355) | py::object worksheet_GetItem(
      function worksheet_SetItem (line 361) | void worksheet_SetItem(
      function application_range (line 386) | py::object application_range(const Application& app, const std::wstr...
      function workbook_range (line 391) | py::object workbook_range(const ExcelWorkbook& wb, const std::wstrin...
      function workbook_GetItem (line 396) | py::object workbook_GetItem(const ExcelWorkbook& wb, const py::objec...
      function Workbook_SetItem (line 440) | py::object Workbook_SetItem(
      function Context_Enter (line 450) | py::object Context_Enter(const py::object& x)
      function Workbook_Exit (line 455) | void Workbook_Exit(
      function Application_Exit (line 465) | void Application_Exit(
      function Application (line 475) | Application application_Construct(
      function application_Open (line 502) | auto application_Open(
      function castInvalidToNone (line 515) | py::object castInvalidToNone(T obj)
      function application_ActiveWorksheet (line 520) | auto application_ActiveWorksheet(Application& app)
      function application_ActiveWorkbook (line 530) | auto application_ActiveWorkbook(Application& app)
      function application_ActiveCell (line 540) | auto application_ActiveCell(Application& app)
      function application_Selection (line 550) | auto application_Selection(Application& app)
      function application_Run (line 560) | auto application_Run(Application& app, const std::wstring& func, con...
      function CallerInfo_Ctor (line 565) | auto CallerInfo_Ctor()
      function CallerInfo_Address (line 572) | auto CallerInfo_Address(const CallerInfo& self, std::string& style, ...
      type BindCollection (line 584) | struct BindCollection
        method BindCollection (line 588) | BindCollection(const V& x)
        method getitem (line 594) | auto getitem(const wstring& name)
        method getdefaulted (line 607) | py::object getdefaulted(const wchar_t* name, const py::object& def...
        method iter (line 615) | auto iter()
        method count (line 625) | size_t count() const { return _collection.count(); }
        method contains (line 627) | bool contains(const wchar_t* name) const
        method _bind (line 634) | static auto _bind(K&& klass)
        method startBinding (line 652) | static auto startBinding(
      type BindCollectionWithActive (line 663) | struct BindCollectionWithActive : public BindCollection<T>
        method active (line 667) | py::object active()
        method startBinding (line 679) | static auto startBinding(
      function ExcelWorksheet (line 695) | ExcelWorksheet addWorksheetToWorkbook(
      function addWorksheetToCollection (line 709) | auto addWorksheetToCollection(
      function toCom (line 721) | auto toCom(T& p, const char* binder)
      function toCom (line 727) | auto toCom(Range& range, const char* binder)
      function getComAttr (line 734) | auto getComAttr(T& p, const char* attrName)
      function setComAttr (line 740) | void setComAttr(py::object& self, const py::object& attrName, const ...

FILE: libs/xlOil_Python/PyCOM.cpp
  type xloil (line 24) | namespace xloil
    type Python (line 26) | namespace Python
      function writeCellImage (line 57) | auto writeCellImage(
      function comObjectWithComtypes (line 185) | py::object comObjectWithComtypes(
      function find_PyCom_PyObjectFromIUnknown (line 205) | auto find_PyCom_PyObjectFromIUnknown()
      function comObjectWithPyCom (line 225) | py::object comObjectWithPyCom(
      function marshalCom (line 238) | py::object marshalCom(
      function comToPy (line 266) | py::object comToPy(Excel::_Application& p, const char* binder)
      function comToPy (line 270) | pybind11::object comToPy(Excel::Window& p, const char* binder)
      function comToPy (line 274) | pybind11::object comToPy(Excel::_Workbook& p, const char* binder)
      function comToPy (line 278) | pybind11::object comToPy(Excel::_Worksheet& p, const char* binder)
      function comToPy (line 282) | pybind11::object comToPy(Excel::Range& p, const char* binder)
      function comToPy (line 286) | pybind11::object comToPy(IDispatch& p, const char* binder)

FILE: libs/xlOil_Python/PyCOM.h
  type IDispatch (line 4) | struct IDispatch
  function namespace (line 6) | namespace Excel
  function namespace (line 11) | namespace xloil

FILE: libs/xlOil_Python/PyCache.cpp
  type xloil (line 11) | namespace xloil
    type CacheUniquifier<py::object> (line 14) | struct CacheUniquifier<py::object>
    type Python (line 20) | namespace Python {
      class PyCache (line 29) | class PyCache
        method PyCache (line 33) | PyCache()
        method PyCache (line 46) | PyCache(const PyCache& that) = delete;
        method PyCache (line 58) | static PyCache* construct()
        method PyCache (line 64) | static PyCache& instance()
        method add (line 70) | py::object add(py::object& obj, const wstring& tag, const wstring&...
        method getitem (line 77) | py::object getitem(const std::wstring_view& str)
        method get (line 84) | py::object get(const std::wstring_view& str, const py::object& def...
        method remove (line 93) | bool remove(const std::wstring& cacheRef)
        method contains (line 97) | bool contains(const std::wstring_view& str)
        method keys (line 102) | py::list keys() const
      function ExcelObj (line 118) | ExcelObj pyCacheAdd(const py::object& obj, const wchar_t* caller)
      function pyCacheGet (line 129) | bool pyCacheGet(const std::wstring_view& str, py::object& obj)

FILE: libs/xlOil_Python/PyCache.h
  function namespace (line 5) | namespace pybind11 { class object; }
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_Python/PyCore.cpp
  type xloil (line 21) | namespace xloil
    type Python (line 23) | namespace Python
      function isErrorType (line 29) | bool isErrorType(const PyObject* obj)
      function isExcelObjType (line 34) | bool isExcelObjType(const PyObject* obj)
      class BinderRegistry (line 45) | class BinderRegistry
        method BinderRegistry (line 48) | static BinderRegistry& get() {
        method add (line 53) | auto add(BinderFunc f, size_t priority)
        method bindAll (line 58) | void bindAll(py::module& mod)
        method BinderRegistry (line 64) | BinderRegistry() {}
      function PyObject (line 69) | PyObject* buildInjectedModule()
      function XLO_NAMED_MODULE (line 100) | XLO_NAMED_MODULE(XLO_PROJECT_NAME, mod, theInjectedModuleName)
      function addBinder (line 114) | int addBinder(std::function<void(pybind11::module&)> binder, size_t ...
      type CannotConvert (line 122) | struct CannotConvert {}
      function cellErrorSymbol (line 128) | auto cellErrorSymbol(CellError e)
      function initialiseCore (line 140) | void initialiseCore(pybind11::module& mod)

FILE: libs/xlOil_Python/PyCore.h
  function namespace (line 8) | namespace xloil

FILE: libs/xlOil_Python/PyEvents.cpp
  type std (line 21) | namespace std
  type xloil (line 29) | namespace xloil
    type Python (line 31) | namespace Python
      class IPyEvent (line 36) | class IPyEvent
        method handlers (line 96) | py::tuple handlers() const
        method IPyEvent (line 105) | IPyEvent& add(const py::object& obj)
        method IPyEvent (line 130) | IPyEvent& remove(const py::object& obj)
        method clear (line 143) | void clear()
        method unbind (line 150) | virtual void unbind() {}
        method IPyEvent (line 153) | IPyEvent()
      type ArithmeticRef (line 53) | struct ArithmeticRef
      type ReplaceArithmeticRef (line 63) | struct ReplaceArithmeticRef
      type ReplaceArithmeticRef<const T&, false> (line 68) | struct ReplaceArithmeticRef<const T&, false>
        method T (line 70) | const T& operator()(const T& x) const { return x; }
      type ReplaceArithmeticRef<T&, true> (line 73) | struct ReplaceArithmeticRef<T&, true>
      class IPyEvent (line 81) | class IPyEvent
        method handlers (line 96) | py::tuple handlers() const
        method IPyEvent (line 105) | IPyEvent& add(const py::object& obj)
        method IPyEvent (line 130) | IPyEvent& remove(const py::object& obj)
        method clear (line 143) | void clear()
        method unbind (line 150) | virtual void unbind() {}
        method IPyEvent (line 153) | IPyEvent()
      class PyEvent (line 159) | class PyEvent {}
      class PyDirectoryWatch (line 220) | class PyDirectoryWatch: public IPyEvent
        method PyDirectoryWatch (line 223) | PyDirectoryWatch(
        method unbind (line 245) | void unbind() override
        method wchar_t (line 250) | const wchar_t* name() const override
        method bind (line 255) | void bind() override
        method fire (line 264) | void fire(const wchar_t* directory, const wchar_t* filename, Event...
      function setAllowPyEvents (line 307) | void setAllowPyEvents(bool value)
      function makeEvent (line 315) | auto makeEvent(TEvent& event)
      function makeEventNoUserExcept (line 325) | auto makeEventNoUserExcept(TEvent& event)
      function bindEvent (line 330) | void bindEvent(
      function bindArithmeticRef (line 347) | void bindArithmeticRef(py::module& mod)
      function setEnableEvents (line 357) | void setEnableEvents(bool value, bool excelEvents)
      function getDirectoryChangeEvent (line 368) | auto getDirectoryChangeEvent(const wstring& path, wstring& action, b...
      function raiseUserException (line 584) | void raiseUserException(const pybind11::error_already_set& e)
  class PyEvent<TEvent, TAllowUserException, std::function<R(Args...)>> (line 163) | class PyEvent<TEvent, TAllowUserException, std::function<R(Args...)>> : ...
    method PyEvent (line 166) | PyEvent(TEvent& event)
    method unbind (line 171) | void unbind() override
    method wchar_t (line 176) | const wchar_t* name() const override
    method bind (line 181) | void bind() override
    method fire (line 186) | void fire(Args... args) const

FILE: libs/xlOil_Python/PyEvents.h
  function namespace (line 3) | namespace pybind11 {
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_Python/PyFunctionRegister.cpp
  type xloil (line 38) | namespace xloil
    type Python (line 40) | namespace Python
      function readFuncFeatures (line 45) | unsigned readFuncFeatures(
      type CommandReturn (line 132) | struct CommandReturn
        method CommandReturn (line 136) | CommandReturn(const IPyToExcel*) {}
      type FPArrayReturn (line 156) | struct FPArrayReturn
        method FPArrayReturn (line 160) | FPArrayReturn(const IPyToExcel*) {}
        method FPArray (line 162) | FPArray* operator()(PyObject* retVal) const
        method FPArray (line 167) | FPArray* operator()(const char* err, const PyFuncInfo* info) const
        method FPArray (line 173) | FPArray* operator()(CellError, const PyFuncInfo* info) const
      type ExcelObjReturn (line 180) | struct ExcelObjReturn
        method ExcelObjReturn (line 186) | ExcelObjReturn(const IPyToExcel* returnConverter)
        method ExcelObj (line 190) | ExcelObj* operator()(PyObject* retVal) const
        method ExcelObj (line 204) | ExcelObj* operator()(T&& x, const PyFuncInfo* = nullptr) const
      type ExcelObjThreadSafeReturn (line 212) | struct ExcelObjThreadSafeReturn
        method ExcelObjThreadSafeReturn (line 218) | ExcelObjThreadSafeReturn(const IPyToExcel* returnConverter)
        method ExcelObj (line 222) | ExcelObj* operator()(PyObject* retVal) const
        method ExcelObj (line 229) | ExcelObj* operator()(T&& x, const PyFuncInfo* = nullptr) const
      function pythonCallback (line 238) | typename TReturn::return_type pythonCallback(
      function getModulePath (line 581) | auto getModulePath(const py::object& module)
      function registerFunctions (line 589) | void registerFunctions(
      function deregisterFunctions (line 612) | void deregisterFunctions(
      function string (line 649) | string pyFuncInfoToString(const PyFuncInfo& info)

FILE: libs/xlOil_Python/PyFunctionRegister.h
  function namespace (line 11) | namespace xloil {
  function namespace (line 18) | namespace xloil
  type Propagation (line 195) | enum Propagation
  function class (line 203) | class RegisteredModule : public LinkedSource

FILE: libs/xlOil_Python/PyFuture.h
  function namespace (line 6) | namespace xloil
  type Iter (line 50) | struct Iter
  function done (line 102) | bool done()
  function bind (line 109) | static void bind(pybind11::module& mod, const std::string& name)
  type Iter (line 148) | struct Iter
  function done (line 199) | bool done()
  function bind (line 206) | static void bind(pybind11::module& mod)

FILE: libs/xlOil_Python/PyHelpers.cpp
  function to_wstring (line 7) | std::wstring to_wstring(const PyObject* p)
  type xloil (line 31) | namespace xloil {
    type Python (line 32) | namespace Python
      function getItemIndexReader1d (line 34) | bool getItemIndexReader1d(
      function getItemIndexReader2d (line 61) | bool getItemIndexReader2d(
      function PyObject (line 75) | PyObject* fastCall(

FILE: libs/xlOil_Python/PyHelpers.h
  function namespace (line 30) | namespace pybind11
  function valuePatcher (line 107) | auto valuePatcher = [patchValue](TEnum value) {
  function namespace (line 133) | namespace xloil
  function push_back (line 339) | void push_back(PyObject* p)
  function push_back (line 345) | void push_back(const pybind11::object& obj)
  function clear (line 366) | void clear()

FILE: libs/xlOil_Python/PyImage.cpp
  type xloil (line 10) | namespace xloil
    type Python (line 12) | namespace Python
      type HandleDC (line 17) | struct HandleDC
        method HandleDC (line 19) | HandleDC(HDC h_) : h(h_) {}
      type HandleBitmap (line 23) | struct HandleBitmap
        method HandleBitmap (line 25) | HandleBitmap(HBITMAP h_) : h(h_) {}
        method release (line 27) | void release() { h = nullptr; }
      function IPictureDisp (line 31) | IPictureDisp* pictureFromPilImage(const py::object& image)

FILE: libs/xlOil_Python/PyImage.h
  type IPictureDisp (line 4) | struct IPictureDisp
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_Python/PyLogWriter.cpp
  function PyFrame_GetLasti (line 18) | inline auto PyFrame_GetLasti(PyFrameObject* frame) { return frame->f_las...
  function PyFrame_GetCode (line 21) | inline auto PyFrame_GetCode(PyFrameObject* frame) { return frame->f_code; }
  type xloil (line 24) | namespace xloil
    type Python (line 26) | namespace Python
      class LogWriter (line 34) | class LogWriter
        method levelFromStr (line 43) | spdlog::level::level_enum levelFromStr(const std::string& target)
        method toSpdLogLevel (line 56) | spdlog::level::level_enum toSpdLogLevel(const py::object& level)
        method writeToLog (line 66) | void writeToLog(const py::object& msg, const py::args& args, const...
        method writeToLogImpl (line 74) | void writeToLogImpl(const py::object& msg, const py::args& args, s...
        method flush (line 100) | void flush()
        method trace (line 106) | void trace(const py::object& msg, const py::args& args) { writeToL...
        method debug (line 107) | void debug(const py::object& msg, const py::args& args) { writeToL...
        method info (line 108) | void info(const py::object& msg,  const py::args& args) { writeToL...
        method warn (line 109) | void warn(const py::object& msg,  const py::args& args) { writeToL...
        method error (line 110) | void error(const py::object& msg, const py::args& args) { writeToL...
        method getLogLevel (line 112) | auto getLogLevel()
        method getLogLevelInt (line 119) | unsigned getLogLevelInt()
        method setLogLevel (line 125) | void setLogLevel(const py::object& level)
        method getFlushLevel (line 130) | auto getFlushLevel()
        method setFlushLevel (line 137) | void setFlushLevel(const py::object& level)
        method levels (line 142) | auto levels()
        method logFilePath (line 148) | auto logFilePath()

FILE: libs/xlOil_Python/PyObjectGC.cpp
  type xloil (line 9) | namespace xloil
    type Python (line 11) | namespace Python
      class GarbageCollector (line 14) | class GarbageCollector
        method GarbageCollector (line 17) | static GarbageCollector& instance()
        method add (line 23) | void add(PyObject* obj)
        method GarbageCollector (line 41) | GarbageCollector()
      class objectGC (line 75) | class objectGC : py::handle
        method objectGC (line 79) | objectGC(py::handle h, bool is_borrowed)
        method objectGC (line 85) | objectGC(const objectGC& o) : py::handle(o) { inc_ref(); }
        method objectGC (line 87) | objectGC(objectGC&& other) noexcept { m_ptr = other.m_ptr; other.m...

FILE: libs/xlOil_Python/PyRibbon.cpp
  type xloil (line 28) | namespace xloil
    type Python (line 30) | namespace Python
      type PyRibbonControl (line 34) | struct PyRibbonControl
        method PyRibbonControl (line 36) | PyRibbonControl(const RibbonControl& ctrl)
      function TaskPane_setPosition (line 67) | void TaskPane_setPosition(ICustomTaskPane& self, std::string position)
      function makeRibbonNameMapper (line 88) | auto makeRibbonNameMapper(const py::object& funcNameMap)
      class ComAddin (line 155) | class ComAddin
        method ComAddin (line 158) | ComAddin(
        method VoidFuture (line 199) | VoidFuture connect()
        method VoidFuture (line 215) | VoidFuture disconnect()
        method VoidFuture (line 230) | VoidFuture invalidate(const wstring& id)
        method VoidFuture (line 235) | VoidFuture activate(const wstring& id)
        method CTPFuture (line 240) | CTPFuture createTaskPaneFrame(
        method IComAddin (line 257) | IComAddin* addin()
        method name (line 263) | auto name() const { return _name; }
        method connected (line 265) | bool connected() const { return _connected; }
      function attachTaskPaneAsync (line 276) | auto attachTaskPaneAsync(
      function attachTaskPane (line 288) | auto attachTaskPane(
      function createTaskPane (line 300) | auto createTaskPane(
      class PyTaskPaneHandler (line 322) | class PyTaskPaneHandler : public ICustomTaskPaneEvents
        method PyTaskPaneHandler (line 325) | PyTaskPaneHandler(const py::object& eventHandler)
        method onVisible (line 337) | void onVisible(bool c) override
        method onDocked (line 345) | void onDocked() override
        method onDestroy (line 353) | void onDestroy() override
      function VoidFuture (line 365) | VoidFuture TaskPaneFrame_attach(
      function setTaskPaneSize (line 382) | void setTaskPaneSize(ICustomTaskPane* pane, const py::tuple& pair)

FILE: libs/xlOil_Python/PyRtd.cpp
  class py_shared_ptr (line 21) | class py_shared_ptr {
    method py_shared_ptr (line 28) | py_shared_ptr() {}
    method py_shared_ptr (line 30) | py_shared_ptr(T *ptr)
    method py_shared_ptr (line 42) | py_shared_ptr(std::shared_ptr<T> r) : _impl(r) {}
    method T (line 46) | T* get() const { return _impl.get(); }
  function CallerInfo (line 142) | const CallerInfo& RtdReturn::caller() const noexcept
  type PyRtdTaskLauncher (line 150) | struct PyRtdTaskLauncher : public IRtdTask
    method PyRtdTaskLauncher (line 157) | PyRtdTaskLauncher(const py::object& func, const shared_ptr<IPyToExcel>...
    method start (line 165) | void start(IRtdPublish& publisher) override
    method done (line 178) | bool done() noexcept override
    method wait (line 182) | void wait() noexcept override
    method cancel (line 187) | void cancel() override
  class PyRtdServer (line 197) | class PyRtdServer
    method IRtdServer (line 205) | IRtdServer& impl()
    type InitDebugPy (line 221) | struct InitDebugPy : public IRtdPublisher
      method InitDebugPy (line 223) | InitDebugPy(IRtdServer* server) : _server(server) {}
      method connect (line 226) | virtual void connect(size_t /*numSubscribers*/)
      method disconnect (line 235) | virtual bool disconnect(size_t) { return true; }
      method stop (line 236) | virtual void stop() {}
      method done (line 237) | virtual bool done() const { return true; }
      method wchar_t (line 238) | virtual const wchar_t* topic() const noexcept { return topicName; }
    method PyRtdServer (line 244) | PyRtdServer()
    method start (line 275) | void start(const py_shared_ptr<IRtdPublisher>& topic)
    method publish (line 280) | bool publish(
    method subscribe (line 292) | py::object subscribe(const wchar_t* topic)
    method peek (line 298) | py::object peek(const wchar_t* topic)
    method drop (line 318) | void drop(const wchar_t* topic)
    method startTask (line 328) | void startTask(
    method progId (line 340) | auto progId() { return impl().progId(); }
  function connect (line 348) | virtual void connect(size_t numSubscribers) override
  function disconnect (line 352) | virtual bool disconnect(size_t numSubscribers) override
  function stop (line 356) | virtual void stop() override

FILE: libs/xlOil_Python/PyRtd.h
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_Python/PyRunLater.cpp
  type xloil (line 15) | namespace xloil
    type Python (line 17) | namespace Python
      function runLater (line 24) | auto runLater(

FILE: libs/xlOil_Python/PySource.cpp
  function oneDriveUrlToLocal (line 34) | bool oneDriveUrlToLocal(const wstring_view& url, wstring& path)
  function wstring (line 72) | wstring loadOneDriveUrl(const wstring& url)
  type xloil (line 111) | namespace xloil
    type Python (line 113) | namespace Python
      function unloadModule (line 115) | bool unloadModule(const py::handle& module)
      type WorkbookOpenHandler (line 149) | struct WorkbookOpenHandler
        method WorkbookOpenHandler (line 153) | WorkbookOpenHandler(const weak_ptr<PyAddin>& loadContext)
      function createWorkbookOpenHandler (line 208) | std::shared_ptr<const void>

FILE: libs/xlOil_Python/PySource.h
  function namespace (line 3) | namespace pybind11 { class handle; }
  function namespace (line 4) | namespace xloil {
  function namespace (line 12) | namespace xloil

FILE: libs/xlOil_Python/PyStatusBar.cpp
  type xloil (line 11) | namespace xloil
    type Python (line 13) | namespace Python
      type PyStatusBar (line 17) | struct PyStatusBar
        method PyStatusBar (line 21) | PyStatusBar(size_t timeout)
        method msg (line 24) | void msg(const std::wstring& msg, size_t timeout)
        method exit (line 29) | void exit(py::args)

FILE: libs/xlOil_Python/TypeConversion/BasicTypes.cpp
  type xloil (line 10) | namespace xloil
    type Python (line 12) | namespace Python
      type CustomReturnConverter (line 16) | struct CustomReturnConverter
      function IPyToExcel (line 23) | const IPyToExcel* detail::getCustomReturnConverter()
      class PyCacheObject (line 34) | class PyCacheObject : public ExcelValVisitor<PyObject*>
        method PyObject (line 40) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 55) | constexpr wchar_t* failMessage() const { return L"Expected cache s...
      type FromPyLong (line 58) | struct FromPyLong
      type FromPyFloat (line 73) | struct FromPyFloat
      type FromPyBool (line 83) | struct FromPyBool
      type FromPyToCache (line 94) | struct FromPyToCache
      type FromPyToSingleValue (line 107) | struct FromPyToSingleValue
      function convertPy (line 125) | void convertPy(pybind11::module& mod, const char* type)
      function convertXl (line 131) | void convertXl(pybind11::module& mod, const char* type)

FILE: libs/xlOil_Python/TypeConversion/BasicTypes.h
  function namespace (line 21) | namespace xloil
  function namespace (line 328) | namespace detail
  function else (line 423) | else if (isPyDate(p))
  function else (line 427) | else if (isErrorType(p))
  function else (line 432) | else if (PyUnicode_Check(p))
  function else (line 436) | else if (detail::getCustomReturnConverter())

FILE: libs/xlOil_Python/TypeConversion/ConverterInterface.h
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_Python/TypeConversion/Numpy.h
  function namespace (line 12) | namespace xloil {
  function namespace (line 18) | namespace xloil

FILE: libs/xlOil_Python/TypeConversion/NumpyDatetime.cpp
  function PyArray_DatetimeMetaData (line 16) | PyArray_DatetimeMetaData *
  function PyArray_Descr (line 25) | PyArray_Descr *
  function npy_int64 (line 57) | inline
  function npy_int32 (line 71) | inline
  function is_leapyear (line 94) | int
  function npy_int64 (line 105) | npy_int64
  function npy_int64 (line 167) | npy_int64
  function npy_int64 (line 181) | npy_int64
  function days_to_month_number (line 211) | int
  function set_datetimestruct_days (line 237) | void
  function NpyDatetime_ConvertDatetimeStructToDatetime64 (line 266) | int
  function NpyDatetime_ConvertDatetime64ToDatetimeStruct (line 401) | int

FILE: libs/xlOil_Python/TypeConversion/NumpyFromExcel.cpp
  type xloil (line 22) | namespace xloil
    type Python (line 24) | namespace Python
      function isArrayDataType (line 26) | bool isArrayDataType(PyTypeObject* t)
      function isNumpyArray (line 31) | bool isNumpyArray(PyObject * p)
      type ToDoubleNPYNan (line 42) | struct ToDoubleNPYNan : conv::ExcelValToType<double, double>
      type ToFloatNPYNan (line 61) | struct ToFloatNPYNan : public ExcelValVisitor<float>
      class NumpyDateFromDate (line 74) | class NumpyDateFromDate : public ExcelValVisitor<npy_datetime>
        method npy_datetime (line 79) | npy_datetime operator()(int x) const noexcept
        method npy_datetime (line 86) | npy_datetime operator()(double x) const noexcept
        method npy_datetime (line 93) | npy_datetime operator()(const PStringRef& str) const
      type TruncateUTF16ToChar (line 107) | struct TruncateUTF16ToChar
      type ToFixedWidthString (line 121) | struct ToFixedWidthString
      type NPToT (line 149) | struct NPToT
      type NPToT<TExcelObjConverter, PyObject*> (line 158) | struct NPToT<TExcelObjConverter, PyObject*>
      type FromExcel (line 166) | struct FromExcel {}
      type FromExcel<Type, std::enable_if_t<std::is_integral_v<typename TypeTraits<Type>::storage>>> (line 167) | struct FromExcel<Type, std::enable_if_t<std::is_integral_v<typename ...
      type FromExcel<NPY_BOOL> (line 171) | struct FromExcel<NPY_BOOL>      { using value = NPToT<conv::ToType<b...
      type FromExcel<NPY_FLOAT> (line 172) | struct FromExcel<NPY_FLOAT>     { using value = NPToT<ToFloatNPYNan,...
      type FromExcel<NPY_DOUBLE> (line 173) | struct FromExcel<NPY_DOUBLE>    { using value = NPToT<ToDoubleNPYNan...
      type FromExcel<NPY_DATETIME> (line 174) | struct FromExcel<NPY_DATETIME>
      type FromExcel<NPY_STRING> (line 178) | struct FromExcel<NPY_STRING>
      type FromExcel<NPY_UNICODE> (line 182) | struct FromExcel<NPY_UNICODE>
      type FromExcel<NPY_OBJECT> (line 186) | struct FromExcel<NPY_OBJECT>
      function getItemSize (line 196) | size_t getItemSize(const ExcelArray&)
      function newNumpyArray (line 224) | py::object newNumpyArray(int numpyType, Py_intptr_t (&dims)[NDim], s...
      class PyFromArray1d (line 259) | class PyFromArray1d : public detail::PyFromExcelImpl<PyFromArray1d<T...
        method PyFromArray1d (line 266) | PyFromArray1d(bool trim = true) : _trim(trim), _conv()
        method PyObject (line 272) | PyObject* operator()(const ExcelObj& obj) const
        method PyObject (line 278) | PyObject* operator()(const ExcelArray& arr) const
        method wchar_t (line 309) | constexpr wchar_t* failMessage() const { return L"Expected array"; }
      class PyFromArray2d (line 313) | class PyFromArray2d : public detail::PyFromExcelImpl<PyFromArray2d<T...
        method PyFromArray2d (line 320) | PyFromArray2d(bool trim = true) : _trim(trim), _conv()
        method PyObject (line 326) | PyObject* operator()(const ExcelObj& obj) const
        method PyObject (line 332) | PyObject* operator()(const ExcelArray& arr) const
        method wchar_t (line 372) | constexpr wchar_t* failMessage() const { return L"Expected array"; }
      function PyObject (line 375) | PyObject* numpyArrayFromCArray(size_t rows, size_t columns, const do...
      class FPArrayConverter (line 387) | class FPArrayConverter : public IPyFromExcel
        method PyObject (line 390) | virtual PyObject* operator()(
      function IPyFromExcel (line 402) | IPyFromExcel* createFPArrayConverter()
      function excelTypeToNumpyDtype (line 407) | int excelTypeToNumpyDtype(ExcelType t)
      function PyObject (line 419) | PyObject* excelArrayToNumpyArray(const ExcelArray& arr, int dims, in...
      function PyObject (line 435) | PyObject* toNumpyDatetimeFromExcelDateArray(const PyObject* obj)
      type Reader (line 523) | struct Reader
      function declare (line 538) | void declare(pybind11::module& mod)

FILE: libs/xlOil_Python/TypeConversion/NumpyHelpers.cpp
  type xloil (line 19) | namespace xloil
    type Python (line 21) | namespace Python
      function importNumpy (line 23) | bool importNumpy()
      function excelDateFromNumpyDate (line 31) | double excelDateFromNumpyDate(const npy_datetime x, const PyArray_Da...
      function PyArray_Descr (line 47) | PyArray_Descr*
      function npy_datetime (line 55) | npy_datetime convertDateTime<NPY_FR_us>(const npy_datetimestruct& dt...
      function ExcelObj (line 67) | ExcelObj FromArrayImpl<NPY_DATETIME>::toExcelObj(

FILE: libs/xlOil_Python/TypeConversion/NumpyHelpers.h
  function namespace (line 22) | namespace xloil
  function stringLength (line 159) | static constexpr size_t stringLength() { return 0; }
  function stringLength (line 181) | static constexpr size_t stringLength() { return 0; }
  function NPY_DATETIME (line 246) | struct FromArrayImpl<NPY_DATETIME>

FILE: libs/xlOil_Python/TypeConversion/NumpyPandas.cpp
  type xloil (line 11) | namespace xloil
    type Python (line 13) | namespace Python
      type TableHelpers (line 15) | namespace TableHelpers
        type ApplyConverter (line 17) | struct ApplyConverter
        type ConverterHolder (line 26) | struct ConverterHolder : public ApplyConverter
          method ConverterHolder (line 31) | ConverterHolder(PyArrayObject* array, bool)
          method stringLength (line 38) | auto stringLength() const { return _impl.stringLength(); }
        type ConverterHolder<NPY_OBJECT> (line 54) | struct ConverterHolder<NPY_OBJECT> : public ApplyConverter
          method ConverterHolder (line 58) | ConverterHolder(PyArrayObject* array, bool objectToString)
          method stringLength (line 83) | size_t stringLength() const { return _builder.stringLength(); }
        type CreateConverter (line 97) | struct CreateConverter
          method ApplyConverter (line 99) | ApplyConverter* operator()(PyArrayObject* array, size_t& stringL...
        function arrayShape (line 107) | size_t arrayShape(const py::handle& p)
        type Converters (line 127) | struct Converters
          method Converters (line 134) | Converters(size_t n, bool objectToString)
          method collect (line 141) | auto collect(const py::handle& p, size_t expectedLength)
          method write (line 157) | auto write(size_t iArray, ExcelArrayBuilder& builder, int startX...
          method hasObjectDtype (line 173) | auto hasObjectDtype() const { return _hasObjectDtype; }
      function ExcelObj (line 177) | ExcelObj numpyTableHelper(

FILE: libs/xlOil_Python/TypeConversion/NumpyToExcel.cpp
  type xloil (line 14) | namespace xloil
    type Python (line 16) | namespace Python
      function isEmptyArray (line 24) | bool isEmptyArray(npy_intp* dims, int nDims)
      class XlFromArray1d (line 34) | class XlFromArray1d : public IPyToExcel
        method XlFromArray1d (line 41) | XlFromArray1d(bool cache = false)
        method ExcelObj (line 45) | ExcelObj operator()(const PyObject* obj) const override
      class XlFromArray2d (line 75) | class XlFromArray2d : public IPyToExcel
        method XlFromArray2d (line 81) | XlFromArray2d(bool cache = false) : _cache(cache) {}
        method ExcelObj (line 83) | ExcelObj operator()(const PyObject* obj) const override
      class XlFromArray1d<NPY_OBJECT> (line 119) | class XlFromArray1d<NPY_OBJECT> : public IPyToExcel
        method XlFromArray1d (line 125) | XlFromArray1d(bool cache = false) : _cacheResult(cache) {}
        method ExcelObj (line 127) | ExcelObj operator()(const PyObject* obj) const override
      class XlFromArray2d<NPY_OBJECT> (line 160) | class XlFromArray2d<NPY_OBJECT> : public IPyToExcel
        method XlFromArray2d (line 166) | XlFromArray2d(bool cache = false) : _cacheResult(cache) {}
        method ExcelObj (line 168) | ExcelObj operator()(const PyObject* obj) const override
      function ExcelObj (line 202) | ExcelObj numpyArrayToExcel(const PyObject* p)
      function numpyToFPArray (line 220) | std::shared_ptr<FPArray> numpyToFPArray(const PyObject* obj)
      type Writer (line 257) | struct Writer

FILE: libs/xlOil_Python/TypeConversion/PyCustomType.cpp
  type xloil (line 12) | namespace xloil
    type Python (line 14) | namespace Python
      class CustomConverterArrayHandler (line 23) | class CustomConverterArrayHandler :
        method CustomConverterArrayHandler (line 30) | CustomConverterArrayHandler() : _excelArray(nullptr)
        method PyObject (line 35) | PyObject* operator()(const ArrayVal& arr) const
        method PyObject (line 47) | PyObject* operator()(CellError err) const
        method setWrapper (line 60) | void setWrapper(PyExcelArray* ptr)
        method wchar_t (line 70) | constexpr wchar_t* failMessage() const { return L"Custom converter...
      class CustomConverter (line 74) | class CustomConverter : public IPyFromExcel
        method CustomConverter (line 82) | CustomConverter(py::object&& callable, bool checkCache, const char...
        method result_type (line 94) | virtual result_type operator()(
        method callConverter (line 109) | auto callConverter(const ExcelObj& xl, const_result_ptr defaultVal)
      class CustomReturn (line 123) | class CustomReturn : public IPyToExcel
        method CustomReturn (line 129) | CustomReturn(py::object&& callable, const char* name)
        method ExcelObj (line 139) | virtual ExcelObj operator()(const PyObject* target) const override
        method invoke (line 155) | auto invoke(const py::object& target) const
        method PyObject (line 160) | PyObject* invokeImpl(const PyObject* target) const

FILE: libs/xlOil_Python/TypeConversion/PyDateType.cpp
  type xloil (line 21) | namespace xloil
    type Python (line 23) | namespace Python
      function importDatetime (line 25) | void importDatetime()
      function isPyDate (line 30) | bool isPyDate(PyObject* p)
      function ExcelObj (line 35) | ExcelObj pyLocalDateTimeToSerial(const PyObject* p)
      function ExcelObj (line 45) | ExcelObj pyDateTimeToSerial(PyObject* p)
      function ExcelObj (line 56) | ExcelObj pyDateToSerial(const PyObject* p)
      function ExcelObj (line 63) | ExcelObj pyDateToExcel(PyObject* p)
      class PyFromDate (line 76) | class PyFromDate : public detail::PyFromExcelImpl<PyFromDate>
        method PyObject (line 82) | PyObject* operator()(int x) const
        method PyObject (line 89) | PyObject* operator()(double x) const
        method PyObject (line 93) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 100) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyFromDateTime (line 103) | class PyFromDateTime : public detail::PyFromExcelImpl<PyFromDateTime>
        method PyObject (line 109) | PyObject* operator()(int x) const
        method PyObject (line 114) | PyObject* operator()(double x) const
        method PyObject (line 122) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 132) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyDateToExcel (line 135) | class PyDateToExcel : public IPyToExcel
        method ExcelObj (line 138) | ExcelObj operator()(const PyObject* obj) const override
      class PyDateTimeToExcel (line 149) | class PyDateTimeToExcel : public IPyToExcel
        method ExcelObj (line 152) | ExcelObj operator()(const PyObject* obj) const override
      function fromExcelDate (line 176) | py::object fromExcelDate(const py::object& obj)
    type Python (line 172) | namespace Python
      function importDatetime (line 25) | void importDatetime()
      function isPyDate (line 30) | bool isPyDate(PyObject* p)
      function ExcelObj (line 35) | ExcelObj pyLocalDateTimeToSerial(const PyObject* p)
      function ExcelObj (line 45) | ExcelObj pyDateTimeToSerial(PyObject* p)
      function ExcelObj (line 56) | ExcelObj pyDateToSerial(const PyObject* p)
      function ExcelObj (line 63) | ExcelObj pyDateToExcel(PyObject* p)
      class PyFromDate (line 76) | class PyFromDate : public detail::PyFromExcelImpl<PyFromDate>
        method PyObject (line 82) | PyObject* operator()(int x) const
        method PyObject (line 89) | PyObject* operator()(double x) const
        method PyObject (line 93) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 100) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyFromDateTime (line 103) | class PyFromDateTime : public detail::PyFromExcelImpl<PyFromDateTime>
        method PyObject (line 109) | PyObject* operator()(int x) const
        method PyObject (line 114) | PyObject* operator()(double x) const
        method PyObject (line 122) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 132) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyDateToExcel (line 135) | class PyDateToExcel : public IPyToExcel
        method ExcelObj (line 138) | ExcelObj operator()(const PyObject* obj) const override
      class PyDateTimeToExcel (line 149) | class PyDateTimeToExcel : public IPyToExcel
        method ExcelObj (line 152) | ExcelObj operator()(const PyObject* obj) const override
      function fromExcelDate (line 176) | py::object fromExcelDate(const py::object& obj)
  type xloil (line 170) | namespace xloil
    type Python (line 23) | namespace Python
      function importDatetime (line 25) | void importDatetime()
      function isPyDate (line 30) | bool isPyDate(PyObject* p)
      function ExcelObj (line 35) | ExcelObj pyLocalDateTimeToSerial(const PyObject* p)
      function ExcelObj (line 45) | ExcelObj pyDateTimeToSerial(PyObject* p)
      function ExcelObj (line 56) | ExcelObj pyDateToSerial(const PyObject* p)
      function ExcelObj (line 63) | ExcelObj pyDateToExcel(PyObject* p)
      class PyFromDate (line 76) | class PyFromDate : public detail::PyFromExcelImpl<PyFromDate>
        method PyObject (line 82) | PyObject* operator()(int x) const
        method PyObject (line 89) | PyObject* operator()(double x) const
        method PyObject (line 93) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 100) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyFromDateTime (line 103) | class PyFromDateTime : public detail::PyFromExcelImpl<PyFromDateTime>
        method PyObject (line 109) | PyObject* operator()(int x) const
        method PyObject (line 114) | PyObject* operator()(double x) const
        method PyObject (line 122) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 132) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyDateToExcel (line 135) | class PyDateToExcel : public IPyToExcel
        method ExcelObj (line 138) | ExcelObj operator()(const PyObject* obj) const override
      class PyDateTimeToExcel (line 149) | class PyDateTimeToExcel : public IPyToExcel
        method ExcelObj (line 152) | ExcelObj operator()(const PyObject* obj) const override
      function fromExcelDate (line 176) | py::object fromExcelDate(const py::object& obj)
    type Python (line 172) | namespace Python
      function importDatetime (line 25) | void importDatetime()
      function isPyDate (line 30) | bool isPyDate(PyObject* p)
      function ExcelObj (line 35) | ExcelObj pyLocalDateTimeToSerial(const PyObject* p)
      function ExcelObj (line 45) | ExcelObj pyDateTimeToSerial(PyObject* p)
      function ExcelObj (line 56) | ExcelObj pyDateToSerial(const PyObject* p)
      function ExcelObj (line 63) | ExcelObj pyDateToExcel(PyObject* p)
      class PyFromDate (line 76) | class PyFromDate : public detail::PyFromExcelImpl<PyFromDate>
        method PyObject (line 82) | PyObject* operator()(int x) const
        method PyObject (line 89) | PyObject* operator()(double x) const
        method PyObject (line 93) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 100) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyFromDateTime (line 103) | class PyFromDateTime : public detail::PyFromExcelImpl<PyFromDateTime>
        method PyObject (line 109) | PyObject* operator()(int x) const
        method PyObject (line 114) | PyObject* operator()(double x) const
        method PyObject (line 122) | PyObject* operator()(const PStringRef& pstr) const
        method wchar_t (line 132) | constexpr wchar_t* failMessage() const { return L"Expected date"; }
      class PyDateToExcel (line 135) | class PyDateToExcel : public IPyToExcel
        method ExcelObj (line 138) | ExcelObj operator()(const PyObject* obj) const override
      class PyDateTimeToExcel (line 149) | class PyDateTimeToExcel : public IPyToExcel
        method ExcelObj (line 152) | ExcelObj operator()(const PyObject* obj) const override
      function fromExcelDate (line 176) | py::object fromExcelDate(const py::object& obj)

FILE: libs/xlOil_Python/TypeConversion/PyDateType.h
  function namespace (line 5) | namespace xloil

FILE: libs/xlOil_Python/TypeConversion/PyDictType.cpp
  type xloil (line 10) | namespace xloil
    type Python (line 12) | namespace Python
      type detail (line 14) | namespace detail
        class PyDictFromArray (line 17) | class PyDictFromArray : public PyFromExcelImpl<PyDictFromArray<TKe...
          method PyObject (line 26) | PyObject* operator()(MissingVal) const
          method PyObject (line 31) | PyObject* operator()(nullptr_t) const
          method PyObject (line 36) | PyObject* operator()(const ArrayVal& obj) const
          method wchar_t (line 60) | constexpr wchar_t* failMessage() const { return L"Expected array...
      function PyObject (line 66) | PyObject* readKeywordArgs(const ExcelObj& obj)
      class XlFromDict (line 72) | class XlFromDict: public IPyToExcel
        method ExcelObj (line 75) | ExcelObj operator()(const PyObject* obj) const override

FILE: libs/xlOil_Python/TypeConversion/PyDictType.h
  function namespace (line 4) | namespace xloil

FILE: libs/xlOil_Python/TypeConversion/PyExcelArrayType.cpp
  type xloil (line 10) | namespace xloil
    type Python (line 12) | namespace Python
      function ExcelArray (line 61) | const ExcelArray& PyExcelArray::base() const
      function PyExcelArray (line 80) | PyExcelArray PyExcelArray::slice(
      function ExcelType (line 134) | ExcelType PyExcelArray::dataType() const { return _base.dataType(); }
      function toArray (line 136) | auto toArray(const PyExcelArray& arr, std::optional<int> dtype, std:...

FILE: libs/xlOil_Python/TypeConversion/PyExcelArrayType.h
  function namespace (line 5) | namespace xloil

FILE: libs/xlOil_Python/TypeConversion/PyRangeType.cpp
  type xloil (line 10) | namespace xloil
    type Python (line 12) | namespace Python
      class PyRangeFromRange (line 16) | class PyRangeFromRange : public detail::PyFromExcelImpl<PyRangeFromR...
        method PyObject (line 22) | PyObject* operator()(const RefVal& obj) const
        method wchar_t (line 26) | constexpr wchar_t* failMessage() const { return L"Expected range"; }

FILE: libs/xlOil_Python/TypeConversion/PyTupleType.cpp
  type xloil (line 13) | namespace xloil
    type Python (line 15) | namespace Python
      function ExcelObj (line 17) | ExcelObj nestedIterableToExcel(const PyObject* obj)
      class PyTupleFromArray (line 100) | class PyTupleFromArray : public detail::PyFromExcelImpl<PyTupleFromA...
        method PyObject (line 107) | PyObject* operator()(const ExcelObj& obj) const
        method wchar_t (line 139) | constexpr wchar_t* failMessage() const { return L"Expected array"; }
      class PyListFromArray (line 143) | class PyListFromArray : public detail::PyFromExcelImpl<PyListFromArr...
        method PyObject (line 150) | PyObject* operator()(const ExcelObj& obj) const
        method wchar_t (line 183) | constexpr wchar_t* failMessage() const { return L"Expected array"; }
      function PyObject (line 186) | PyObject* excelArrayToNestedTuple(const ExcelObj & obj)
      type Adapter (line 193) | struct Adapter

FILE: libs/xlOil_Python/TypeConversion/PyTupleType.h
  function namespace (line 5) | namespace xloil

FILE: libs/xlOil_SQL/Cache.cpp
  type xloil (line 5) | namespace xloil
    type CacheUniquifier<std::unique_ptr<const SQL::CacheObj>> (line 8) | struct CacheUniquifier<std::unique_ptr<const SQL::CacheObj>>
    type SQL (line 13) | namespace SQL
      function ExcelObj (line 15) | ExcelObj cacheAdd(unique_ptr<const CacheObj>&& obj)
      function CacheObj (line 21) | const CacheObj* cacheFetch(const std::wstring_view& key)

FILE: libs/xlOil_SQL/Cache.h
  type sqlite3 (line 4) | struct sqlite3
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_SQL/Common.cpp
  type xloil (line 12) | namespace xloil
    type SQL (line 14) | namespace SQL
      function sqlThrow (line 16) | void sqlThrow(sqlite3* db, int errCode)
      function newDatabase (line 22) | shared_ptr<sqlite3> newDatabase()
      function wstring (line 34) | wstring tableSchema(
      function createVTable (line 76) | void createVTable(
      function sqlPrepare (line 98) | shared_ptr<sqlite3_stmt> sqlPrepare(sqlite3* db, const wstring& sql)
      function sqlExec (line 107) | int sqlExec(sqlite3* db, const wstring& sql)
      function ExcelObj (line 136) | ExcelObj sqlQueryToArray(const std::shared_ptr<sqlite3_stmt>& prepared)

FILE: libs/xlOil_SQL/Common.h
  function namespace (line 13) | namespace xloil { class ExcelArray; }
  function namespace (line 15) | namespace xloil

FILE: libs/xlOil_SQL/Main.cpp
  type xloil (line 5) | namespace xloil
    type SQL (line 7) | namespace SQL
      function XLO_PLUGIN_INIT (line 9) | XLO_PLUGIN_INIT(AddinContext* context, const PluginContext& plugin)

FILE: libs/xlOil_SQL/XlArrayTable.cpp
  type xloil (line 10) | namespace xloil
    type SQL (line 12) | namespace SQL
      type XlArrayTable (line 16) | struct XlArrayTable
        method XlArrayTable (line 19) | XlArrayTable(const InputType& input) : data(input) {}
      type XlRangeTable (line 24) | struct XlRangeTable
        method XlRangeTable (line 27) | XlRangeTable(const InputType& input) : data(input) {}
      type XlTableCursor (line 48) | struct XlTableCursor
      function xConnect (line 55) | static int xConnect(
      function xCreate (line 81) | static int xCreate(
      function xBestIndex (line 91) | static int xBestIndex(
      function xDisconnect (line 103) | static int xDisconnect(sqlite3_vtab *pVtab) {
      function xOpen (line 109) | static int xOpen(sqlite3_vtab*, sqlite3_vtab_cursor **ppCursor) {
      function xClose (line 118) | static int xClose(sqlite3_vtab_cursor *cur) {
      function xFilter (line 128) | static int xFilter(
      function xNext (line 143) | static int xNext(sqlite3_vtab_cursor *cur)
      function xEof (line 156) | static int xEof(sqlite3_vtab_cursor *cur) {
      type TableReturn (line 162) | struct TableReturn {}
      type TableReturn<XlRangeTable> (line 163) | struct TableReturn<XlRangeTable> { using type = ExcelObj; }
      type TableReturn<XlArrayTable> (line 164) | struct TableReturn<XlArrayTable> { using type = const ExcelObj&; }
      type ExcelValToSqlType (line 167) | struct ExcelValToSqlType
      function xColumn (line 193) | static int xColumn(
      function xRowid (line 208) | static int xRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid)

FILE: libs/xlOil_SQL/XlArrayTable.h
  type sqlite3_module (line 3) | struct sqlite3_module
  function namespace (line 4) | namespace xloil { class ExcelArray; class ExcelRef; class ExcelObj;  }
  function namespace (line 6) | namespace xloil

FILE: libs/xlOil_SQL/xloSql.cpp
  type xloil (line 15) | namespace xloil
    type SQL (line 17) | namespace SQL
      function processMeta (line 19) | void processMeta(
      function XLO_FUNC_START (line 51) | XLO_FUNC_START(

FILE: libs/xlOil_SQL/xloSqlDB.cpp
  type xloil (line 13) | namespace xloil
    type SQL (line 15) | namespace SQL
      class DataBaseRef (line 17) | class DataBaseRef : public CacheObj
        method DataBaseRef (line 20) | DataBaseRef(const std::shared_ptr<sqlite3>& db)
        method getDB (line 23) | virtual std::shared_ptr<sqlite3> getDB() const
      function XLO_FUNC_START (line 30) | XLO_FUNC_START(xloSqlDB())

FILE: libs/xlOil_SQL/xloSqlQuery.cpp
  type xloil (line 12) | namespace xloil
    type SQL (line 14) | namespace SQL
      function XLO_FUNC_START (line 16) | XLO_FUNC_START( xloSqlQuery(

FILE: libs/xlOil_SQL/xloSqlTable.cpp
  type xloil (line 13) | namespace xloil
    type SQL (line 15) | namespace SQL
      function XLO_FUNC_START (line 17) | XLO_FUNC_START( xloSqlTable(

FILE: libs/xlOil_SQL/xloSqlTables.cpp
  type xloil (line 12) | namespace xloil
    type SQL (line 14) | namespace SQL
      function XLO_FUNC_START (line 16) | XLO_FUNC_START( xloSqlTables(

FILE: libs/xlOil_Utils/Main.cpp
  type xloil (line 4) | namespace xloil
    type Utils (line 6) | namespace Utils
      function XLO_PLUGIN_INIT (line 8) | XLO_PLUGIN_INIT(AddinContext* ctx, const PluginContext& plugin)

FILE: libs/xlOil_Utils/RegexHelpers.h
  function namespace (line 5) | namespace xloil

FILE: libs/xlOil_Utils/xloBlock.cpp
  type xloil (line 18) | namespace xloil
    function XLO_FUNC_START (line 24) | XLO_FUNC_START( xloBlock(

FILE: libs/xlOil_Utils/xloConcat.cpp
  type xloil (line 10) | namespace xloil
    function XLO_FUNC_START (line 15) | XLO_FUNC_START( xloConcat(

FILE: libs/xlOil_Utils/xloFill.cpp
  type xloil (line 6) | namespace xloil
    function XLO_FUNC_START (line 8) | XLO_FUNC_START(

FILE: libs/xlOil_Utils/xloFillNA.cpp
  type xloil (line 7) | namespace xloil
    function XLO_FUNC_START (line 9) | XLO_FUNC_START(

FILE: libs/xlOil_Utils/xloIndex.cpp
  type xloil (line 7) | namespace xloil
    function XLO_FUNC_START (line 9) | XLO_FUNC_START(

FILE: libs/xlOil_Utils/xloPad.cpp
  type xloil (line 7) | namespace xloil
    function XLO_FUNC_START (line 9) | XLO_FUNC_START(

FILE: libs/xlOil_Utils/xloRegex.cpp
  type xloil (line 14) | namespace xloil
    function doMatch (line 19) | auto doMatch(const TStr& str, const std::wregex& regex,
    function XLO_FUNC_START (line 32) | XLO_FUNC_START(xloRegex(

FILE: libs/xlOil_Utils/xloSearch.cpp
  type xloil (line 14) | namespace xloil
    function XLO_FUNC_START (line 16) | XLO_FUNC_START(xloSearch(

FILE: libs/xlOil_Utils/xloSort.cpp
  type xloil (line 14) | namespace xloil
    type SortDirection (line 20) | enum SortDirection
    type LessThan (line 30) | struct LessThan
      method LessThan (line 32) | LessThan(const ExcelArray& data, const MyArray& directions, const My...
    function swapmem (line 58) | void swapmem(size_t* a, size_t* b, size_t nBytes)
    function XLO_FUNC_START (line 71) | XLO_FUNC_START(

FILE: libs/xlOil_Utils/xloSplit.cpp
  type xloil (line 12) | namespace xloil
    function findSplitPoints (line 16) | void findSplitPoints(
    function XLO_FUNC_START (line 50) | XLO_FUNC_START(xloSplit(

FILE: src/xlOil-COM/API/ComUtils.cpp
  type xloil (line 20) | namespace xloil
    function ExcelObj (line 28) | ExcelObj variantToExcelObj(const VARIANT& variant, bool allowRange)
    function excelObjToVariant (line 33) | void excelObjToVariant(VARIANT* v, const ExcelObj& obj)
    function statusBarMsg (line 38) | void statusBarMsg(const std::wstring_view& msg, size_t timeout)

FILE: src/xlOil-COM/API/Events.cpp
  type xloil (line 29) | namespace xloil
    type Event (line 31) | namespace Event
      type DirectoryWatchEvent (line 53) | struct DirectoryWatchEvent : public DirectoryWatchEventBase
        method DirectoryWatchEvent (line 55) | DirectoryWatchEvent(const std::wstring& path, const bool subDirs)
        method handleFileAction (line 70) | void handleFileAction(
      function directoryWatchChange (line 91) | void directoryWatchChange(int64_t id, const set<pair<wstring, uint32...
      function directoryWatchError (line 117) | void directoryWatchError(int64_t id)
      function XLOIL_EXPORT (line 126) | XLOIL_EXPORT std::wstring to_wstring(const FileAction x)
      function XLOIL_EXPORT (line 138) | XLOIL_EXPORT shared_ptr<DirectoryWatchEventBase> DirectoryChange(con...

FILE: src/xlOil-COM/API/ExcelRange.cpp
  type xloil (line 11) | namespace xloil
    function _variant_t (line 15) | _variant_t stringToVariant(const std::wstring_view& str)
    function newRange (line 22) | std::unique_ptr<Range> newRange(const wchar_t* address)
    function ExcelRef (line 29) | ExcelRef refFromComRange(Excel::Range& range)
    function ExcelObj (line 154) | ExcelObj ExcelRange::value() const
    function ExcelObj (line 159) | ExcelObj ExcelRange::value(row_t i, col_t j) const
    function ExcelObj (line 209) | ExcelObj ExcelRange::formula() const
    function ExcelWorksheet (line 246) | ExcelWorksheet ExcelRange::parent() const
    function Application (line 255) | Application ExcelRange::app() const
    type SpecialCellsValue (line 259) | enum class SpecialCellsValue : int
    function ExcelRange (line 267) | ExcelRange ExcelRange::specialCells(SpecialCells type, ExcelType value...

FILE: src/xlOil-COM/API/ExcelThread.cpp
  type xloil (line 28) | namespace xloil
    class Messenger (line 32) | class Messenger
      method Messenger (line 35) | Messenger(HINSTANCE excelInstance)
      method createInstance (line 74) | static void createInstance(void* excelInstance)
      method destroyInstance (line 79) | static void destroyInstance()
      method Messenger (line 85) | static Messenger& instance()
      type QueueItem (line 92) | struct QueueItem
        method QueueItem (line 98) | QueueItem(
        method useCOM (line 107) | bool useCOM() const noexcept
        method useXLL (line 111) | bool useXLL() const noexcept
      method firstJobTime (line 151) | auto firstJobTime(ULONGLONG now)
      method startTimer (line 159) | void startTimer(unsigned millisecs)
      method enqueue (line 167) | void enqueue(const shared_ptr<QueueItem>& item, unsigned millisecs) ...
      method TimerCallback (line 193) | static void CALLBACK TimerCallback(
      method LRESULT (line 260) | static LRESULT CALLBACK WindowProc(
    function initMessageQueue (line 286) | void initMessageQueue(void* excelInstance)
    function teardownMessageQueue (line 291) | void teardownMessageQueue()
    function isMainThread (line 296) | bool isMainThread()
    function isCallerInfoSafe (line 322) | bool isCallerInfoSafe()
    type detail (line 327) | namespace detail
      function runExcelThreadImpl (line 329) | void runExcelThreadImpl(
      type RetryAtStartup (line 367) | struct RetryAtStartup
    function runComSetupOnXllOpen (line 392) | void runComSetupOnXllOpen(const std::function<void()>& func)

FILE: src/xlOil-COM/API/RtdServer.cpp
  type xloil (line 19) | namespace xloil
    function wchar_t (line 70) | const wchar_t* RtdPublisher::topic() const noexcept
    function newRtdServer (line 88) | std::shared_ptr<IRtdServer> newRtdServer(
    function rtdAsync (line 94) | shared_ptr<ExcelObj> rtdAsync(const shared_ptr<IRtdAsyncTask>& task)
    function rtdAsyncServerClear (line 111) | void rtdAsyncServerClear()

FILE: src/xlOil-COM/AppObjects.cpp
  function workaroundVisualStudioBug (line 21) | void workaroundVisualStudioBug()
  type xloil (line 49) | namespace xloil
    type comPtrCast (line 60) | struct comPtrCast
    type comPtrCast<T, T> (line 65) | struct comPtrCast<T, T>
    function fromComPtr (line 74) | auto fromComPtr(const ComPtr_t<V>& v)
    type signature (line 80) | struct signature
    function throwIfRequired (line 100) | void throwIfRequired(HRESULT hr)
    function _variant_t (line 110) | _variant_t toVariant(const T& x)
    function _variant_t (line 116) | _variant_t toVariant(const std::wstring_view& str)
    function IDispatch (line 123) | IDispatch* getItemHelper(TObj& obj, const _variant_t& what, HRESULT& r...
    function IDispatch (line 132) | IDispatch* getItemHelper(TObj& obj, const _variant_t& what, HRESULT& r...
    function comTryGet (line 147) | bool comTryGet(TObj& obj, const TArg& what, TRes& out)
    function TRes (line 161) | TRes comGetItem(TObj& obj, const TArg& what)
    function comGetApp (line 171) | auto comGetApp(T& x)
    function comGetApp (line 180) | auto comGetApp(T& x)
    function comGetCount (line 190) | auto comGetCount(T& x)
    function comGetCount (line 199) | auto comGetCount(T& x)
    function Application (line 209) | Application& thisApp()
    function Application (line 249) | Application workbookFinder(const wchar_t* workbook)
    function ExcelWorksheet (line 290) | ExcelWorksheet Application::activeWorksheet() const
    function ExcelRange (line 301) | ExcelRange Application::activeCell() const
    function ExcelRange (line 431) | ExcelRange Application::selection()
    function appRun_impl (line 443) | decltype(auto) appRun_impl(F func, T(&args)[N], std::index_sequence<Id...
    function appRun (line 448) | decltype(auto) appRun(const wchar_t* func, T(&args)[N]) {
    function ExcelObj (line 453) | ExcelObj Application::run(
    function ExcelWorkbook (line 489) | ExcelWorkbook Application::open(
    function Application (line 535) | Application ExcelWindow::app() const
    function ExcelWorkbook (line 544) | ExcelWorkbook ExcelWindow::workbook() const
    function Application (line 574) | Application ExcelWorkbook::app() const
    function ExcelWorksheet (line 589) | ExcelWorksheet ExcelWorkbook::add(
    function Application (line 641) | Application ExcelWorksheet::app() const
    function ExcelWorkbook (line 646) | ExcelWorkbook ExcelWorksheet::parent() const
    function ExcelRange (line 655) | ExcelRange ExcelWorksheet::range(
    function ExcelRange (line 675) | ExcelRange ExcelWorksheet::range(const std::wstring_view& address) const
    function ExcelObj (line 689) | ExcelObj ExcelWorksheet::value(Range::row_t i, Range::col_t j) const
    function ExcelRange (line 695) | ExcelRange ExcelWorksheet::usedRange() const
    function ExcelWorkbook (line 731) | ExcelWorkbook Workbooks::add()
    function variantToUnknown (line 742) | auto variantToUnknown(const VARIANT& v)
    function UnknownObject (line 762) | UnknownObject detail::ComIteratorBase::get()
    function T (line 825) | T Collection<T, Ptr>::get(const std::wstring_view& name) const
    function T (line 831) | T Collection<T, Ptr>::get(const size_t index) const
    function Application (line 855) | Application Collection<T, Ptr>::app() const
    function ExcelWorkbook (line 890) | ExcelWorkbook Worksheets::parent() const
  type signature<R(Args...)> (line 83) | struct signature<R(Args...)>
  type signature<R (C::*)(Args...)> (line 89) | struct signature<R (C::*)(Args...)>

FILE: src/xlOil-COM/ClassFactory.cpp
  function HRESULT (line 7) | HRESULT inline regWriteImpl(
  function HRESULT (line 40) | HRESULT inline regWrite(
  function HRESULT (line 50) | HRESULT inline regWrite(
  type xloil (line 61) | namespace xloil
    type COM (line 63) | namespace COM
      class ClassFactory (line 65) | class ClassFactory : public ComObject<IClassFactory>
        method ClassFactory (line 71) | ClassFactory(const creator_t& func)
      function HRESULT (line 205) | HRESULT RegisterCom::writeRegistry(
      function HRESULT (line 216) | HRESULT RegisterCom::writeRegistry(

FILE: src/xlOil-COM/ClassFactory.h
  function namespace (line 11) | namespace xloil

FILE: src/xlOil-COM/ComAddin.cpp
  type xloil (line 24) | namespace xloil
    type COM (line 26) | namespace COM
      type ComAddinEvents (line 28) | struct ComAddinEvents
        method OnDisconnection (line 30) | void OnDisconnection(bool /*excelClosing*/) {}
        method OnAddInsUpdate (line 31) | void OnAddInsUpdate() { Event::ComAddinsUpdate().fire(); }
        method OnBeginShutdown (line 32) | void OnBeginShutdown() {}
      class CustomTaskPaneConsumerImpl (line 35) | class CustomTaskPaneConsumerImpl :
        method HRESULT (line 39) | HRESULT __stdcall raw_CTPFactoryAvailable(ICTPFactory* ctpfactory)...
      class ComAddinImpl (line 84) | class ComAddinImpl :
        method ComAddinImpl (line 88) | ComAddinImpl()
        method HRESULT (line 115) | virtual HRESULT __stdcall raw_OnConnection(
        method HRESULT (line 123) | virtual HRESULT __stdcall raw_OnDisconnection(
        method HRESULT (line 131) | virtual HRESULT __stdcall raw_OnAddInsUpdate(SAFEARRAY**) override
        method HRESULT (line 136) | virtual HRESULT __stdcall raw_OnStartupComplete(SAFEARRAY**) override
        method HRESULT (line 140) | virtual HRESULT __stdcall raw_OnBeginShutdown(SAFEARRAY**) override
        method ICTPFactory (line 146) | ICTPFactory* ctpFactory() const
      type SetAutomationSecurity (line 156) | struct SetAutomationSecurity
        method SetAutomationSecurity (line 158) | SetAutomationSecurity(Office::MsoAutomationSecurity value)
      class ComAddinCreator (line 176) | class ComAddinCreator : public IComAddin
        method ComAddinCreator (line 194) | ComAddinCreator(const wchar_t* name, const wchar_t* description)
        method create (line 210) | static auto create(const wchar_t* name, const wchar_t* description)
        method close (line 223) | void close() noexcept override
        method findAddin (line 245) | void findAddin(Excel::_Application& app)
        method isComAddinConnected (line 251) | bool isComAddinConnected() const
        method connect (line 262) | void connect(
        method disconnect (line 335) | void disconnect() override
        method wchar_t (line 347) | const wchar_t* progid() const override
        method ribbonInvalidate (line 351) | void ribbonInvalidate(const wchar_t* controlId = 0) const override
        method ribbonActivate (line 356) | bool ribbonActivate(const wchar_t* controlId) const override
        method createTaskPane (line 363) | shared_ptr<ICustomTaskPane> createTaskPane(
        method TaskPaneMap (line 384) | const TaskPaneMap& panes() const override { return _panes; }
        method handleWorkbookClose (line 386) | void handleWorkbookClose(const wchar_t* wbName)
      function createComAddin (line 393) | shared_ptr<IComAddin> createComAddin(

FILE: src/xlOil-COM/ComAddin.h
  function namespace (line 3) | namespace xloil

FILE: src/xlOil-COM/ComEventSink.cpp
  type xloil (line 15) | namespace xloil
    type COM (line 17) | namespace COM
      class WorkbookMonitor (line 25) | class WorkbookMonitor
        method checkOnOpenWorkbook (line 28) | static void checkOnOpenWorkbook(struct Excel::_Workbook* Wb)
        method Workbook_BeforeSave (line 43) | static void Workbook_BeforeSave()
        method Workbook_AfterSave (line 57) | static void Workbook_AfterSave(bool success)
        method check (line 72) | static void check()
      class EventHandler (line 109) | class EventHandler :
        method EventHandler (line 117) | EventHandler(Excel::_Application* source)
        method NewWorkbook (line 122) | void NewWorkbook(Workbook* Wb)
        method SheetSelectionChange (line 127) | void SheetSelectionChange(
        method SheetBeforeDoubleClick (line 138) | void SheetBeforeDoubleClick(
        method SheetBeforeRightClick (line 151) | void SheetBeforeRightClick(
        method SheetActivate (line 164) | void SheetActivate(IDispatch* Sh)
        method SheetDeactivate (line 170) | void SheetDeactivate(IDispatch* Sh)
        method SheetCalculate (line 176) | void SheetCalculate(IDispatch* Sh)
        method SheetChange (line 184) | void SheetChange(
        method WorkbookOpen (line 195) | static void WorkbookOpen(Workbook* Wb)
        method WorkbookActivate (line 200) | static void WorkbookActivate(Workbook* Wb)
        method WorkbookDeactivate (line 204) | static void WorkbookDeactivate(Workbook* Wb)
        method WorkbookBeforeClose (line 208) | static void WorkbookBeforeClose(
        method WorkbookBeforeSave (line 225) | static void WorkbookBeforeSave(
        method WorkbookAfterSave (line 235) | static void WorkbookAfterSave(
        method WorkbookBeforePrint (line 242) | void WorkbookBeforePrint(
        method WorkbookNewSheet (line 250) | void WorkbookNewSheet(
        method WorkbookAddinInstall (line 256) | void WorkbookAddinInstall(Workbook* Wb)
        method WorkbookAddinUninstall (line 260) | void WorkbookAddinUninstall(Workbook* Wb)
        method AfterCalculate (line 264) | void AfterCalculate()
        method inStack (line 282) | bool inStack(short dispid)
      function createEventSink (line 415) | std::shared_ptr<Excel::AppEvents> createEventSink(Excel::_Applicatio...

FILE: src/xlOil-COM/ComEventSink.h
  function namespace (line 5) | namespace Excel { struct AppEvents; struct _Application; }
  function namespace (line 6) | namespace xloil

FILE: src/xlOil-COM/ComVariant.cpp
  type xloil (line 13) | namespace xloil
    type COM (line 15) | namespace COM
      function elementConvert (line 21) | auto elementConvert(const T& val)       { return val; }
      function elementConvert (line 23) | auto elementConvert(const VARIANT& val) { return variantToExcelObj(v...
      function addStringLength (line 26) | void addStringLength(size_t&, const T&) {}
      function addStringLength (line 29) | void addStringLength(size_t& len, const BSTR& v)
      function addStringLength (line 35) | void addStringLength(size_t& len, const VARIANT& v)
      function variantErrorToCellError (line 41) | auto variantErrorToCellError(SCODE scode)
      function isNonEmpty (line 46) | bool isNonEmpty(VARIANT& obj)
      function trimmedArraySize (line 59) | void trimmedArraySize(VARIANT* data, size_t& nRows, size_t& nCols)
      function stringLength (line 81) | size_t stringLength(const SafeArrayAccessor<T>& array)
      function toExcelObj (line 115) | auto toExcelObj(SafeArrayAccessor<T> array, bool trimArray)
      class ToVariant (line 137) | class ToVariant : public ExcelValVisitor<VARIANT>
        method result_t (line 144) | result_t operator()(int x) const
        method result_t (line 148) | result_t operator()(bool x) const
        method result_t (line 152) | result_t operator()(double x) const
        method result_t (line 156) | result_t operator()(const ArrayVal& obj) const
        method result_t (line 161) | result_t operator()(const ExcelArray& arr) const
        method result_t (line 187) | result_t operator()(const PStringRef& pstr) const
        method result_t (line 195) | result_t operator()(CellError x) const
        method result_t (line 201) | result_t operator()(const RefVal& ref) const
        method result_t (line 207) | result_t operator()(const ExcelObj& obj) const
      class ToVariantWithRange (line 213) | class ToVariantWithRange : public ToVariant
        method result_t (line 218) | result_t operator()(const RefVal& ref) const
      function excelObjToVariant (line 225) | void excelObjToVariant(VARIANT* v, const ExcelObj& obj, bool allowRa...
      function ExcelObj (line 233) | ExcelObj variantToExcelObj(const VARIANT& variant, bool allowRange, ...
      function trimmedVariantArrayBounds (line 292) | bool trimmedVariantArrayBounds(const VARIANT& variant, size_t& nRows...
      function VARIANT (line 307) | VARIANT stringToVariant(const char* str)
      function VARIANT (line 312) | VARIANT stringToVariant(const wchar_t* str)
      function VARIANT (line 317) | VARIANT stringToVariant(const std::wstring_view& str)

FILE: src/xlOil-COM/ComVariant.h
  type VARIANT (line 4) | typedef struct tagVARIANT VARIANT;
  type SAFEARRAY (line 5) | typedef struct tagSAFEARRAY SAFEARRAY;
  function namespace (line 7) | namespace xloil

FILE: src/xlOil-COM/Connect.cpp
  type xloil (line 14) | namespace xloil
    type COM (line 18) | namespace COM
      function HWND (line 20) | HWND nextExcelMainWindow(HWND startFrom)
      class COMConnector (line 71) | class COMConnector
        method COMConnector (line 74) | COMConnector()
        method connect (line 78) | bool connect()
        method connected (line 106) | bool connected() const { return _xlApp.valid(); }
        method Application (line 115) | Application& thisApp() { return (Application&)_xlApp; }
      function connectCom (line 125) | bool connectCom()
      function disconnectCom (line 133) | void disconnectCom()
      function isComApiAvailable (line 138) | bool isComApiAvailable() noexcept
      function Application (line 149) | Application& attachedApplication()

FILE: src/xlOil-COM/Connect.h
  function namespace (line 4) | namespace xloil { class Application; }
  function namespace (line 5) | namespace Excel { struct _Application; }
  function namespace (line 7) | namespace xloil

FILE: src/xlOil-COM/CustomTaskPane.cpp
  type xloil (line 13) | namespace xloil
    type COM (line 15) | namespace COM
      class CustomTaskPaneEventHandler (line 17) | class CustomTaskPaneEventHandler
        method CustomTaskPaneEventHandler (line 22) | CustomTaskPaneEventHandler(
        method HRESULT (line 60) | HRESULT VisibleStateChange(Office::_CustomTaskPane*)
        method HRESULT (line 65) | HRESULT DockPositionStateChange(Office::_CustomTaskPane*)
      class CustomTaskPaneCreator (line 76) | class CustomTaskPaneCreator : public ICustomTaskPane
        method CustomTaskPaneCreator (line 84) | CustomTaskPaneCreator(
        method IDispatch (line 113) | IDispatch* content() const override
        method ExcelWindow (line 122) | ExcelWindow window() const override
        method setVisible (line 131) | void setVisible(bool value) override
        method getVisible (line 139) | bool getVisible() override
        method getSize (line 147) | std::pair<int, int> getSize() override
        method setSize (line 155) | void setSize(int width, int height) override
        method DockPosition (line 164) | DockPosition getPosition() const override
        method setPosition (line 172) | void setPosition(DockPosition pos) override
        method getTitle (line 181) | std::wstring getTitle() const
        method destroy (line 190) | void destroy() override
        method listen (line 206) | void listen(const std::shared_ptr<ICustomTaskPaneEvents>& events) ...
        method attach (line 215) | void attach(size_t hwnd, bool asParent) override
      function ICustomTaskPane (line 227) | ICustomTaskPane* createCustomTaskPane(

FILE: src/xlOil-COM/CustomTaskPane.h
  function namespace (line 3) | namespace Office { struct ICTPFactory; }
  function namespace (line 5) | namespace xloil

FILE: src/xlOil-COM/RibbonExtensibility.cpp
  type xloil (line 15) | namespace xloil
    type COM (line 17) | namespace COM
      class RibbonImpl (line 19) | class RibbonImpl :
        method RibbonImpl (line 34) | RibbonImpl()
        method HRESULT (line 46) | virtual HRESULT __stdcall raw_GetCustomUI(
        method HRESULT (line 55) | HRESULT onLoadHandler(IDispatch* disp)
        method setRibbon (line 65) | void setRibbon(
        method addCallback (line 77) | int addCallback(const wchar_t* name, RibbonCallback&& fn)
      class Ribbon (line 200) | class Ribbon : public IRibbon
        method Ribbon (line 203) | Ribbon(
        method invalidate (line 210) | void invalidate(const wchar_t* controlId) const override
        method activateTab (line 221) | bool activateTab(const wchar_t* controlId) const override
      function createRibbon (line 236) | shared_ptr<IRibbon> createRibbon(

FILE: src/xlOil-COM/RibbonExtensibility.h
  function namespace (line 6) | namespace Office { struct IRibbonExtensibility; }
  function namespace (line 7) | namespace xloil { struct RibbonControl;  }
  type VARIANT (line 8) | typedef struct tagVARIANT VARIANT;
  function namespace (line 10) | namespace xloil

FILE: src/xlOil-COM/RtdAsyncManager.cpp
  type scoped_atomic_flag (line 29) | struct scoped_atomic_flag
    method scoped_atomic_flag (line 33) | scoped_atomic_flag(std::atomic_flag& flag)
    method swap (line 53) | void swap(scoped_atomic_flag& that)
  type xloil (line 60) | namespace xloil
    type COM (line 62) | namespace COM
      class AsyncTaskPublisher (line 64) | class AsyncTaskPublisher
        method AsyncTaskPublisher (line 98) | AsyncTaskPublisher(
        method disconnect (line 107) | bool disconnect(size_t numSubscribers) override
        method taskMatches (line 121) | bool taskMatches(const IRtdAsyncTask& that) const
      type CellTasks (line 66) | struct CellTasks
        method isSubarray (line 74) | bool isSubarray(const msxll::XLREF12& ref) const
        method setCaller (line 79) | void setCaller(const msxll::XLREF12& ref)
      class AsyncTaskPublisher (line 93) | class AsyncTaskPublisher : public RtdPublisher
        method AsyncTaskPublisher (line 98) | AsyncTaskPublisher(
        method disconnect (line 107) | bool disconnect(size_t numSubscribers) override
        method taskMatches (line 121) | bool taskMatches(const IRtdAsyncTask& that) const
      function startCellTask (line 127) | void startCellTask(
      function newCellTasks (line 143) | auto newCellTasks(
      function writeArray (line 154) | void writeArray(
      type RtdAsyncManager (line 169) | namespace RtdAsyncManager
        class Impl (line 176) | class Impl
          method Impl (line 179) | Impl()
          method clear (line 189) | void clear()
          method findTargetCellTasks (line 195) | auto findTargetCellTasks(
        function Impl (line 263) | Impl* getInstance(unique_lock<shared_mutex>& lock)
          method Impl (line 179) | Impl()
          method clear (line 189) | void clear()
          method findTargetCellTasks (line 195) | auto findTargetCellTasks(
        function getValueAndSubscribe (line 300) | static auto getValueAndSubscribe(
        function init (line 375) | void init()
        function getValue (line 382) | std::shared_ptr<const ExcelObj>
        function clear (line 425) | void clear()

FILE: src/xlOil-COM/RtdAsyncManager.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOil-COM/RtdManager.cpp
  class AtlModule (line 33) | class AtlModule : public CAtlDllModuleT<AtlModule>
  type xloil (line 37) | namespace xloil
    type COM (line 39) | namespace COM
      class RtdServerImpl (line 42) | class
        method updateNotify (line 56) | void updateNotify()
        method TWorker (line 67) | TWorker& manager()
        method HRESULT (line 84) | HRESULT _InternalQueryInterface(REFIID riid, void** ppv) throw()
        method HRESULT (line 96) | HRESULT __stdcall raw_ServerStart(
        method HRESULT (line 115) | HRESULT __stdcall raw_ConnectData(
        method HRESULT (line 139) | HRESULT __stdcall raw_RefreshData(
        method HRESULT (line 156) | HRESULT __stdcall raw_DisconnectData(long topicId) override
        method HRESULT (line 170) | HRESULT __stdcall raw_Heartbeat(long* result) override
        method HRESULT (line 177) | HRESULT __stdcall raw_ServerTerminate() override
      class RtdServer (line 197) | class RtdServer : public IRtdServer
        method RtdServer (line 206) | RtdServer(const wchar_t* progId, const GUID* fixedClsid)
        method testConnect (line 221) | void testConnect(long topicId, const std::wstring_view& topicName)
        method testDisconnect (line 226) | void testDisconnect(long topicId)
        method start (line 231) | void start(
        method subscribe (line 237) | shared_ptr<const ExcelObj> subscribe(const wchar_t * topic) override
        method subscribeOnly (line 246) | void subscribeOnly(const wchar_t* topic) override
        method publish (line 250) | bool publish(const wchar_t* topic, ExcelObj&& value = ExcelObj( st...
        method peek (line 255) | shared_ptr<const ExcelObj>
        method drop (line 264) | bool drop(const wchar_t* topic) override
        method wchar_t (line 268) | const wchar_t* progId() const noexcept override
        method clear (line 273) | void clear() override
        method callRtd (line 297) | bool callRtd(const wchar_t* topic) const
      function newRtdServer (line 305) | std::shared_ptr<IRtdServer> newRtdServer(

FILE: src/xlOil-COM/RtdManager.h
  type tagSAFEARRAY (line 4) | struct tagSAFEARRAY
  function namespace (line 7) | namespace xloil

FILE: src/xlOil-COM/RtdServerWorker.h
  function namespace (line 27) | namespace xloil

FILE: src/xlOil-COM/TaskPaneHostControl.cpp
  type xloil (line 15) | namespace xloil
    type COM (line 17) | namespace COM
      class ATL_NO_VTABLE (line 25) | class ATL_NO_VTABLE
      function detach (line 57) | void detach() noexcept
      function CLSID (line 100) | static const CLSID& WINAPI GetObjectCLSID()
      function AttachWindow (line 105) | void AttachWindow(HWND hwnd, bool asParent) override
      function AttachDestroyHandler (line 155) | void AttachDestroyHandler(const std::shared_ptr<ICustomTaskPaneEvent...
    function HWND (line 197) | HWND GetExcelHWND(HWND from)
    function HWND (line 203) | HWND GetAttachableParent()
    function HWND (line 220) | HWND getWindowByClass(HWND from, const wchar_t* className, size_t len ...
    function moveAttachedWindow (line 249) | void moveAttachedWindow()
    function HRESULT (line 266) | HRESULT OnPosChanging(UINT message, WPARAM wParam, LPARAM lParam, BOOL...
    function LRESULT (line 283) | static LRESULT CALLBACK parentSubclassProc(
    function LRESULT (line 340) | static LRESULT CALLBACK handleMoveSubclassProc(
    function LRESULT (line 365) | static LRESULT CALLBACK handlePositionSubclassProc(
  function wchar_t (line 409) | const wchar_t* taskPaneHostControlProgId()

FILE: src/xlOil-COM/TaskPaneHostControl.h
  function namespace (line 4) | namespace xloil

FILE: src/xlOil-COM/WorkbookScopeFunctions.cpp
  type xloil (line 23) | namespace xloil
    type COM (line 25) | namespace COM
      function checkRegistryKeys (line 29) | bool checkRegistryKeys()
      type Writer (line 44) | struct Writer
        method write (line 50) | void write(const S& fmtStr, Args&&... args)
        method writeBreakable (line 61) | void writeBreakable(const S& fmtStr, Args&&... args)
      function writeLocalFunctionsToVBA (line 74) | void writeLocalFunctionsToVBA(
      function removeExistingXlOilVBA (line 175) | void removeExistingXlOilVBA(const wchar_t* workbookName)

FILE: src/xlOil-COM/WorkbookScopeFunctions.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOil-COM/XllContextInvoke.cpp
  type xloil (line 11) | namespace xloil
    function tryComCall (line 14) | auto tryComCall(TFunc fn) -> typename std::invoke_result<TFunc>::type
    function xloRunInXLLContext (line 29) | xloRunInXLLContext()
    function runInXllContext (line 49) | bool runInXllContext(const std::function<bool()>& f)
    function runInXllContext (line 72) | int runInXllContext(int func, ExcelObj* result, int nArgs, const Excel...

FILE: src/xlOil-COM/XllContextInvoke.h
  function namespace (line 4) | namespace Excel { struct _Application; }
  function namespace (line 5) | namespace xloil { class ExcelObj; }
  function namespace (line 7) | namespace xloil

FILE: src/xlOil-Dynamic/DynamicRegistration.cpp
  type xloil (line 32) | namespace xloil
    class PageUnlock (line 38) | class PageUnlock
      method PageUnlock (line 41) | PageUnlock(void* address, size_t size)
    class ThunkHolder (line 58) | class ThunkHolder
      method ThunkHolder (line 63) | ThunkHolder()
      method ThunkHolder (line 79) | static ThunkHolder& get() {
      method callBuildThunk (line 84) | auto callBuildThunk(
      method hookEntryPoint (line 121) | auto hookEntryPoint(const void* thunk)
    class RegisteredCallback (line 140) | class RegisteredCallback : public RegisteredWorksheetFunc
      method RegisteredCallback (line 143) | RegisteredCallback(
      method doRegister (line 162) | int doRegister() const
      method reregister (line 173) | virtual bool reregister(const std::shared_ptr<const WorksheetFuncSpe...
      method DynamicSpec (line 220) | const DynamicSpec& spec() const
    function XLOIL_EXPORT (line 230) | XLOIL_EXPORT shared_ptr<RegisteredWorksheetFunc> DynamicSpec::register...
    function TRet (line 239) | TRet invokeLambda(

FILE: src/xlOil-Dynamic/ExternalRegionAllocator.h
  function namespace (line 7) | namespace xloil

FILE: src/xlOil-Dynamic/LocalFunctions.cpp
  type xloil (line 23) | namespace xloil
    function unregisterLocalFuncs (line 33) | void unregisterLocalFuncs(LocalFunctionMap& toRemove)
    function registerLocalFuncs (line 66) | void registerLocalFuncs(
    function clearLocalFunctions (line 142) | void clearLocalFunctions(
    function isExecutingLocalFunction (line 153) | bool isExecutingLocalFunction()
  function localFunctionEntryPoint (line 160) | int __stdcall localFunctionEntryPoint(

FILE: src/xlOil-Dynamic/LocalFunctions.h
  function namespace (line 5) | namespace xloil

FILE: src/xlOil-Dynamic/PEHelper.h
  function namespace (line 5) | namespace xloil

FILE: src/xlOil-Dynamic/Thunker.cpp
  class xloper12 (line 23) | class xloper12
  type xloil (line 25) | namespace xloil {
    class ExcelObj (line 26) | class ExcelObj
    function handRoll64 (line 96) | void handRoll64(CodeHolder* code,
    function createArrayOfArgsOnStack (line 198) | void createArrayOfArgsOnStack(
    function writeFunctionBody (line 221) | void writeFunctionBody(
    function buildThunk (line 260) | void buildThunk(
    function patchThunkData (line 350) | bool patchThunkData(char* thunk, size_t thunkSize, const void* fromDat...
  function createCodeInfo (line 36) | auto createCodeInfo()
  function Error (line 57) | Error asmJitWriteCode(uint8_t* dst, CodeHolder* code, size_t& codeSize) ...
  type xloil (line 93) | namespace xloil
    class ExcelObj (line 26) | class ExcelObj
    function handRoll64 (line 96) | void handRoll64(CodeHolder* code,
    function createArrayOfArgsOnStack (line 198) | void createArrayOfArgsOnStack(
    function writeFunctionBody (line 221) | void writeFunctionBody(
    function buildThunk (line 260) | void buildThunk(
    function patchThunkData (line 350) | bool patchThunkData(char* thunk, size_t thunkSize, const void* fromDat...

FILE: src/xlOil-Dynamic/Thunker.h
  function namespace (line 3) | namespace asmjit { class CodeHolder; }
  function namespace (line 4) | namespace xloil

FILE: src/xlOil-Funcs/ExcelObjCache.cpp
  type xloil (line 6) | namespace xloil
  function XLO_FUNC_START (line 17) | XLO_FUNC_START(
  function XLO_FUNC_START (line 29) | XLO_FUNC_START(

FILE: src/xlOil-Funcs/xloHelp.cpp
  type xloil (line 6) | namespace xloil
    function XLO_FUNC_START (line 8) | XLO_FUNC_START(xloHelp(

FILE: src/xlOil-Funcs/xloLog.cpp
  type xloil (line 9) | namespace xloil
    function XLO_FUNC_START (line 11) | XLO_FUNC_START(xloLog(

FILE: src/xlOil-Funcs/xloReload.cpp
  type xloil (line 8) | namespace xloil
    function reloadPlugin (line 10) | bool reloadPlugin(const wchar_t* pluginName) noexcept
    function XLO_FUNC_START (line 31) | XLO_FUNC_START(xloReload(

FILE: src/xlOil-Funcs/xloVersion.cpp
  type xloil (line 8) | namespace xloil
    function XLO_FUNC_START (line 10) | XLO_FUNC_START(xloVersion())

FILE: src/xlOil-Loader/LoaderEntryPoint.cpp
  function writeToStartUpLog (line 36) | void writeToStartUpLog(const char* msg, bool openWindow=false) noexcept
  function FARPROC (line 51) | FARPROC WINAPI delayLoadFailureHook(unsigned dliNotify, DelayLoadInfo* p...
  function loadEnvironmentBlock (line 71) | void loadEnvironmentBlock(const toml::table& settings)
  function findAllCoreDllImports (line 84) | auto findAllCoreDllImports() noexcept
  type xlOilCoreAddin (line 105) | struct xlOilCoreAddin
    method log (line 111) | void log(const char* fmt, Args...args)
    method autoOpen (line 116) | void autoOpen()
    method autoClose (line 197) | void autoClose()
    method addInManagerInfo (line 206) | static auto addInManagerInfo()

FILE: src/xlOil-XLL/ArrayBuilder.cpp
  type xloil (line 3) | namespace xloil
    function fixStrings (line 50) | void fixStrings(ExcelObj* pStart, size_t size, wchar_t* stringData)
    function ExcelObj (line 65) | ExcelObj SequentialArrayBuilder::toExcelObj()

FILE: src/xlOil-XLL/Async.cpp
  type xloil (line 5) | namespace xloil
    function XLOIL_EXPORT (line 7) | XLOIL_EXPORT void asyncReturn(
    function XLOIL_EXPORT (line 19) | XLOIL_EXPORT bool yieldAndCheckIfEscPressed()

FILE: src/xlOil-XLL/Caller.cpp
  type xldlg_enum_struct (line 28) | struct xldlg_enum_struct
  function xldlg_enum_proc (line 38) | bool CALLBACK xldlg_enum_proc(HWND hwnd, xldlg_enum_struct *p_enum)
  function called_from_paste_fn_dlg (line 90) | bool called_from_paste_fn_dlg()
  type xloil (line 110) | namespace xloil
    function fillColumnNameCache (line 118) | auto fillColumnNameCache()
    function writeColumn (line 155) | uint8_t writeColumn(size_t colIndex, TChar buf[3])
    function writeColumnNameW (line 168) | uint8_t writeColumnNameW(size_t colIndex, wchar_t*& buf)
    function writeDecimal (line 175) | void writeDecimal(size_t value, wchar_t*& buf, size_t& bufSize)
    type WriteA1 (line 182) | struct WriteA1
    type WriteRC (line 196) | struct WriteRC
    function writeLocalAddressImpl (line 217) | uint16_t writeLocalAddressImpl(
    function writeLocalAddress (line 247) | uint16_t writeLocalAddress(
    function writeSheetAddress (line 263) | uint16_t writeSheetAddress(
    function writeAddressImpl (line 311) | int writeAddressImpl(
    function writeColumnName (line 469) | uint8_t writeColumnName(size_t colIndex, char buf[4])
    function XLOIL_EXPORT (line 474) | XLOIL_EXPORT uint16_t xlrefWriteWorkbookAddress(
    function XLOIL_EXPORT (line 490) | XLOIL_EXPORT uint16_t xlrefToAddress(
    type ColumnNameAlphabet (line 503) | struct ColumnNameAlphabet
    function skipOne (line 517) | void skipOne(const Char*& c)
    function parseColLetters (line 522) | auto parseColLetters(const wchar_t*& c, const wchar_t* last)
    function readNumberPart (line 541) | auto readNumberPart(const wchar_t*& c, const wchar_t* end)
    function readPrefixedNumber (line 551) | auto readPrefixedNumber(const wchar_t*& c, const wchar_t* end)
    function localAddressToXlRef (line 569) | bool localAddressToXlRef(const std::wstring_view& address, msxll::XLRE...
    function addressToXlRef (line 615) | bool addressToXlRef(
    function inFunctionWizard (line 627) | bool inFunctionWizard()

FILE: src/xlOil-XLL/Date.cpp
  type xloil (line 14) | namespace xloil
    function excelSerialDateToYMD (line 22) | bool excelSerialDateToYMD(int nSerialDate, int &nYear, int &nMonth, in...
    function excelSerialDatetoYMDHMS (line 58) | bool excelSerialDatetoYMDHMS(
    function excelSerialDateFromYMD (line 88) | int excelSerialDateFromYMD(int nYear, int nMonth, int nDay) noexcept
    function excelSerialDateFromYMDHMS (line 112) | double excelSerialDateFromYMDHMS(
    type wmembuf (line 124) | struct wmembuf : std::wstreambuf
      method wmembuf (line 126) | wmembuf(wchar_t const* base, size_t size)
      method str (line 130) | void str(wchar_t const* base, size_t size)
    type wimemstream (line 136) | struct wimemstream : virtual wmembuf, std::wistream
      method wimemstream (line 139) | wimemstream(wchar_t const* base, size_t size)
      method str (line 143) | void str(wchar_t const* base, size_t size)
    function stringToDateTime (line 151) | bool stringToDateTime(

FILE: src/xlOil-XLL/ExcelArray.cpp
  type xloil (line 6) | namespace xloil
    function ExcelObj (line 33) | ExcelObj ExcelArray::toExcelObj() const

FILE: src/xlOil-XLL/ExcelCall.cpp
  type xloil (line 8) | namespace xloil
    function wchar_t (line 10) | const wchar_t* xlRetCodeToString(int ret, bool checkXllContext)
    function isSafeFunction (line 38) | bool isSafeFunction(int funcNumber)
    function XLOIL_EXPORT (line 56) | XLOIL_EXPORT int callExcelRaw(
    function lookup (line 68) | int lookup(const char* fname)
    function excelFuncNumber (line 108) | int excelFuncNumber(const char* name)

FILE: src/xlOil-XLL/ExcelCallMapping.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOil-XLL/ExcelObj.cpp
  type xloil (line 24) | namespace xloil
    function wchar_t (line 30) | wchar_t* makePStringBuffer(size_t nChars)
    function wchar_t (line 38) | wchar_t* pascalWStringFromC(const char* cstr, size_t len)
    function totalStringLength (line 54) | size_t totalStringLength(const xloper12* arr, size_t nRows, size_t nCols)
    function wchar_t (line 66) | const wchar_t* enumAsWCString(CellError e)
    function wchar_t (line 82) | const wchar_t* enumAsWCString(ExcelType e)
    type Compare (line 195) | struct Compare
    type CompareEqual (line 202) | struct CompareEqual
    function doCompare (line 212) | int doCompare(
    type Const (line 526) | namespace Const
      function ExcelObj (line 547) | const ExcelObj& Missing()
      function ExcelObj (line 552) | const ExcelObj& Error(CellError e)
      function ExcelObj (line 567) | const ExcelObj& EmptyStr()
  type std (line 574) | namespace std

FILE: src/xlOil-XLL/ExcelRef.cpp
  type xloil (line 4) | namespace xloil
    function XLOIL_EXPORT (line 6) | XLOIL_EXPORT ExcelRef::ExcelRef(const ExcelObj& from)
    function XLOIL_EXPORT (line 35) | XLOIL_EXPORT ExcelRef::ExcelRef(const std::wstring_view& address)
    function XLOIL_EXPORT (line 61) | XLOIL_EXPORT ExcelRef::ExcelRef(

FILE: src/xlOil-XLL/FPArray.cpp
  type xloil (line 9) | namespace xloil
    function createArray (line 13) | auto createArray(size_t nRows, size_t nCols)
    function FPArray (line 51) | FPArray* FPArray::empty()

FILE: src/xlOil-XLL/FuncRegistry.cpp
  type xloil (line 28) | namespace xloil
    function XLOIL_EXPORT (line 30) | XLOIL_EXPORT FuncInfo::~FuncInfo()
    function XLOIL_EXPORT (line 34) | XLOIL_EXPORT bool FuncInfo::operator==(const FuncInfo& that) const
    function XLOIL_EXPORT (line 39) | XLOIL_EXPORT bool FuncInfo::isValid() const
    class FunctionRegistry (line 55) | class FunctionRegistry
      method FunctionRegistry (line 63) | FunctionRegistry()
      method FunctionRegistry (line 74) | static FunctionRegistry& get()
      method teardown (line 80) | void teardown()
      method registerWithExcel (line 90) | static int registerWithExcel(
      method throwIfPresent (line 251) | void throwIfPresent(const wstring& name) const
      method RegisteredFuncPtr (line 258) | RegisteredFuncPtr add(const shared_ptr<const WorksheetFuncSpec>& spec)
      method remove (line 266) | void remove(const wchar_t* funcName)
      method clear (line 271) | void clear()
    class RegisteredStatic (line 349) | class RegisteredStatic : public RegisteredWorksheetFunc
      method RegisteredStatic (line 352) | RegisteredStatic(const std::shared_ptr<const StaticWorksheetFunction...
    function RegisteredFuncPtr (line 376) | RegisteredFuncPtr registerFunc(const std::shared_ptr<const WorksheetFu...
    function registerFuncRaw (line 390) | int
    function teardownFunctionRegistry (line 405) | void teardownFunctionRegistry()
  type xloil (line 53) | namespace xloil
    function XLOIL_EXPORT (line 30) | XLOIL_EXPORT FuncInfo::~FuncInfo()
    function XLOIL_EXPORT (line 34) | XLOIL_EXPORT bool FuncInfo::operator==(const FuncInfo& that) const
    function XLOIL_EXPORT (line 39) | XLOIL_EXPORT bool FuncInfo::isValid() const
    class FunctionRegistry (line 55) | class FunctionRegistry
      method FunctionRegistry (line 63) | FunctionRegistry()
      method FunctionRegistry (line 74) | static FunctionRegistry& get()
      method teardown (line 80) | void teardown()
      method registerWithExcel (line 90) | static int registerWithExcel(
      method throwIfPresent (line 251) | void throwIfPresent(const wstring& name) const
      method RegisteredFuncPtr (line 258) | RegisteredFuncPtr add(const shared_ptr<const WorksheetFuncSpec>& spec)
      method remove (line 266) | void remove(const wchar_t* funcName)
      method clear (line 271) | void clear()
    class RegisteredStatic (line 349) | class RegisteredStatic : public RegisteredWorksheetFunc
      method RegisteredStatic (line 352) | RegisteredStatic(const std::shared_ptr<const StaticWorksheetFunction...
    function RegisteredFuncPtr (line 376) | RegisteredFuncPtr registerFunc(const std::shared_ptr<const WorksheetFu...
    function registerFuncRaw (line 390) | int
    function teardownFunctionRegistry (line 405) | void teardownFunctionRegistry()

FILE: src/xlOil-XLL/FuncRegistry.h
  function namespace (line 7) | namespace xloil

FILE: src/xlOil-XLL/Intellisense.cpp
  function wstring (line 30) | static wstring RegistrationInfoName(wstring xllPath)
  function wstring (line 41) | wstring findActiveIntelliServer()
  function triggerIntellisenseRefresh (line 55) | void triggerIntellisenseRefresh()
  type xloil (line 63) | namespace xloil
    function publishIntellisenseInfo (line 72) | void publishIntellisenseInfo(const std::shared_ptr<const FuncInfo>& info)
    function publishIntellisenseInfo (line 80) | void publishIntellisenseInfo(const std::vector<std::shared_ptr<const F...
    function IntellisenseRegistrationInfo (line 99) | IntellisenseRegistrationInfo(const ExcelObj& /*version*/)
    function registerIntellisenseHook (line 170) | void registerIntellisenseHook(const wchar_t* xllPath)

FILE: src/xlOil-XLL/Intellisense.h
  function namespace (line 5) | namespace xloil

FILE: src/xlOil-XLL/Log.cpp
  type xloil (line 18) | namespace xloil
    function loggerInitialise (line 20) | std::shared_ptr<spdlog::logger> loggerInitialise(
    function loggerSetFlush (line 43) | void loggerSetFlush(
    function loggerAddPopupWindowSink (line 51) | void loggerAddPopupWindowSink(
    function loggerAddRotatingFileSink (line 62) | std::wstring loggerAddRotatingFileSink(

FILE: src/xlOil-XLL/LogWindow.cpp
  type xloil (line 17) | namespace xloil
    class LogWindow (line 19) | class LogWindow : public ILogWindow
      method createWindowClass (line 32) | static auto createWindowClass(HINSTANCE hInstance, const wchar_t* wi...
      method LogWindow (line 61) | LogWindow(
      method LRESULT (line 109) | static LRESULT CALLBACK StaticWindowProc(
      method LRESULT (line 131) | LRESULT CALLBACK WindowProc(
      method setTextBoxContents (line 184) | void setTextBoxContents(const wchar_t* text, size_t numLines = 66666...
      method isOpen (line 192) | bool isOpen() const
      method appendToWindow (line 197) | void appendToWindow(const wstring& msg)
      method showWindow (line 213) | virtual void showWindow() noexcept
      method setWindowText (line 221) | virtual void setWindowText() noexcept
      method openWindow (line 227) | void openWindow() noexcept override
      method appendMessage (line 239) | void appendMessage(wstring&& msg) noexcept override
    class LogWindowThreaded (line 255) | class LogWindowThreaded : public LogWindow
      method showWindow (line 261) | virtual void showWindow() noexcept
      method setWindowText (line 269) | virtual void setWindowText() noexcept
    function createLogWindow (line 278) | shared_ptr<ILogWindow> createLogWindow(
    function loadFailureLogWindow (line 297) | void loadFailureLogWindow(HINSTANCE parent, const std::wstring_view& m...

FILE: src/xlOil-XLL/LogWindowSink.cpp
  type xloil (line 28) | namespace xloil
    type MainLogWindow (line 30) | namespace MainLogWindow
      function setLogLevelRadioGroup (line 36) | void setLogLevelRadioGroup(int base, int item)
      function setCaptureLevel (line 47) | void setCaptureLevel(spdlog::level::level_enum level)
      function setPopupLevel (line 53) | void setPopupLevel(spdlog::level::level_enum level)
      function LRESULT (line 61) | LRESULT CALLBACK MenuWindowProc(
    class LogWindowSink (line 87) | class LogWindowSink : public spdlog::sinks::base_sink<std::mutex>
      method LogWindowSink (line 92) | LogWindowSink(
      method sink_it_ (line 120) | void sink_it_(const spdlog::details::log_msg& msg) override
      method flush_ (line 135) | void flush_() override {}
      method set_formatter_ (line 137) | void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatte...
      method openWindow (line 143) | void openWindow()
    function makeLogWindowSink (line 157) | std::shared_ptr<spdlog::sinks::sink>
    function openLogWindow (line 167) | void openLogWindow()
    function setLogWindowPopupLevel (line 172) | void setLogWindowPopupLevel(const char* popupLevel)

FILE: src/xlOil-XLL/LogWindowSink.h
  function namespace (line 4) | namespace spdlog { namespace sinks { class sink; } }
  function namespace (line 6) | namespace xloil

FILE: src/xlOil-XLL/State.cpp
  type xloil (line 8) | namespace xloil
    function setDllPath (line 19) | void setDllPath(HMODULE handle)
    function getExcelVersion (line 29) | int getExcelVersion()
    function HINSTANCE (line 37) | HINSTANCE getExcelHInstance()
    function HWND (line 43) | HWND getExcelHWnd()
    function checkDynamicArraySupport (line 49) | bool checkDynamicArraySupport()
    type Environment (line 57) | namespace Environment
      function XLOIL_EXPORT (line 59) | XLOIL_EXPORT void initAppContext()
      function setCoreHandle (line 67) | void setCoreHandle(void* coreHInstance)
      function wchar_t (line 80) | const wchar_t* coreDllPath() noexcept
      function wchar_t (line 84) | const wchar_t* coreDllName() noexcept
      function XLOIL_EXPORT (line 97) | XLOIL_EXPORT const ExcelProcessInfo& excelProcess() noexcept
      function registerIntellisense (line 102) | void registerIntellisense(const wchar_t* xllPath)

FILE: src/xlOil-XLL/StaticRegister.cpp
  type xloil (line 13) | namespace xloil
    type detail (line 35) | namespace detail
      function StaticRegistrationBuilder (line 43) | StaticRegistrationBuilder& createRegistrationMemo(
      function processRegistryQueue (line 50) | std::vector<std::shared_ptr<const WorksheetFuncSpec>>
      function registerStaticFuncs (line 62) | std::vector<std::shared_ptr<const RegisteredWorksheetFunc>>

FILE: src/xlOil-XLL/Throw.cpp
  type xloil (line 5) | namespace xloil
    function XLOIL_EXPORT (line 7) | XLOIL_EXPORT void logException(
    function writeWindowsError (line 24) | std::wstring writeWindowsError()

FILE: src/xlOil-XLL/XllEvents.cpp
  type xloil (line 3) | namespace xloil
    type Event (line 5) | namespace Event

FILE: src/xlOil/Interface.cpp
  function static_pointer_cast (line 30) | std::weak_ptr<T>
  type xloil (line 41) | namespace xloil
    function registerFunc (line 129) | auto registerFunc(
    function deleteSource (line 327) | void deleteSource(const std::shared_ptr<FuncSource>& context)

FILE: src/xlOil/Loaders/AddinLoader.cpp
  type xloil (line 25) | namespace xloil
    function createContext (line 37) | auto createContext(const wchar_t* xllPath)
    function AddinContext (line 84) | AddinContext& theCoreContext()
    function createCoreAddinContext (line 95) | std::shared_ptr<AddinContext> createCoreAddinContext()
    function createAddinContext (line 102) | std::shared_ptr<AddinContext>createAddinContext(const wchar_t* pathName)
    function addinCloseXll (line 127) | void addinCloseXll(const wchar_t* xllPath)
    function teardownAddinContext (line 158) | void teardownAddinContext()

FILE: src/xlOil/Loaders/AddinLoader.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOil/Loaders/CoreEntryPoint.cpp
  type xloil (line 32) | namespace xloil
    function XLOIL_EXPORT (line 34) | XLOIL_EXPORT int coreAutoOpenHandler(const wchar_t* xllPath) noexcept
    function XLOIL_EXPORT (line 129) | XLOIL_EXPORT int coreAutoCloseHandler(const wchar_t* xllPath) noexcept
  function DllMain (line 149) | DllMain(

FILE: src/xlOil/Loaders/CoreEntryPoint.h
  function namespace (line 4) | namespace xloil

FILE: src/xlOil/Loaders/PluginLoader.cpp
  type xloil (line 34) | namespace xloil
    type LoadedPlugin (line 42) | struct LoadedPlugin
    function loadPluginForAddin (line 56) | bool loadPluginForAddin(AddinContext& context, const std::wstring& plu...
    function detachPluginForAddin (line 170) | bool detachPluginForAddin(AddinContext& context, const std::wstring& p...
    function unloadPluginImpl (line 191) | bool unloadPluginImpl(const wchar_t* name, LoadedPlugin& plugin) noexcept
    function unloadAllPlugins (line 208) | void unloadAllPlugins() noexcept
    function listPluginNames (line 215) | std::vector<std::wstring> listPluginNames()

FILE: src/xlOil/Loaders/PluginLoader.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOil/Log.cpp
  type xloil (line 3) | namespace xloil
    function XLOIL_EXPORT (line 5) | XLOIL_EXPORT spdlog::details::registry& loggerRegistry()

FILE: src/xlOilHelpers/Environment.cpp
  type xloil (line 13) | namespace xloil
    function getEnvironmentVar (line 15) | std::wstring getEnvironmentVar(const wchar_t * name)
    function getEnvironmentVar (line 24) | std::string getEnvironmentVar(const char * name)
    function setEnvironmentVar (line 33) | bool setEnvironmentVar(const wchar_t* name, const wchar_t* value)
    function setEnvironmentVar (line 42) | bool setEnvironmentVar(const char* name, const char* value)
    function expandEnvironmentStrings (line 47) | std::wstring expandEnvironmentStrings(const wchar_t* str)
    function getWindowsRegistryValue (line 100) | inline bool getWindowsRegistryValue(
    function getWindowsRegistryValue (line 133) | bool getWindowsRegistryValue(
    function getWindowsRegistryValue (line 148) | bool getWindowsRegistryValue(
    function wstring (line 166) | wstring expandWindowsRegistryStrings(const std::wstring& str)
    type Helpers (line 190) | namespace Helpers
      function writeWindowsError (line 192) | std::wstring writeWindowsError()
      function makeTempFile (line 213) | std::pair<HANDLE, std::wstring> makeTempFile()

FILE: src/xlOilHelpers/Environment.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOilHelpers/Exception.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOilHelpers/GuidUtils.cpp
  class HashAlgorithm (line 25) | class HashAlgorithm
    method HashAlgorithm (line 34) | HashAlgorithm(const wchar_t* algorithm)
    method transformBlock (line 93) | void transformBlock(BYTE* data, DWORD dataBytes)
    method computeHash (line 108) | auto computeHash()
  function SwapBytes (line 142) | void SwapBytes(BYTE* guid, int left, int right)
  function SwapByteOrder (line 150) | void SwapByteOrder(BYTE* guid)
  function Create (line 166) | void Create(GUID& result, const GUID& namespaceId, const string& name)
  type xloil (line 204) | namespace xloil
    function stableGuidFromString (line 208) | void stableGuidFromString(GUID& result, const GUID& id, const std::wst...
    function guidToWString (line 217) | std::wstring guidToWString(const GUID& guid, GuidToString mode)
    function createGuid (line 261) | bool createGuid(_GUID& guid)

FILE: src/xlOilHelpers/GuidUtils.h
  function namespace (line 6) | namespace xloil

FILE: src/xlOilHelpers/Settings.cpp
  type xloil (line 25) | namespace xloil
    type Settings (line 27) | namespace Settings
      function findStr (line 31) | auto findStr(const toml::view_node& root, const char* tag, const str...
      function findVecStr (line 35) | auto findVecStr(const toml::view_node& root, const char* tag)
      function plugins (line 45) | vector<wstring> plugins(const toml::view_node& root)
      function pluginSearchPattern (line 49) | std::wstring pluginSearchPattern(const toml::view_node& root)
      function logFilePath (line 53) | std::wstring logFilePath(const toml::table& root)
      function logLevel (line 60) | std::string logLevel(const toml::table& root)
      function logPopupLevel (line 65) | std::string logPopupLevel(const toml::table& root)
      function logFlushLevel (line 70) | std::string logFlushLevel(const toml::table& root)
      function dateFormats (line 84) | std::vector<std::wstring> dateFormats(const toml::table& root)
      function writeTableAsPairs (line 95) | void writeTableAsPairs(const TTable& table, TResult& container)
      function environmentVariables (line 106) | std::vector<std::pair<std::wstring, std::wstring>>
      function loadBeforeCore (line 124) | bool loadBeforeCore(const toml::table& root)
      function findPluginSettings (line 129) | toml::node_view<const toml::node> findPluginSettings(
    function findSettingsFile (line 146) | std::shared_ptr<const toml::table> findSettingsFile(const wchar_t* dll...

FILE: src/xlOilHelpers/Settings.h
  function namespace (line 6) | namespace toml {
  function namespace (line 13) | namespace xloil

FILE: src/xlOilHelpers/Utils.h
  function namespace (line 5) | namespace xloil

FILE: tests/AutoSheets/PythonTest.py
  class dummy (line 7) | class dummy:
    method __init__ (line 8) | def __init__(self,val):
  function list_of_stuff (line 12) | def list_of_stuff():
  function check_a_thing (line 17) | def check_a_thing(thing:dummy):
  function pySum (line 25) | def pySum(x, y, z):
  function pySumNums (line 37) | def pySumNums(x: float, y: float, a: int = 2, b: int = 3) -> float:
  function pyTest1 (line 51) | def pyTest1(x):
  function pyTestArr2d (line 67) | def pyTestArr2d(x: xlo.Array(float)) -> xlo.Array(float):
  function pyTestArrNoTrim (line 81) | def pyTestArrNoTrim(x: xlo.Array(object, trim=False)) -> xlo.Array:
  function pyTestArrNoArgs (line 89) | def pyTestArrNoArgs(x: xlo.Array):
  function pyTestArr1d (line 99) | def pyTestArr1d(x: xlo.Array(float, dims=1), multiple):
  function pyTestFastArr (line 109) | def pyTestFastArr(x: xlo.FastArray) -> xlo.FastArray:
  function pyTestList (line 117) | def pyTestList(x: list):
  class CustomObj (line 134) | class CustomObj:
    method __init__ (line 135) | def __init__(self):
  function pyTestCache (line 139) | def pyTestCache(cachedObj=None):
  function pyCacheKeys (line 149) | def pyCacheKeys():
  function pyTestToCache (line 153) | def pyTestToCache(x) -> xlo.SingleValue:
  function pyTestDate (line 169) | def pyTestDate(x: dt.datetime) -> dt.datetime:
  function pyTestDateArray (line 173) | def pyTestDateArray(y: xlo.Array(np.datetime64)) -> xlo.Array(np.datetim...
  function pyTestDateArray2 (line 177) | def pyTestDateArray2(y: xlo.Array(np.datetime64)) -> xlo.Array(np.dateti...
  function pyTestKwargs (line 196) | def pyTestKwargs(lookup: dict, **kwargs) -> dict:
  function arg_triple (line 201) | def arg_triple(x):
  function pyTestVargs (line 207) | def pyTestVargs(*args: arg_triple) -> float:
  function pyTestVargsKwargs (line 211) | def pyTestVargsKwargs(*args, **kwargs) -> float:
  function pyRunTestsNonLocal (line 226) | def pyRunTestsNonLocal(address):
  function pyPressRunTests (line 231) | def pyPressRunTests():
  function pyTestExcelCall (line 291) | def pyTestExcelCall(func, arg1:xlo.AllowRange=None, arg2:xlo.AllowRange=...
  function pyTestAppRun (line 301) | def pyTestAppRun(func, arg1:xlo.AllowRange=None, arg2:xlo.AllowRange=Non...
  function pyTestIter (line 317) | def pyTestIter(size:int, dims:int):
  function pyTestWorkbooks (line 330) | def pyTestWorkbooks():
  function pyTestCom (line 342) | def pyTestCom():
  function pyTestRange (line 352) | def pyTestRange(r: xlo.Range):
  function pyTestRangeFormula (line 375) | def pyTestRangeFormula(r: xlo.Range):
  function pyTestRangeFormula2 (line 379) | def pyTestRangeFormula2(r: xlo.Range):
  function pyTestRangeTypes (line 383) | def pyTestRangeTypes(r: xlo.Range, x, y):
  function pysys (line 391) | def pysys(attr):
  function pyThreadTest (line 403) | def pyThreadTest(x: float, y: float, a: int, b: int, u:int, v:int):
  function arg_doubler (line 424) | def arg_doubler(x):
  function pyTestCustomConv (line 430) | def pyTestCustomConv(x: arg_doubler):
  function date_row (line 434) | def date_row(x):
  function pyTestDateConv (line 448) | def pyTestDateConv(dates: date_row):
  function pyTestDFrame (line 468) | def pyTestDFrame(df: pd.DataFrame) -> xlo.Cache:
  function pyTestDFrameIndex (line 480) | def pyTestDFrameIndex(df: PDFrame(headings=True, index="Time", dates=['D...
  function pyTestFrameFetch (line 488) | def pyTestFrameFetch(df, index=None, col_name=None):
  function pyTestDFrameMultiIndex (line 507) | def pyTestDFrameMultiIndex(
  function pyTestFrameWrite (line 517) | def pyTestFrameWrite(df: pd.DataFrame) 
Condensed preview — 680 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,988K chars).
[
  {
    "path": ".gitattributes",
    "chars": 66,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n"
  },
  {
    "path": ".gitignore",
    "chars": 616,
    "preview": "# Prerequisites\n*.d\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic"
  },
  {
    "path": ".readthedocs.yml",
    "chars": 378,
    "preview": "# .readthedocs.yml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html fo"
  },
  {
    "path": ".runsettings",
    "chars": 247,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RunSettings>\n    <RunConfiguration>\n        <EnvironmentVariables>\n            <"
  },
  {
    "path": "FUNDING.yml",
    "chars": 17,
    "preview": "github: [cunnane]"
  },
  {
    "path": "LICENSE",
    "chars": 601,
    "preview": "Apache License\n\n   Copyright 2020 Steven Cunnane\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   "
  },
  {
    "path": "README.md",
    "chars": 2708,
    "preview": "\nxlOil\n=====\n\nxlOil provides framework for interacting with Excel in different programming\nlanguages. It gives a way to "
  },
  {
    "path": "Version.txt",
    "chars": 7,
    "preview": "0.22.1\n"
  },
  {
    "path": "config/xloil.ini",
    "chars": 6587,
    "preview": "#\n######## xlOil Settings #########\n#\n# This is a TOML file.\n#\n#################################\n#\n[Addin]\n\n##### Plugin"
  },
  {
    "path": "config/xloil_local.ini",
    "chars": 5087,
    "preview": "#\n######## xlOil Dev Settings ###########################################\n#\n# This is a version of xlOil.ini which is co"
  },
  {
    "path": "config/xloil_local_32.ini",
    "chars": 4915,
    "preview": "#\n######## xlOil Dev Settings ###########################################\n#\n# This is a version of xlOil.ini which is co"
  },
  {
    "path": "docs/make.cmd",
    "chars": 1955,
    "preview": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-bu"
  },
  {
    "path": "docs/requirements.txt",
    "chars": 89,
    "preview": "numpy\nnumpydoc\nautodocsumm\nsphinx-rtd-theme \ndocutils>=0.16 \nsphinx_rtd_theme\nautodocsumm"
  },
  {
    "path": "docs/source/Concepts.rst",
    "chars": 6320,
    "preview": "==============\nxlOil Concepts\n==============\n\nThis document explains some of the key xlOil concepts shared accross diffe"
  },
  {
    "path": "docs/source/Core.rst",
    "chars": 6487,
    "preview": "===========\nxlOil Core\n===========\n\nHere we tell you how to get started using xlOil and how to distribute addins\n\n.. _co"
  },
  {
    "path": "docs/source/Developer.rst",
    "chars": 1132,
    "preview": "=======================\nxlOil Development Guide\n=======================\n\nGetting started as developer\n------------------"
  },
  {
    "path": "docs/source/Events.rst",
    "chars": 6278,
    "preview": "==================\nxlOil Excel Events\n==================\n\n.. contents::\n    :local:\n\nIntroduction\n------------\n\nxlOil al"
  },
  {
    "path": "docs/source/Introduction.rst",
    "chars": 5574,
    "preview": "=====\nxlOil\n=====\n\nxlOil is a framework for linking programming languages with Excel language. \nThat is, a way to write "
  },
  {
    "path": "docs/source/conf.py",
    "chars": 5165,
    "preview": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common op"
  },
  {
    "path": "docs/source/index.rst",
    "chars": 459,
    "preview": ".. raw:: html\n\n\t<iframe src=\"https://github.com/sponsors/cunnane/card\" title=\"Sponsor xlOil\" height=\"200\" width=\"500\" st"
  },
  {
    "path": "docs/source/xlOil_Core_Functions.rst",
    "chars": 2198,
    "preview": "=========================\nxlOil Core Functions\n=========================\n\nThis page describes the worksheet functions re"
  },
  {
    "path": "docs/source/xlOil_Cpp/COM.rst",
    "chars": 1287,
    "preview": "=======================\nxlOil C++ Using COM\n=======================\n\nThe root of Excel's COM interface is `Excel.Applica"
  },
  {
    "path": "docs/source/xlOil_Cpp/CppRtd.rst",
    "chars": 2949,
    "preview": "=======================\nxlOil C++ RTD functions\n=======================\n\nIn Excel, RTD (real time data) functions are ab"
  },
  {
    "path": "docs/source/xlOil_Cpp/CustomGUI.rst",
    "chars": 2485,
    "preview": "==============================\nxlOil C++ GUI Customisation\n==============================\n\n.. contents::\n    :local:\n\nxl"
  },
  {
    "path": "docs/source/xlOil_Cpp/DynamicRegistration.rst",
    "chars": 1997,
    "preview": "==============================\nxlOil C++ Dynamic Registration\n==============================\n\nTo support registration of"
  },
  {
    "path": "docs/source/xlOil_Cpp/Events.rst",
    "chars": 436,
    "preview": "================\nxlOil C++ Events\n================\n\nSee :ref:`Events:Introduction`.\n\nExamples\n--------\n\n.. highlight:: c"
  },
  {
    "path": "docs/source/xlOil_Cpp/GettingStarted.rst",
    "chars": 5075,
    "preview": "=========================\nxlOil C++ Getting Started\n=========================\n\n\nThere are a few ways to build a C++ proj"
  },
  {
    "path": "docs/source/xlOil_Cpp/ObjectHandles.rst",
    "chars": 1225,
    "preview": "========================\nxlOil C++ Object Handles\n========================\n\nIt is often convenient to pass a pointer to "
  },
  {
    "path": "docs/source/xlOil_Cpp/SpecialArgs.rst",
    "chars": 2905,
    "preview": "======================\nXLL Special Arguments\n======================\n\nUser-defined Excel functions in XLLs usually take a"
  },
  {
    "path": "docs/source/xlOil_Cpp/StaticXLLs.rst",
    "chars": 1223,
    "preview": "======================\nxlOil C++ Static XLLs\n======================\n\nAs explained in :any:`GettingStarted`, it is possib"
  },
  {
    "path": "docs/source/xlOil_Cpp/index.rst",
    "chars": 5353,
    "preview": "======================\nxlOil C++\n======================\n\nxlOil C++ provides a layer above the `XLL API <https://docs.mic"
  },
  {
    "path": "docs/source/xlOil_Python/BuiltInUDFs.rst",
    "chars": 2281,
    "preview": "==================================\nxlOil Built-in Worksheet Functions\n==================================\n\nThe the import"
  },
  {
    "path": "docs/source/xlOil_Python/Concepts.rst",
    "chars": 4386,
    "preview": "=========================\nxlOil Python Concepts\n=========================\n\n.. contents::\n    :local:\n\n\nWorkbook Modules\n"
  },
  {
    "path": "docs/source/xlOil_Python/CustomGUI.rst",
    "chars": 11655,
    "preview": "==============================\nxlOil Python GUI Customisation\n==============================\n\n.. contents::\n    :local:\n"
  },
  {
    "path": "docs/source/xlOil_Python/Debugging.rst",
    "chars": 1943,
    "preview": "==============================\nxlOil Python Debugging\n==============================\n\nOnly python debuggers capable of h"
  },
  {
    "path": "docs/source/xlOil_Python/DistributingAddins.rst",
    "chars": 3780,
    "preview": "=======================================\nxlOil Python Distribution and Packaging\n=======================================\n"
  },
  {
    "path": "docs/source/xlOil_Python/Dynamic.rst",
    "chars": 3145,
    "preview": "========================================\nxlOil Python Dynamic Runtime Interaction\n======================================"
  },
  {
    "path": "docs/source/xlOil_Python/Example.rst",
    "chars": 247,
    "preview": "======================\nxlOil Python Examples\n======================\n\nThis is code for the xlOil python test spreadsheet."
  },
  {
    "path": "docs/source/xlOil_Python/ExampleGUI.rst",
    "chars": 268,
    "preview": "=========================\nxlOil Python GUI Examples\n=========================\n\nThis is code for the xlOil python test sp"
  },
  {
    "path": "docs/source/xlOil_Python/ExampleRTD.rst",
    "chars": 271,
    "preview": "=========================\nxlOil Python RTD Examples\n=========================\n\nThis is code for the xlOil python test sp"
  },
  {
    "path": "docs/source/xlOil_Python/ExcelApplication.rst",
    "chars": 13338,
    "preview": "==========================================\nxlOil Python: The Excel.Application object\n=================================="
  },
  {
    "path": "docs/source/xlOil_Python/ExternalPackages.rst",
    "chars": 3752,
    "preview": "=============================\nxlOil Python Package Support\n=============================\n\nxlOil has built-in converters "
  },
  {
    "path": "docs/source/xlOil_Python/FAQ.rst",
    "chars": 4474,
    "preview": "======================\nxlOil Python Questions\n======================\n\n.. contents::\n    :local:\n\n\nImportError: Typelib d"
  },
  {
    "path": "docs/source/xlOil_Python/Functions.rst",
    "chars": 6588,
    "preview": "==================================\nxlOil Python Registering Functions\n==================================\n\n.. contents::\n"
  },
  {
    "path": "docs/source/xlOil_Python/GettingStarted.rst",
    "chars": 5067,
    "preview": "=========================\nxlOil Python Introduction\n=========================\n\n.. contents::\n    :local:\n\nIntroduction\n-"
  },
  {
    "path": "docs/source/xlOil_Python/Jupyter.rst",
    "chars": 4126,
    "preview": "=========================\nxlOil Jupyter Interaction\n=========================\n\n.. contents::\n    :local:\n    \nIntroducti"
  },
  {
    "path": "docs/source/xlOil_Python/ModuleReference.rst",
    "chars": 5784,
    "preview": "=================================\nxlOil Python Module Reference\n=================================\n\n.. contents::\n    :lo"
  },
  {
    "path": "docs/source/xlOil_Python/Rtd.rst",
    "chars": 6206,
    "preview": "======================\nxlOil Python Async/Rtd\n======================\n\nIntroduction\n------------\n\nRTD (real time data) fu"
  },
  {
    "path": "docs/source/xlOil_Python/TypeConversion.rst",
    "chars": 14703,
    "preview": "============================\nxlOil Python Type Conversion\n============================\n\n.. contents::\n    :local:\n\n\nArgu"
  },
  {
    "path": "docs/source/xlOil_Python/index.rst",
    "chars": 370,
    "preview": "============\nxlOil Python\n============\n\n.. toctree::\n    :maxdepth: 4\n    :caption: Contents\n\n    GettingStarted\n    Con"
  },
  {
    "path": "docs/source/xlOil_SQL/index.rst",
    "chars": 5204,
    "preview": "=========\nxlOil SQL\n=========\n\nThe SQL plugin uses sqlite3 to provide functions which query Excel arrays (or\nranges) as "
  },
  {
    "path": "docs/source/xlOil_Utils.rst",
    "chars": 6731,
    "preview": "===========\nxlOil Utils\n===========\n\nThe Utils plugin contains general purpose tools to manipulate data,\nparticularly ar"
  },
  {
    "path": "docs/source/xloil.doxyfile",
    "chars": 112860,
    "preview": "# Doxyfile 1.8.18\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org)"
  },
  {
    "path": "docs/xlOil-Sphinx.code-workspace",
    "chars": 43,
    "preview": "{\n\t\"folders\": [\n\t\t{\n\t\t\t\"path\": \".\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "external/Excel2013SDK/INCLUDE/XLCALL.H",
    "chars": 41681,
    "preview": "/*\n**  Microsoft Excel Developer's Toolkit\n**  Version 15.0\n**\n**  File:           INCLUDE\\XLCALL.H\n**  Description:    "
  },
  {
    "path": "external/Excel2013SDK/SRC/ReadMe.txt",
    "chars": 1360,
    "preview": "Changes to XLCALL.CPP in the Microsoft Excel 2013 XLL Software Development Kit (SDK)\n==================================="
  },
  {
    "path": "external/Excel2013SDK/SRC/XLCALL.CPP",
    "chars": 2461,
    "preview": "/*\n**  Microsoft Excel Developer's Toolkit\n**  Version 14.0\n**\n**  File:           SRC\\XLCALL.CPP\n**  Description:    Co"
  },
  {
    "path": "external/Sources.txt",
    "chars": 282,
    "preview": "Asmjit\n------\n\nBranch: master (25 Oct 2019)\nSource: https://github.com/asmjit/asmjit/commit/ac77dfcd75f043e2fe317133a971"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/add.hpp",
    "chars": 1858,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/dec.hpp",
    "chars": 8323,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/detail/div_base.hpp",
    "chars": 2568,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/div.hpp",
    "chars": 1274,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/inc.hpp",
    "chars": 8297,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/mod.hpp",
    "chars": 1274,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/mul.hpp",
    "chars": 2062,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic/sub.hpp",
    "chars": 1808,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/arithmetic.hpp",
    "chars": 803,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/data.hpp",
    "chars": 1158,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/detail/get_data.hpp",
    "chars": 2164,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/elem.hpp",
    "chars": 1306,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/enum.hpp",
    "chars": 1619,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/insert.hpp",
    "chars": 3089,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/pop_back.hpp",
    "chars": 1732,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/pop_front.hpp",
    "chars": 1811,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/push_back.hpp",
    "chars": 1729,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/push_front.hpp",
    "chars": 1739,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/remove.hpp",
    "chars": 2906,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/replace.hpp",
    "chars": 2725,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/reverse.hpp",
    "chars": 1378,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/size.hpp",
    "chars": 1158,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/to_list.hpp",
    "chars": 2012,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/to_seq.hpp",
    "chars": 1977,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array/to_tuple.hpp",
    "chars": 1298,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/array.hpp",
    "chars": 1600,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/assert_msg.hpp",
    "chars": 748,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/cat.hpp",
    "chars": 1018,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comma.hpp",
    "chars": 743,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comma_if.hpp",
    "chars": 752,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison/equal.hpp",
    "chars": 1006,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison/greater.hpp",
    "chars": 1141,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison/greater_equal.hpp",
    "chars": 1243,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison/less.hpp",
    "chars": 1965,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison/less_equal.hpp",
    "chars": 1275,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison/not_equal.hpp",
    "chars": 64923,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/comparison.hpp",
    "chars": 783,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/config/config.hpp",
    "chars": 5043,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/config/limits.hpp",
    "chars": 878,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/deduce_d.hpp",
    "chars": 912,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/detail/dmc/while.hpp",
    "chars": 65769,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/detail/edg/while.hpp",
    "chars": 48574,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/detail/msvc/while.hpp",
    "chars": 31126,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/detail/while.hpp",
    "chars": 67561,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/expr_if.hpp",
    "chars": 956,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/expr_iif.hpp",
    "chars": 1224,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/if.hpp",
    "chars": 906,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/iif.hpp",
    "chars": 1325,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control/while.hpp",
    "chars": 17561,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/control.hpp",
    "chars": 991,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/debug/assert.hpp",
    "chars": 1374,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/debug/error.hpp",
    "chars": 1574,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/debug/line.hpp",
    "chars": 1686,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/debug.hpp",
    "chars": 784,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/dec.hpp",
    "chars": 736,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/auto_rec.hpp",
    "chars": 26136,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/check.hpp",
    "chars": 2183,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/dmc/auto_rec.hpp",
    "chars": 26466,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/is_binary.hpp",
    "chars": 1241,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/is_nullary.hpp",
    "chars": 1248,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/is_unary.hpp",
    "chars": 1227,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/null.hpp",
    "chars": 721,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/detail/split.hpp",
    "chars": 1529,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/empty.hpp",
    "chars": 742,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/enum.hpp",
    "chars": 739,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/enum_params.hpp",
    "chars": 760,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/enum_params_with_a_default.hpp",
    "chars": 805,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/enum_params_with_defaults.hpp",
    "chars": 802,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/enum_shifted.hpp",
    "chars": 763,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/enum_shifted_params.hpp",
    "chars": 784,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/expand.hpp",
    "chars": 745,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/expr_if.hpp",
    "chars": 745,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/apply.hpp",
    "chars": 1475,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/detail/is_empty.hpp",
    "chars": 1719,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/empty.hpp",
    "chars": 567,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/expand.hpp",
    "chars": 842,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/identity.hpp",
    "chars": 759,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/intercept.hpp",
    "chars": 8913,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/is_1.hpp",
    "chars": 946,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/is_empty.hpp",
    "chars": 2544,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/is_empty_or_1.hpp",
    "chars": 1205,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/is_empty_variadic.hpp",
    "chars": 1780,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities/overload.hpp",
    "chars": 1150,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/facilities.hpp",
    "chars": 1204,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/for.hpp",
    "chars": 736,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/identity.hpp",
    "chars": 751,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/if.hpp",
    "chars": 730,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/inc.hpp",
    "chars": 736,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iterate.hpp",
    "chars": 747,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/lower1.hpp",
    "chars": 4079,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/lower2.hpp",
    "chars": 4079,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/lower3.hpp",
    "chars": 4079,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/lower4.hpp",
    "chars": 4079,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/lower5.hpp",
    "chars": 4079,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/upper1.hpp",
    "chars": 4131,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/upper2.hpp",
    "chars": 4131,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/upper3.hpp",
    "chars": 4131,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/upper4.hpp",
    "chars": 4131,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/bounds/upper5.hpp",
    "chars": 4131,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/finish.hpp",
    "chars": 3617,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/forward1.hpp",
    "chars": 54776,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/forward2.hpp",
    "chars": 54709,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/forward3.hpp",
    "chars": 54709,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/forward4.hpp",
    "chars": 54709,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/forward5.hpp",
    "chars": 54709,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/reverse1.hpp",
    "chars": 48331,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/reverse2.hpp",
    "chars": 48331,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/reverse3.hpp",
    "chars": 48331,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/reverse4.hpp",
    "chars": 48331,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/iter/reverse5.hpp",
    "chars": 48331,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/local.hpp",
    "chars": 20769,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/rlocal.hpp",
    "chars": 17087,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/self.hpp",
    "chars": 833,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/detail/start.hpp",
    "chars": 3617,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/iterate.hpp",
    "chars": 3706,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/local.hpp",
    "chars": 1129,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration/self.hpp",
    "chars": 820,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/iteration.hpp",
    "chars": 852,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/library.hpp",
    "chars": 1747,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/limits.hpp",
    "chars": 741,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/adt.hpp",
    "chars": 2171,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/append.hpp",
    "chars": 1359,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/at.hpp",
    "chars": 1355,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/cat.hpp",
    "chars": 1586,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/detail/dmc/fold_left.hpp",
    "chars": 68186,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/detail/edg/fold_left.hpp",
    "chars": 84875,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/detail/edg/fold_right.hpp",
    "chars": 113960,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/detail/fold_left.hpp",
    "chars": 62809,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/detail/fold_right.hpp",
    "chars": 29437,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/enum.hpp",
    "chars": 1460,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/filter.hpp",
    "chars": 2538,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/first_n.hpp",
    "chars": 2684,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/fold_left.hpp",
    "chars": 21383,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/fold_right.hpp",
    "chars": 1326,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/for_each.hpp",
    "chars": 2089,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/for_each_i.hpp",
    "chars": 3289,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/for_each_product.hpp",
    "chars": 13798,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/rest_n.hpp",
    "chars": 2350,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/reverse.hpp",
    "chars": 1427,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/size.hpp",
    "chars": 2468,
    "preview": "# /* Copyright (C) 2001\n#  * Housemarque Oy\n#  * http://www.housemarque.com\n#  *\n#  * Distributed under the Boost Softwa"
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/to_array.hpp",
    "chars": 25793,
    "preview": "# /* **************************************************************************\n#  *                                    "
  },
  {
    "path": "external/boost-1.67/boost/preprocessor/list/to_seq.hpp",
    "chars": 1196,
    "preview": "# /* **************************************************************************\n#  *                                    "
  }
]

// ... and 480 more files (download for full content)

About this extraction

This page contains the full source code of the cunnane/xloil GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 680 files (4.6 MB), approximately 1.2M tokens, and a symbol index with 2704 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!