Skip to content
Open
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"]
}
}
41 changes: 27 additions & 14 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,35 +8,36 @@ 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 network round 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.
Here's a batching example scenario: 100 cells call the custom function. Instead of 100 network requests, you send one request that lists all 100 operations and then returns 100 answers.

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

## View the completed sample

To view the completed sample, follow this article and paste the code examples into your own project. For example, to create a new custom function project for TypeScript use the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md), then add all the code from this article to the project. Run the code and try it out.

Alternatively, download or view the complete sample project at [Custom function batching pattern](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Excel-custom-functions/Batching). If you want to view the code in whole before reading any further, take a look at the [script file](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Excel-custom-functions/Batching/src/functions/functions.js).

## Create the batching pattern in this article
## Key points

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

1. A [push operation](#add-the-_pushoperation-function) to add a new operation to the batch of calls each time Excel calls your custom function.
2. A [function to make the remote request](#make-the-remote-request) when the batch is ready.
3. [Server code to respond to the batch request](#process-the-batch-call-on-the-remote-service), calculate all of the operation results, and return the values.

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

## Create the batching pattern in this article

In the following sections, you'll learn how to construct the code one example at a time. It's recommended you create a brand-new custom functions project using the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) generator. To create a new project, see [Get started developing Excel custom functions](../quickstarts/excel-custom-functions-quickstart.md). You can use TypeScript or JavaScript.

> [!TIP]
> To view the completed sample, create a new custom functions project with the Yeoman generator for Office Add-ins, and then paste the code examples into your own project. Run the code and try it out.
>
> Alternatively, download or view the complete sample project at [Custom function batching pattern](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Excel-custom-functions/Batching). If you want to view the code in whole before reading any further, take a look at the [script file](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Excel-custom-functions/Batching/src/functions/functions.js).

## Batch each call to your custom function

Your custom functions work by calling a remote service to perform the operation and calculate the result they need. This provides a way for them to store each requested operation into a batch. Later you'll see how to create a `_pushOperation` function to batch the operations. First, take a look at the following code example to see how to call `_pushOperation` from your custom function.

In the following code, the custom function performs division but relies on a remote service to do the actual calculation. It calls `_pushOperation` to batch the operation along with other operations to the remote service. It names the operation **div2**. You can use any naming scheme you want for operations as long as the remote service is also using the same scheme (more on the remote service later). Also, the arguments the remote service will need to run the operation are passed.

### Add the div2 custom function
### Add the `div2` custom function

Add the following code to your **functions.js** or **functions.ts** file (depending on if you used JavaScript or TypeScript).

Expand Down Expand Up @@ -176,7 +177,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 +233,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.
If needed, 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.
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure the original statement that you "can't debug desktop Excel from the command line" is true. You can debug by right-clicking in the task pane and choosing debug to open the developer tools.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you think it would be sufficient to simply remove the sentence?

Suggested change
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.
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.


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.
Copy link
Member

Choose a reason for hiding this comment

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

This is the same sentence as earlier but copilot didn't change it. Interesting.


### 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