Notebooks

The notebook.py tab works like a Jupyter notebook: you split your code into cells and run them individually, in groups, or all at once, keeping the results and variables around between runs. It’s the ideal place to explore data interactively or prototype code before moving it into a custom function or script.

Unlike Jupyter notebooks, xlwings Lite notebooks are regular Python files, and code cells are defined using a # %% comment. This is the same mechanism used by the Spyder IDE or the Python Interactive window in VS Code.

Cells

Cells are separated by a comment that starts with # %%. Anything before the first # %% is treated as the first cell. You can optionally add a title, which then shows up in the output pane.

_images/notebook_cell.png

The cell state is shown to the left of the line numbers:

The cell is currently running.
The cell ran successfully.
The cell raised an error.

Unlike Jupyter notebooks, the numbers ([1], [2], etc.) indicate each cell’s current position and don’t increase with every run. They may change when you insert, remove, or reorder cells. This allows you to easily connect the output from the Output pane with the respective cell.

Like Jupyter, the notebook automatically displays the value of the last expression in a cell. In the screenshot above, a cell whose last line is just df shows the DataFrame in the output pane—you don’t need to call print().

All cells share one Python namespace, so variables, imports, and functions defined in one cell are available in later cells, just as they are in Jupyter notebooks.

Running cells

You can run cells via the run button, cell actions, or keyboard shortcuts:

Run button

The dropdown lets you choose what the button does:

  • Run Cell: run the active cell.

  • Run Cell & Advance: run the active cell, then move the cursor to the next cell.

  • Reset & Run All: reset the notebook session and run every cell from the top.

There’s also a Replace output toggle that controls whether running a cell replaces the previous output (default) or appends the new output below it. Reset & Run All always clears the previous output because it resets the notebook session.

Cell actions

Each cell shows a set of clickable links above it:

  • ▶ Run Cell: run just this cell.

  • ▶▶ Run Cell And Below: run this cell and every cell below it.

  • + Insert Cell: add a new empty # %% cell right after this one.

Keyboard shortcuts

The following keyboard shortcuts are available:

  • Shift + Enter: run the current cell and advance, i.e., move the cursor to the next cell.

  • Ctrl + Enter (Windows) / Cmd + Enter (macOS): run the current cell without advancing.

  • F5: run the action currently selected in the Run button.

Plots

Matplotlib and Plotly figures are displayed automatically:

Matplotlib

# %%
import matplotlib.pyplot as plt

plt.plot([1, 2, 3, 4, 5])

or, using the object-oriented interface:

# %%
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4, 5])

Plotly

# %%
import plotly.express as px

df = px.data.iris()
px.scatter(df, x="sepal_width", y="sepal_length", color="species")

or

# %%
import plotly.express as px

df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species")
fig.show()

Top-level async/await support

Notebooks allow you to use await directly at the top level of a cell; you don’t need to wrap your code in an async function as required by regular Python files (e.g., main.py):

# %%
import httpx  # add httpx to requirements.txt

async with httpx.AsyncClient() as client:
    response = await client.get("https://api.github.com/repos/xlwings/xlwings")
response.json()["stargazers_count"]

Working with the Excel object model

There are two ways to get the active workbook:

  • The classic, sync API: The whole workbook is loaded the moment you call xw.books.active. With large worksheets, this can get slow or even run out of memory, and values can be outdated by the time you call myrange.value:

    import xlwings as xw
    
    book = xw.books.active
    data = book.sheets[0]["A1:B2"].value
    

    data represents the state of the Excel values when you called xw.books.active.

  • The lazy, async API: Cell values are loaded on demand. This is faster for large workbooks as only the specified data is loaded. On top of that, the values always correspond to the current state in Excel:

    import xlwings as xw
    
    book = await xw.books.get_active()
    data = await book.sheets[0]["A1:B2"].get_value()
    

    data represents the state of the Excel values when you called get_value().

Writes to Excel are flushed automatically at the end of each cell, so you’ll see changes appear in the sheet as soon as the cell finishes running. If you need to flush data mid-cell, you can do it explicitly:

await book.flush()

Migrating from Python in Excel to xlwings Lite

You can migrate formulas from Microsoft’s Python in Excel by going to xlwings Lite menu > Import PiE (active sheet). This scans the active sheet for =PY() formulas, converts them into notebook cells, and appends them to the existing notebook.py file.

Limitations

You currently can only have a single notebook, which has to be called notebook.py.