Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"MD025": false,
"MD033": {
"allowed_elements": ["kbd"]
}
}
29 changes: 25 additions & 4 deletions docs/excel/custom-functions-batching.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
ms.date: 09/09/2022
ms.date: 09/19/2025
description: Batch custom functions together to reduce network calls to a remote service.
title: Batching custom function calls for a remote service
ms.topic: best-practice
Expand All @@ -8,9 +8,18 @@ ms.localizationpriority: medium

# Batch custom function calls for a remote service

If your custom functions call a remote service you can use a batching pattern to reduce the number of network calls to the remote service. To reduce network round trips you batch all the calls into a single call to the web service. This is ideal when the spreadsheet is recalculated.
Use batching to group calls to a remote service into one network request. This cuts down the number of trips to your remote service and helps the worksheet finish recalculating faster.

For example, if someone used your custom function in 100 cells in a spreadsheet, and then recalculated the spreadsheet, your custom function would run 100 times and make 100 network calls. By using a batching pattern, the calls can be combined to make all 100 calculations in a single network call.
## Key points
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After reading through all these bullet points, it really feels clunky. Like if this is a summary at the end, perhaps that makes more sense. I feel like the original text (will paste below) is better and maybe just move it sooner if the goal is to provide an executive summary.

To set up batching for your custom functions you'll need to write three main sections of code.

A push operation to add a new operation to the batch of calls each time Excel calls your custom function.
A function to make the remote request when the batch is ready.
Server code to respond to the batch request, calculate all of the operation results, and return the values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the great feedback! I rewrote this section and reorganized the first few paragraphs of the article to incorporate your suggestions. Does this seem more accurate?


- Several calls can be combined into one request that runs every short interval (for example, about 100 ms).
- Each function call gets a `Promise` that is resolved when the single combined response returns.
- Shorter intervals show results sooner but send more requests. Slightly longer intervals reduce traffic.
- Map errors back to the specific call so one failure does not hide others.
- Set a reasonable maximum number of items per batch (for example, 500) to keep the request size safe.
- Cache recent results if many calls use the same inputs.

Example scenario: 100 cells call the custom function. Instead of 100 network requests, you send one request that lists all 100 operations and then return 100 answers.

[!include[Excel custom functions note](../includes/excel-custom-functions-note.md)]

Expand Down Expand Up @@ -176,7 +185,7 @@ Add the following code to your **functions.js** or **functions.ts** file.

