Excel Add-in
The Excel add-in APIs integrate Datatailr workflows with spreadsheet-based workflows.
Related API pages
Quick start: deploy your first Excel add-in
Step 1: write your Excel add-in
In this example, we will create a simple Excel Add-in that implements some basic functionality.
# my_addin.py
import datatailr.excel
addin = datatailr.excel.Addin(
"MyAddin",
"This is a very cool simple Excel addin!",
)
@addin.expose(description="Adds 2 numbers", help="To add 2 numbers give them to the function")
def add(a: int, b: int) -> float:
return a + b
@addin.expose(description="Subtracts 2 numbers", help="To subtract 2 numbers give them to the function")
def sub(a: int, b: int) -> float:
return a - b
def __excel_main__(port, debug=False):
addin.run(port=port)
Step 2: deploy the Excel add-in
Your Excel Add-in deployment can be defined as a datatailr.scheduler.Job
object:
# my_addin_deployment.py
from datatailr import ExcelAddin
from my_addin import __excel_main__
addin = ExcelAddin(
name="my_addin",
entrypoint=__excel_main__,
)
addin.save()
addin.start()
Running the code above will deploy your Excel Add-in.
Developing and deploying Excel add-ins
Excel add-ins on Datatailr are created automatically from Python modules. Any fully type-annotated functions you expose will be callable from Excel once the add-in is sideloaded.
Develop an Excel add-in
from datatailr.excel import Addin, Queue
Create the add-in
my_addin = Addin("MyAddin", "This is a very cool simple Excel addin!")
Addin(...) parameters
- name: str - Display name in Excel.
- description: str - Shown in the taskpane.
- version: str (optional), default value "1.0.0" - Semantic version.
- min_update_interval: float (optional), default value 0.5 - exists for compatibility with addins defined for v1. Doesn't do anything.
Expose functions
Decorate fully annotated functions with addin.expose(...).
import time
from datatailr.excel import Queue
@addin.expose(description="Add two numbers", help="Returns a + b")
def add(a: float, b: float) -> float:
return a + b
addin.expose(...) parameters
- description: str - Shown in the taskpane next to the function name.
- help: str - Tooltip shown in the formula bar.
- volatile: bool = False - Mark as volatile (Excel may recalc more often).
- streaming: bool = False - If True, the function's first argument must be
queue: datatailr.excel.Queue. The return value is ignored; values are sent viaqueue.push(...). - progressbar: bool = False - When True, the function becomes a streaming function that auto-streams a progress bar until the final result is ready.
Streaming functions
import time
from datatailr.excel import Queue
@addin.expose(
description="Simple numeric ticker",
help="Streams an increasing number",
streaming=True,
)
def int_ticker_N(queue: Queue, start: int, N: int) -> int:
value = start
for _ in range(N):
queue.push(value) # streamed to Excel immediately
value += 1
time.sleep(1)
# return value is ignored for streaming functions
Queue API
- Queue.push(value: Any) -> None - Streams a value to Excel. Type should match the function's annotated return type.
- Queue.error(message: str) -> None - Sends an error for the current invocation.
Working with matrices
Excel custom functions may accept and return 2-D lists ("matrices"). Elements may be mixed-type (strings, numbers, etc). Even 1-D vectors must still be represented as a 2-D nested list.
def print_row() -> list:
return [[1, 2, 3]]
def print_column() -> list:
return [[1], [2], [3]]
def print_matrix() -> list:
return [[1, 2], [3, 4]]
Optional parameters
If you define a default for a parameter, Excel treats it as optional. For list-like parameters, follow standard Python practice (avoid mutable defaults):
def foo(x: list | None = None) -> ...:
if x is None:
...
Deploy an Excel add-in
Assume the add-in lives in my_module/my_addin.py:
import datatailr.excel
addin = datatailr.excel.Addin(
"MyAddin",
"This is a very cool simple Excel addin as always!",
version="1.0.0",
)
@addin.expose(description="Adds 2 numbers", help="Provide two numbers")
def add(a: int, b: int) -> int:
return a + b
Deploying in the IDE (for development)
Run via the IDE proxy for quick testing:
if __name__ == "__main__":
addin.run(12345, 12346, ide=True)
Addin.run(...) parameters
- port: int - HTTP port for the download page and non-streaming calls.
- ws_port: int - WebSocket port for streaming functions.
- ide: bool = True - Must be True when running inside the IDE. Using False here in the IDE will produce a broken add-in.
Deploying to Datatailr
Create a Job with JobType.EXCEL:
from my_module.my_addin import __excel_main__
from datatailr.scheduler import Job, JobType, EntryPoint, Resources
job = Job(
"my_addin",
python_version="3.10",
resources=Resources(memory="512m", cpu=1.0),
entrypoint=EntryPoint(type=JobType.EXCEL, func=__excel_main__),
python_requirements="numpy",
)
job.save()
This will deploy the add-in and make it available with the rest of the deployed applications and add-ins in the dev apps section.
Note: In EntryPoint, you pass a function name (e.g., __excel_main__) to carry
the module reference; the function itself is not executed for Excel jobs.