# Async API

To interact with the Excel object model, scripts and notebooks let you use the same syntax as the classic, locally installed xlwings (*sync API*). This often works fine, but because xlwings Lite runs in a browser, it talks to Excel differently. That difference creates three limitations, and the *async API* gives you a method to work around each one:

1. **All cell values are loaded up front.** Getting a sync book (`xw.books.active` for notebooks or using the `xw.Book` type hint in scripts) fetches all values from the entire workbook, which can be slow and may cause the browser to run out of memory for large workbooks.

   → [`await myrange.get_value()`]() with an async `Book` reads only the values you ask for.
2. **Writes are queued.** When you assign a value to a range, for example, it’s only applied at the end of a notebook cell or when a script finishes, not immediately.

   → [`await book.flush()`]() applies queued writes immediately.
3. **Reads can be outdated.** Anything you read via the sync API reflects the workbook state from the start of the notebook cell or the start of the script.

   → [`await book.load()`]() refreshes everything.

The following sections cover each method in detail.

## `get_value()`: reading values on demand

To read values on demand:

- Use an async `Book` object, which disables the loading of all values up front:
  - Notebook: `await xw.books.get_active()`
  - Script: `xw.BookAsync` (type hint)
- Use `await myrange.get_value()` instead of `myrange.value` to load the values live.

In the following example, only the value of a single cell is loaded, no matter how big the workbook is:

### Notebook

```python
# %%
import xlwings as xw

book = await xw.books.get_active()  # sync version: book = xw.books.active
myrange = book.sheets[0]["A1"]
await myrange.get_value()  # sync version: myrange.value
```

### Script

```python
import xlwings as xw
from xlwings import script

@script
async def my_script(book: xw.BookAsync):  # sync version: def my_script(book: xw.Book)
    myrange = book.sheets[0]["A1"]
    await myrange.get_value()  # sync version: myrange.value
```

#### NOTE
- Notebooks let you `await` at the top level without requiring an `async def`.
- Scripts must use `await` inside of an `async def`.

`get_value()` respects the same converters and options as `value`, so you can, for example, read a range directly into a pandas DataFrame:

```python
import pandas as pd

df = await (
    book.sheets["Sheet1"]["A1:C10"]
    .options(pd.DataFrame, index=False)
    .get_value()
)
```

While `await get_value()` technically also works with a sync book to get the current values, a sync book still loads the whole workbook up front.

## `flush()`: writing immediately

When writing to a workbook, xlwings Lite queues every action and applies them in order at the end of a notebook cell or when the script finishes. If you need to flush queued writes to Excel *before* the automatic flush happens, call `await book.flush()`:

### Notebook

```python
# %%
book = await xw.books.get_active()
book.sheets[0]["A1"].value = "Hello xlwings!"
await book.flush()
await book.sheets[0]["A1"].get_value()

# Output
# 'Hello xlwings!'
```

### Script

```python
import xlwings as xw
from xlwings import script

@script
async def my_script(book: xw.BookAsync):
    book.sheets[0]["A1"].value = "Hello xlwings!"
    await book.flush()
    print(await book.sheets[0]["A1"].get_value())
    # prints 'Hello xlwings!'
```

Here are some common scenarios where you need to use `await book.flush()`:

- After writing a value to an Excel cell, call `await book.flush()` before reading that value—or a dependent cell—within the same notebook cell or script (example above).
- If you want to see the printed output immediately in the Output pane, use `await book.flush()` after `print()`.
- If you call a method that writes to the file system, such as `mysheet["A1:D10"].to_png("/data/range.png")`, call `await book.flush()` before accessing the file in the same notebook cell or script.

## `load()`: reading the current workbook state

Before running a script or a notebook cell, xlwings Lite automatically runs `await book.load()`, so you rarely need to call it explicitly. To refresh the workbook state midway through a notebook cell or script, use `await book.load()` or `await mysheet.load()`:

### Notebook

```python
# %%
book = await xw.books.get_active()
sheet1 = book.sheets[0]
await book.load()  # or: await sheet1.load()
sheet1.tables
```

### Script

```python
import xlwings as xw
from xlwings import script

@script
async def my_script(book: xw.BookAsync):
    sheet1 = book.sheets[0]
    await book.load()  # or: await sheet1.load()
    sheet1.tables
```

A few things to keep in mind:

- On an async book, `await book.load()` fetches everything *except* values since you should access values via `await myrange.get_value()`. On a sync book, `await book.load()` *includes* values. If you want to exclude values on a sync book, use `await book.load(values=False)`.
- Calling `load()` on a sheet object rather than the book loads only that sheet instead of the whole book, so it’s slightly more efficient.