```javascript
// This function simulates the work of a remote service. Because each service
// differs, you will need to modify this function appropriately to work with the service you are using.
// differs, you will need to modify this function appropriately to work with the service you are using.
// This function takes a batch of argument sets and returns a promise that may contain a batch of values.
// NOTE: When implementing this function on a server, also apply an appropriate authentication mechanism
// to ensure only the correct callers can access it.
Expand Down Expand Up @@ -232,6 +241,18 @@ To modify the `_fetchFromRemoteService` function to run in your live remote serv
- Apply an appropriate authentication mechanism. Ensure that only the correct callers can access the function.
- Place the code in the remote service.

## When to avoid batching

Batching adds a small delay and some extra code. Avoid batching in the following scenarios.

| Scenario | Negative impact of batching | Recommendation |
|----------|-------------------|----------------|
| Single or very few calls | Extra wait for timer | Call service directly if list is still empty |
| Very large input data per call | Request might get too large | Limit size or send those calls alone |
| Some calls are much slower than others | One slow call delays faster ones | Group slow types separately |
| Need near‑instant result (less than 50 ms) | Timer adds delay | Use a shorter timer or skip batching |
| Server already combines work | No benefit | Skip batching on the client |

## Next steps

Learn about [the various parameters](custom-functions-parameter-options.md) you can use in your custom functions. Or review the basics behind making [a web call through a custom function](custom-functions-web-reqs.md).
Expand Down
26 changes: 13 additions & 13 deletions docs/excel/custom-functions-debugging.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: Custom functions debugging in a non-shared runtime
description: Learn how to debug your Excel custom functions that don't use a shared runtime.
ms.date: 01/03/2024
description: Debug Excel custom functions that don't use a shared runtime.
ms.date: 09/19/2025
ms.topic: troubleshooting
ms.localizationpriority: medium
---

# Custom functions debugging in a non-shared runtime

This article discusses debugging only for custom functions that **don't use a [shared runtime](../testing/runtimes.md#shared-runtime)**. To debug custom functions add-ins that use a shared runtime, see [Overview of debugging Office Add-ins](../testing/debug-add-ins-overview.md).
This article covers debugging only for custom functions that **don't use a [shared runtime](../testing/runtimes.md#shared-runtime)**. For shared runtime scenarios, see [Overview of debugging Office Add-ins](../testing/debug-add-ins-overview.md).

[!include[Excel custom functions note](../includes/excel-custom-functions-note.md)]

Expand All @@ -31,13 +31,13 @@ The process of debugging a custom function for add-ins that don't use a shared r

## Use the browser developer tools to debug custom functions in Excel on the web

You can use the browser developer tools to debug custom functions that don't use a shared runtime in Excel on the web. The following steps work for both Windows and macOS.
You can use the browser developer tools to debug custom functions that don't use a shared runtime in Excel on the web. The following steps work for Windows and macOS.

### Run your add-in from Visual Studio Code

1. Open your custom functions root project folder in [Visual Studio Code (VS Code)](https://code.visualstudio.com/).
1. Choose **Terminal** > **Run Task** and type or select **Watch**. This will monitor and rebuild for any file changes.
1. Choose **Terminal** > **Run Task** and type or select **Dev Server**.
1. Choose **Terminal** > **Run Task** and run **Watch**. This will monitor and rebuild for any file changes.
1. Choose **Terminal** > **Run Task** and run **Dev Server**.

### Sideload your add-in

Expand All @@ -54,18 +54,18 @@ You can use the browser developer tools to debug custom functions that don't use

### Start debugging

1. Open developer tools in the browser. For Chrome and most browsers F12 will open the developer tools.
1. Open developer tools in the browser. For Chrome and most browsers F12 opens the developer tools.
1. In developer tools, open your source code script file using <kbd>Cmd</kbd>+<kbd>P</kbd> or <kbd>Ctrl</kbd>+<kbd>P</kbd> (**functions.js** or **functions.ts**).
1. [Set a breakpoint](https://code.visualstudio.com/Docs/editor/debugging#_breakpoints) in the custom function source code.

If you need to change the code you can make edits in VS Code and save the changes. Refresh the browser to see the changes loaded.
Edit code in VS Code, save, then refresh the workbook page to load updates.

## Use the command line tools to debug

If you aren't using VS Code, you can use the command line (such as bash, or PowerShell) to run your add-in. You'll need to use the browser developer tools to debug your code in Excel on the web. You cannot debug the desktop version of Excel using the command line.
If you aren't using VS Code, you can use the command line such as bash or PowerShell to run your add-in. Use the browser developer tools to debug your code in Excel on the web. You cannot debug the desktop version of Excel from the command line.

1. From the command line run `npm run watch` to watch for and rebuild when code changes occur.
1. Open a second command line window (the first one will be blocked while running the watch.)
1. Open a second command line window (the first one is busy while running the watch.)

1. If you want to start your add-in in the desktop version of Excel and the "scripts" section of the project's package.json file has a "start:desktop" script, then run `npm run start:desktop`; otherwise, run `npm run start`.

Expand All @@ -77,22 +77,22 @@ If you aren't using VS Code, you can use the command line (such as bash, or Powe

If your add-in doesn't sideload in the document, follow the steps in [Sideload your add-in](#sideload-your-add-in) to sideload your add-in. Then continue to the next section to start debugging.

1. Open developer tools in the browser. For Chrome and most browsers F12 will open the developer tools.
1. Open developer tools in the browser. For Chrome and most browsers F12 opens the developer tools.
1. In developer tools, open your source code script file (**functions.js** or **functions.ts**). Your custom functions code may be located near the end of the file.
1. In the custom function source code, apply a breakpoint by selecting a line of code.

If you need to change the code, you can make edits in VS Code and save the changes. Refresh the browser to see the changes loaded.

### Commands for building and running your add-in

There are several build tasks available.
Available build tasks:

- `npm run watch`: builds for development and automatically rebuilds when a source file is saved
- `npm run build-dev`: builds for development once
- `npm run build`: builds for production
- `npm run dev-server`: runs the web server used for development

You can use the following tasks to start debugging on desktop or online.
Use these tasks to start debugging:

- `npm run start:desktop`: Starts Excel on desktop and sideloads your add-in. If the "start:desktop" script isn't present in the "scripts" section of the project's package.json file, then run `npm run start` instead.
- `npm run start -- web --document {url}` (where `{url}` is the URL of an Excel file on OneDrive or SharePoint): Starts Excel on the web and sideloads your add-in.
Expand Down
18 changes: 9 additions & 9 deletions docs/excel/custom-functions-errors.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
---
title: Handle and return errors from your custom function
description: 'Handle and return errors like #NULL! from your custom function.'
ms.date: 08/12/2021
description: 'Return meaningful Excel errors (like #VALUE! and #N/A) from custom functions and map exceptions to user-friendly messages.'
ms.date: 09/19/2025
ms.localizationpriority: medium
---

# Handle and return errors from your custom function

If something goes wrong while your custom function runs, return an error to inform the user. If you have specific parameter requirements, such as only positive numbers, test the parameters and throw an error if they aren't correct. You can also use a [`try...catch`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/try...catch) block to catch any errors that occur while your custom function runs.
When a custom function encounters invalid input, an unavailable resource, or a computation failure, return the most specific Excel error possible. Validate parameters early to fail promptly and wrap external calls in `try...catch` blocks to translate low-level exceptions into meaningful Excel errors.

## Detect and throw an error

Let's look at a case where you need to ensure that a zip code parameter is in the correct format for the custom function to work. The following custom function uses a regular expression to check the zip code. If the zip code format is correct, then it will look up the city using another function and return the value. If the format isn't valid, the function returns a `#VALUE!` error to the cell.
The following example validates a U.S. ZIP Code with a regular expression before it proceeds. If the format is invalid, it throws a `#VALUE!` error.

