---
title: Excel custom functions tutorial
description: In this tutorial, you will create an Excel add-in that contains a custom function that can perform calculations, request web data, or stream web data.
ms.date: 12/26/2024
ms.service: excel
#Customer intent: As an add-in developer, I want to create custom functions in Excel to increase user productivity.
ms.localizationpriority: high
---
# Tutorial: Create custom functions in Excel
Custom functions enable you to add new functions to Excel by defining those functions in JavaScript as part of an add-in. Users within Excel can access custom functions as they would any native function in Excel, such as `SUM()`. You can create custom functions that perform simple tasks like calculations or more complex tasks such as streaming real-time data from the web into a worksheet.
In this tutorial, you will:
> [!div class="checklist"]
> - Create a custom function add-in using the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md).
> - Use a prebuilt custom function to perform a simple calculation.
> - Create a custom function that gets data from the web.
> - Create a custom function that streams real-time data from the web.
## Prerequisites
[!include[Yeoman generator prerequisites](../includes/quickstart-yo-prerequisites.md)]
## Create a custom functions project
To start, create the code project to build your custom function add-in. The [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) will set up your project with some prebuilt custom functions that you can try out. If you've already run the custom functions quick start and generated a project, continue to use that project and skip to [this step](#create-a-custom-function-that-requests-data-from-the-web) instead.
> [!NOTE]
> If you recreate the Yo Office project, you may get an error because the Office cache already has an instance of a function with the same name. You can prevent this by [clearing the Office cache](../testing/clear-cache.md) before running `npm run start`.
1. [!include[Yeoman generator create project guidance](../includes/yo-office-command-guidance.md)]
- **Choose a project type:** `Excel Custom Functions using a Shared Runtime`
- **Choose a script type:** `JavaScript`
- **What do you want to name your add-in?** `My custom functions add-in`
:::image type="content" source="../images/yo-office-excel-cf-quickstart.png" alt-text="The Yeoman Office Add-in generator command line interface prompts for custom functions projects.":::
The Yeoman generator will create the project files and install supporting Node components.
1. Navigate to the root folder of the project.
```command line
cd "My custom functions add-in"
```
1. Build the project.
```command line
npm run build
```
> [!NOTE]
> Office Add-ins should use HTTPS, not HTTP, even when you are developing. If you are prompted to install a certificate after you run `npm run build`, accept the prompt to install the certificate that the Yeoman generator provides.
1. Start the local web server, which runs in Node.js. You can try out the custom function add-in in Excel.
# [Excel on Windows or Mac](#tab/excel-windows)
The command to test your add-in in Excel on Windows or Mac depends on when the project was created. If the `"scripts"` section of the project's package.json file has a "start:desktop" script, then run `npm run start:desktop`; otherwise, run the command `npm run start`. The local web server will start and Excel will open with your add-in loaded.
[!INCLUDE [alert use https](../includes/alert-use-https.md)]
# [Excel on the web](#tab/excel-online)
To test your add-in in Excel on the web, run the following command. When you run this command, the local web server will start. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions.
[!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)]
[!INCLUDE [alert use https](../includes/alert-use-https.md)]
---
## Try out a prebuilt custom function
The custom functions project that you created contains some prebuilt custom functions, defined within the **./src/functions/functions.js** file. The **./manifest.xml** file specifies that all custom functions belong to the `CONTOSO` namespace. You'll use the CONTOSO namespace to access the custom functions in Excel.
Next, try out the `ADD` custom function by completing the following steps.
1. In Excel, go to any cell and enter `=CONTOSO`. Notice that the autocomplete menu shows the list of all functions in the `CONTOSO` namespace.
1. Run the `CONTOSO.ADD` function, with numbers `10` and `200` as input parameters, by typing the value `=CONTOSO.ADD(10,200)` in the cell and pressing Enter.
The `ADD` custom function computes the sum of the two numbers that you provided and returns the result of **210**.
[!include[Manually register an add-in](../includes/excel-custom-functions-manually-register.md)]
> [!NOTE]
> See the [Troubleshooting](#troubleshooting) section of this article if you encounter errors when sideloading the add-in.
## Create a custom function that requests data from the web
Integrating data from the Web is a great way to extend Excel through custom functions. Next you'll create a custom function named `getStarCount` that shows how many stars a given Github repository possesses.
1. In the **My custom functions add-in** project, find the file **./src/functions/functions.js** and open it in your code editor.
1. In **function.js**, add the following code.
```JS
/**
* Gets the star count for a given Github repository.
* @customfunction
* @param {string} userName string name of Github user or organization.
* @param {string} repoName string name of the Github repository.
* @return {number} number of stars given to a Github repository.
*/
async function getStarCount(userName, repoName) {
try {
//You can change this URL to any web request you want to work with.
const url = "https://api.github.com/repos/" + userName + "/" + repoName;
const response = await fetch(url);
//Expect that status code is in 200-299 range
if (!response.ok) {
throw new Error(response.statusText)
}
const jsonResponse = await response.json();
return jsonResponse.watchers_count;
}
catch (error) {
return error;
}
}
```
1. Run the following command to rebuild the project.
```command line
npm run build
```
1. Complete the following steps (for Excel on the web, Windows, or Mac) to re-register the add-in in Excel. You must complete these steps before the new function will be available.
### [Excel on Windows or Mac](#tab/excel-windows)
1. Close Excel and then reopen Excel.
1. In the Excel ribbon, select **Home** > **Add-ins**.
1. Under the **Developer Add-ins** section, select **My custom functions add-in** to register it.
:::image type="content" source="../images/excel-cf-select-add-in.png" alt-text="The My Add-ins dialog that shows active add-ins, with the My custom function add-in button highlighted.":::
1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Office-Add-in-Samples")** and press Enter. You should see that the result in cell **B1** is the current number of stars given to the [Office-Add-in-Samples repository](https://github.com/OfficeDev/Office-Add-in-Samples).
# [Excel on the web](#tab/excel-online)
1. Select **Home** > **Add-ins**, then select **More Settings**.
1. On the **Office Add-ins** dialog, select **Upload My Add-in**.
1. Choose **Browse...** and navigate to the root directory of the project that the Yeoman generator created.
1. Select the file **manifest.xml** and choose **Open**, then choose **Upload**.
1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Excel-Custom-Functions")** and press Enter. You should see that the result in cell **B1** is the current number of stars given to the [Excel-Custom-Functions Github repository](https://github.com/OfficeDev/Excel-Custom-Functions).
---
> [!NOTE]
> See the [Troubleshooting](#troubleshooting) section of this article if you encounter errors when sideloading the add-in.
## Create a streaming asynchronous custom function
The `getStarCount` function returns the number of stars a repository has at a specific moment in time. Custom functions also return data that is continuously changing. These functions are called streaming functions. They must include an `invocation` parameter which refers to the cell that called the function. The `invocation` parameter is used to update the contents of the cell at any time.
In the following code sample, notice that there are two functions, `currentTime` and `clock`. The `currentTime` function is a static function that doesn't use streaming. It returns the date as a string. The `clock` function uses the `currentTime` function to provide the new time every second to a cell in Excel. It uses `invocation.setResult` to deliver the time to the Excel cell and `invocation.onCanceled` to handle function cancellation.
The **My custom functions add-in** project already contains the following two functions in the **./src/functions/functions.js** file.
```JS
/**
* Returns the current time
* @returns {string} String with the current time formatted for the current locale.
*/
function currentTime() {
return new Date().toLocaleTimeString();
}
/**
* Displays the current time once a second
* @customfunction
* @param {CustomFunctions.StreamingInvocation} invocation Custom function invocation
*/
function clock(invocation) {
const timer = setInterval(() => {
const time = currentTime();
invocation.setResult(time);
}, 1000);
invocation.onCanceled = () => {
clearInterval(timer);
};
}
```
To try out the functions, type the text **=CONTOSO.CLOCK()** in cell **C1** and press Enter. You should see the current date, which streams an update every second. While this clock is just a timer on a loop, you can use the same idea of setting a timer on more complex functions that make web requests for real-time data.
## Troubleshooting
You may encounter issues if you run the tutorial multiple times. If the Office cache already has an instance of a function with the same name, your add-in gets an error when it sideloads.
You can prevent this conflict by [clearing the Office cache](../testing/clear-cache.md) before running `npm run start`. If your npm process is already running, enter `npm stop`, clear the Office cache, and then restart npm.
:::image type="content" source="../images/custom-function-already-exists-error.png" alt-text="An error message in Excel titled 'Error installing functions'. It contains the text 'This add-in wasn't installed because a custom function with the same name already exists'.":::
## Next steps
Congratulations! You've created a new custom functions project, tried out a prebuilt function, created a custom function that requests data from the web, and created a custom function that streams data. Next, learn how to [Share custom function data with the task pane](share-data-and-events-between-custom-functions-and-the-task-pane-tutorial.md).