```typescript
/**
* Gets a city name for the given U.S. zip code.
* Gets a city name for the given U.S. ZIP Code.
* @customfunction
* @param {string} zipCode
* @returns The city of the zip code.
* @returns The city of the ZIP Code.
*/
function getCity(zipCode: string): string {
let isValidZip = /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(zipCode);
Expand All @@ -30,7 +30,7 @@ function getCity(zipCode: string): string {

## The CustomFunctions.Error object

The [CustomFunctions.Error](/javascript/api/custom-functions-runtime/customfunctions.error) object is used to return an error back to the cell. When you create the object, specify which error you want to use by choosing one of the following `ErrorCode` enum values.
The [CustomFunctions.Error](/javascript/api/custom-functions-runtime/customfunctions.error) object returns an error to the cell. Specify which error by choosing an `ErrorCode` value from the following list.

|ErrorCode enum value |Excel cell value |Description |
|---------------|---------|---------|
Expand Down Expand Up @@ -59,7 +59,7 @@ throw error;

### Handle errors when working with dynamic arrays

In addition to returning a single error, a custom function can output a dynamic array that includes an error. For example, a custom function could output the array `[1],[#NUM!],[3]`. The following code sample shows how to input three parameters into a custom function, replace one of the input parameters with a `#NUM!` error, and then return a 2-dimensional array with the results of processing each input parameter.
You can return dynamic arrays that contain errors. For example, a custom function could output the array `[1],[#NUM!],[3]`. The following code sample shows how to input three parameters into a custom function, replace one of the input parameters with a `#NUM!` error, and then return a 2-dimensional array with the results of processing each input parameter.

```js
/**
Expand Down Expand Up @@ -98,7 +98,7 @@ To process inputs that contain errors, a custom function must have the JSON meta

## Use `try...catch` blocks

In general, use [`try...catch`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/try...catch) blocks in your custom function to catch any potential errors that occur. If you don't handle exceptions in your code, they will be returned to Excel. By default, Excel returns `#VALUE!` for unhandled errors or exceptions.
Use [`try...catch`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/try...catch) blocks to catch potential errors and return meaningful error messages to your users. By default, Excel returns `#VALUE!` for unhandled errors or exceptions.

In the following code sample, the custom function makes a fetch call to a REST service. It's possible that the call will fail, for example, if the REST service returns an error or the network goes down. If this happens, the custom function will return `#N/A` to indicate that the web call failed.

Expand Down
Loading