Office Dev Scripts
Office Dev Scripts
e OVERVIEW
Script fundamentals
i REFERENCE
Get started
g TUTORIAL
s SAMPLE
More samples
Share scripts
c HOW-TO GUIDE
Office Scripts in Excel let you automate your day-to-day tasks. Use the Action Recorder
to turn manual steps into reusable scripts. Edit those scripts or create new ones with the
Code Editor. Let others in the workbook run these scripts with a single button. Then,
share them with coworkers so everyone can improve their workflow.
This series of documents teaches you how to use these tools. You'll find a wealth of
samples covering different Excel scenarios. Use the tutorials to introduce yourself to the
Action Recorder and Code Editor. These provide step-by-step guidance on how to
record your frequent Excel actions, edit those scripts, and create new scripts from
scratch.
https://www.microsoft.com/en-us/videoplayer/embed/RE4qdFF?postJsllMsg=true
As an example, imagine at the start of each work day you open a .csv file from an
accounting site in Excel. You then spend several minutes deleting unnecessary columns,
formatting a table, adding formulas, and creating a PivotTable in a new worksheet.
Those actions you repeat daily can be recorded once with the Action Recorder. From
then on, running the script will take care of your entire .csv conversion. You'll not only
remove the risk of forgetting steps, but be able to share your process with others
without having to teach them anything. Office Scripts allows you to automate your
common tasks so you and your workplace can be more efficient and productive.
Action Recorder
The Action Recorder records actions you take in Excel and saves them as a script. With
the Action recorder running, you can capture the Excel actions as you edit cells, change
formatting, and create tables. The resulting script can be run on other worksheets and
workbooks to recreate your original actions.
More information about the Action Recorder can be found in the article Record your
actions as Office Script .
Code Editor
Use the Code Editor to edit scripts recorded with the Action Recorder or make a brand
new script. This tool lets you tweak and customize scripts to better suit your exact
needs. You can also add logic and functionality that is not directly accessible through
the Excel UI, such as conditional statements (if/else) and loops.
Tip
The Action Recorder has a Copy as code button to record actions into script code
without saving the entire script.
Our tutorials provide a guided and structured way learn the capabilities of Office Scripts.
After completing the tutorials, read Fundamentals for Office Scripts in Excel to learn
more about the Code Editor and how to write and edit your own scripts. For additional
information about the Code Editor and how your script code is interpreted, read Office
Scripts Code Editor environment.
Add buttons that run scripts to help your colleagues discover your valuable solutions
and let them run scripts straight from the workbook. Learn more about script buttons in
Run Office Scripts with buttons.
7 Note
Learn more about how scripts are stored in your OneDrive in Office Scripts file
storage and ownership.
) Important
To schedule a script, open the script in the Code Editor. Open the Script scheduling
section and complete the sign in process to Excel through Power Automate. Set how
often you want the script to run and select Create flow to begin.
Next steps
Complete the Office Scripts in Excel tutorial to learn how to create your first script.
See also
Fundamentals for Office Scripts in Excel
Office Scripts API reference
Platform limits and requirements with Office Scripts
Office Scripts settings in M365
Sharing Office Scripts in Excel
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Tutorial: Create and format an Excel
table
Article • 09/20/2024
This tutorial teaches you the basics of recording, editing, and writing an Office Script for
Excel. You'll record a script that applies some formatting to a sales record worksheet.
You'll then edit the recorded script to apply more formatting, create a table, and sort
that table. This record-then-edit pattern is an important tool to see what your Excel
actions look like as code.
Prerequisites
You'll need access to Office Scripts for this tutorial. Please review the Platform support if
the Automate tab doesn't appear.
) Important
2. Copy the following fruit sales data and paste it into the worksheet, starting at cell
A1.
ノ Expand table
3. Open the Automate tab. If you don't see the Automate tab, check the ribbon
overflow by selecting the drop-down arrow. If it's still not there, follow the advice
in the article Troubleshoot Office Scripts.
5. Select cells A2:C2 (the "Oranges" row) and set the fill color to orange.
Your worksheet should look like this (don't worry if the color is different):
TypeScript
selectedSheet.getRange("A2:C2").getFormat().getFill().setColor("FFC000"
);
}
This code gets the current worksheet from the workbook. Then, it sets the fill color
of the range A2:C2.
Ranges are a fundamental part of Office Scripts in Excel. A range is a contiguous,
rectangular block of cells that contains values, formula, and formatting. They are
the basic structure of cells through which you'll perform most of your scripting
tasks.
3. Add the following line to the end of the script (between where the color is set and
the closing } ):
TypeScript
selectedSheet.getRange("A3:C3").getFormat().getFill().setColor("yellow"
);
4. Test the script by selecting Run. Your workbook should now look like this:
Create a table
Next, convert this fruit sales data into a table. You'll keep modifying the first script for
the entire tutorial.
1. Add the following line to the end of the script (before the closing } ):
TypeScript
2. That call returns a Table object. Use that table to sort the data. Sort the data in
ascending order based on the values in the "Fruit" column. Add the following line
after the table creation:
TypeScript
selectedSheet.getRange("A2:C2").getFormat().getFill().setColor("FFC000"
);
selectedSheet.getRange("A3:C3").getFormat().getFill().setColor("yellow"
);
let table = selectedSheet.addTable("A1:C5", true);
table.getSort().apply([{ key: 0, ascending: true }]);
}
Tables have a TableSort object, accessed through the Table.getSort method. You
can apply sorting criteria to that object. The apply method takes in an array of
SortField objects. In this case, you only have one sorting criteria, so you only use
one SortField . The key: 0 value sets the column with the sort-defining values to
"0" (which is the first column on the table, column A in this case). The ascending:
true value sorts the data in ascending order (instead of descending order).
7 Note
If you re-run the script, you'll get an error. This is because you can't create a
table on top of another table. However, you can run the script in a different
worksheet or workbook.
This tutorial teaches you how to read data from a workbook with an Office Script for
Excel. You'll be writing a new script that formats a bank statement and normalizes the
data in that statement. As part of that data clean-up, your script will read values from
the transaction cells, apply a simple formula to each value, and write the resulting
answer to the workbook. Reading data from the workbook lets you automate some of
your decision making processes in the script.
Tip
If you're new to Office Scripts, we recommend starting with Tutorial: Create and
format an Excel table. Office Scripts use TypeScript and this tutorial is intended for
people with beginner to intermediate-level knowledge of JavaScript or TypeScript.
If you're new to JavaScript, we recommend starting with the Mozilla JavaScript
tutorial .
Prerequisites
You'll need access to Office Scripts for this tutorial. Please review the Platform support if
the Automate tab doesn't appear.
Read a cell
Scripts made with the Action Recorder can only write information to the workbook. With
the Code Editor, you can edit and make scripts that also read data from a workbook.
Start by making a script that reads data and acts based on what was read. Throughout
the tutorial, you'll work with a sample banking statement. This statement is a combined
checking and credit statement. Unfortunately, the bank reports balance changes
differently. The checking statement gives income as positive credit and costs as negative
debit. The credit statement does the opposite.
Over the rest of the tutorial, you'll normalize this data using a script. First, you need to
read data from the workbook.
1. Create a new worksheet in the workbook you've used for the rest of the tutorial.
2. Copy the following data and paste it into the new worksheet, starting at cell A1.
ノ Expand table
4. Clean up the formatting. This is a financial document, so have your script change
the number formatting in the Debit and Credit columns to show values as dollar
amounts. Also have your script fit the column width to the data.
TypeScript
5. Now read a value from one of the number columns. Add the following code to the
end of the script (before the closing } ).
TypeScript
7. You should see [Array[1]] in the console. This is not a number because ranges are
two-dimensional arrays of data. That two-dimensional range is being logged to the
console directly. Luckily, the Code Editor lets you see the contents of the array.
9. Expand the second level of the array by selecting the newly revealed blue triangle.
You should now see this:
1. Use getValue and setValue methods to change the value of the cell. These
methods work on a single cell. When handling multi-cell ranges, you'll want to use
getValues and setValues . Add the following code to the end of the script.
TypeScript
// Run the `Math.abs` method with the value at D2 and apply that value
back to D2.
let positiveValue = Math.abs(range.getValue() as number);
range.setValue(positiveValue);
7 Note
We are casting the returned value of range.getValue() to a number by
using the as keyword. This is necessary because a range could be strings,
numbers, or booleans. In this instance, we explicitly need a number.
1. Remove the code that affects only a single cell (the previous absolute value code),
such that your script now looks like this:
TypeScript
2. Add a loop to the end of the script that iterates through the rows in the last two
columns. For each cell, the script sets the value to the current value's absolute
value.
Note that the array defining cell locations is zero-based. That means cell A1 is
range[0][0] .
TypeScript
// Iterate over the fourth and fifth columns and set their values to
their absolute value.
let rowCount = range.getRowCount();
for (let i = 1; i < rowCount; i++) {
// The column at index 3 is column "4" in the worksheet.
if (rangeValues[i][3] != 0) {
let positiveValue = Math.abs(rangeValues[i][3] as number);
selectedSheet.getCell(i, 3).setValue(positiveValue);
}
This portion of the script does several important tasks. First, it gets the values and
row count of the used range. This lets the script look at values and know when to
stop. Second, it iterates through the used range, checking each cell in the Debit or
Credit columns. Finally, if the value in the cell is not 0, it is replaced by its absolute
value. The script ignores zeroes, so you can leave the blank cells as they were.
Your banking statement should now have properly formatted positive numbers.
Next steps
Open the Code Editor and try out some of our Sample scripts for Office Scripts in Excel.
You can also visit Fundamentals for Office Scripts in Excel to learn more about creating
Office Scripts.
The next series of Office Scripts tutorials focus on using Office Scripts with Power
Automate. Learn more about the advantages combining the two platforms in Run Office
Scripts with Power Automate or try Tutorial: Update a spreadsheet from a Power
Automate flow to create a Power Automate flow that uses an Office Script.
Tutorial: Update a spreadsheet from a
Power Automate flow
Article • 12/05/2023
This tutorial teaches you how to run an Office Script for Excel through Power
Automate . You'll make a script that updates the values of two cells with the current
time. You'll then connect that script to a manually triggered Power Automate flow, so
that the script is run whenever a button in Power Automate is selected. Once you
understand the basic pattern, you can expand the flow to include other applications and
automate more of your daily workflow.
Tip
If you are new to Office Scripts, we recommend starting with Tutorial: Create and
format an Excel table. Office Scripts use TypeScript and this tutorial is intended for
people with beginner to intermediate-level knowledge of JavaScript or TypeScript.
If you're new to JavaScript, we recommend starting with the Mozilla JavaScript
tutorial .
Prerequisites
You'll need access to Office Scripts and Power Automate for this tutorial. Please review
the Platform support if the Automate tab doesn't appear. The Power Automate sign-up
FAQ has information on getting started with Power Automate.
TypeScript
// Get the current date and time using the JavaScript Date object.
let date = new Date(Date.now());
3. Rename the script to Set date and time. Select the script name to change it.
2. In the menu that's displayed on the left side of the screen, select Create. This
brings you to a list of ways to create new workflows.
3. In the Start from blank section, select Instant flow. This creates a manually
activated workflow. You can also make scheduled flows and flows that start based
on events. These are covered in the next tutorials.
4. In the dialog window that appears, enter a name for your flow in the Flow name
text box. Under Choose how to trigger the flow, select Manually trigger a flow
from the list of options. Select Create to finish the initial setup.
Note that a manually triggered flow is just one of many types of flows. In the next
tutorial, you'll make a flow that automatically runs when you receive an email.
6. In the Add an action task pane, search for "Excel run script". Choose the Excel
Online (Business) connector's Run script action. This action runs a script from your
OneDrive on a workbook. If you want to use a script stored in your team's
SharePoint library, you should use the Run script from a SharePoint library action.
7. You may be asked to sign in to your Microsoft 365 account. Do so to continue the
tutorial.
8. Next, you'll select the workbook and script to use in the flow step. For the tutorial,
you'll use the workbook you created in your OneDrive, but you could use any
workbook in a OneDrive or SharePoint site. Specify the following parameters for
the Run script action:
Your flow is now ready to be run through Power Automate. You can test it using the Test
button in the flow editor or follow the remaining tutorial steps to run the flow from your
flow collection.
2. Select My tutorial flow from the list of flows displayed in the My flows tab. This
shows the details of the flow we previously created.
3. Select Run.
4. A task pane will appear for running the flow. If you are asked to Sign in to Excel
Online, do so by selecting Continue.
5. Select Run flow. This runs the flow, which runs the related Office Script.
6. Select Done. You should see the run history update accordingly.
7. Refresh the page to see the results of the Power Automate. If it failed, verify the
flow's settings and run it a second time.
8. Open the workbook to see the updated cells. You should see the current date in
cell A1 and the current time in cell B1. Power Automate uses Coordinated Universal
Time (UTC), so the time will likely be offset from your current time zone.
Next steps
Complete Tutorial: Automatically save content from emails in a workbook. It teaches you
how to pass data from a workflow service to your Office Script and run the Power
Automate flow when certain events occur.
Tutorial: Automatically save content
from emails in a workbook
Article • 12/05/2023
This tutorial teaches you how to use an Office Script for Excel with an automated Power
Automate workflow. Your script will automatically run each time you receive an email,
recording information from the email in an Excel workbook. Being able to pass data
from other applications into an Office Script gives you a great deal of flexibility and
freedom in your automated processes.
Tip
If you're new to Office Scripts, we recommend starting with Tutorial: Create and
format an Excel table. If you're new to Power Automate, we recommend starting
with Tutorial: Update a spreadsheet from a Power Automate flow. Office Scripts
use TypeScript and this tutorial is intended for people with beginner to
intermediate-level knowledge of JavaScript or TypeScript. If you're new to
JavaScript, we recommend starting with the Mozilla JavaScript tutorial .
Prerequisites
You'll need access to Office Scripts and Power Automate for this tutorial. Please review
the Platform support if the Automate tab doesn't appear. The Power Automate sign-up
FAQ has information on getting started with Power Automate.
3. Replace the existing code with the following script and select Run. This will setup
the workbook with consistent worksheet, table, and PivotTable names.
TypeScript
function main(workbook: ExcelScript.Workbook) {
// Add a new worksheet to store the email table.
let emailsSheet = workbook.addWorksheet("Emails");
newPivotTable.addDataHierarchy(newPivotTable.getHierarchy("Subject"));
}
1. From within the Code Editor task pane, select New Script.
2. The flow that you'll create later in the tutorial sends the script information about
each email that's received. The script needs to accept that input through
parameters in the main function. Replace the default script with the following
script.
TypeScript
function main(
workbook: ExcelScript.Workbook,
from: string,
dateReceived: string,
subject: string) {
3. The script needs access to the workbook's table and PivotTable. Add the following
code to the body of the script, after the opening { .
TypeScript
TypeScript
// Parse the received date string to determine the day of the week.
let emailDate = new Date(dateReceived);
let dayName = emailDate.toLocaleDateString("en-US", { weekday: 'long'
});
5. The subject string may include the "RE:" reply tag. Remove that from the string so
that emails in the same thread have the same subject for the table. Add the
following code to the end of your script, before the closing } .
TypeScript
// Remove the reply tag from the email subject to group emails on the
same thread.
let subjectText = subject.replace("Re: ", "");
subjectText = subjectText.replace("RE: ", "");
6. Now that the email data has been formatted, add a row to the email table. Add the
following code to the end of your script, before the closing } .
TypeScript
// Add the parsed text to the table.
table.addRow(-1, [dateReceived, dayName, from, subjectText]);
7. Finally, make sure the PivotTable is refreshed. Add the following code to the end of
your script, before the closing } :
TypeScript
Your script is now ready for a Power Automate workflow. It should look like the
following script.
TypeScript
function main(
workbook: ExcelScript.Workbook,
from: string,
dateReceived: string,
subject: string) {
// Get the email table.
let emailWorksheet = workbook.getWorksheet("Emails");
let table = emailWorksheet.getTable("EmailTable");
// Parse the received date string to determine the day of the week.
let emailDate = new Date(dateReceived);
let dayName = emailDate.toLocaleDateString("en-US", { weekday: 'long' });
// Remove the reply tag from the email subject to group emails on the same
thread.
let subjectText = subject.replace("Re: ", "");
subjectText = subjectText.replace("RE: ", "");
2. In the menu that's displayed on the left side of the screen, select Create. This
brings you to list of ways to create new workflows.
3. In the Start from blank section, select Automated flow. This creates a workflow
triggered by an event, such as receiving an email.
4. In the dialog window that appears, enter a name for your flow in the Flow name
text box. Under Choose your flow's trigger, select When a new email arrives from
the list of options. You may need to search for the option using the search box.
Finally, select Create.
7 Note
This tutorial uses Outlook. Feel free to use your preferred email service
instead, though some options may be different.
5. In the flow builder, select the + button and Add an action.
6. In the Add an action task pane, search for "Excel run script". Choose the Excel
Online (Business) connector's Run script action. This action runs a script from your
OneDrive on a workbook. If you want to use a script stored in your team's
SharePoint library, you should use the Run script from a SharePoint library action.
7. You may be asked to sign in to your Microsoft 365 account. Do so to continue the
tutorial.
8. Next, you'll select the workbook and script to use in the flow step. For the tutorial,
you'll use the workbook you created in your OneDrive, but you could use any
workbook in a OneDrive or SharePoint site. Specify the following parameters for
the Run script action:
Note that the parameters for the script will only appear once the script is selected.
9. Select Save.
Your flow is now enabled. It will automatically run your script each time you receive an
email through Outlook.
2. Select your flow. Here you can see the run history. You can refresh the page or
select the refresh All runs button to update the history. The flow will trigger shortly
after an email is received. Test the flow by sending yourself mail.
When the flow is triggered and successfully runs your script, you should see the
workbook's table and PivotTable update.
Troubleshooting
Receiving multiple emails at the same time can cause merge conflicts in Excel. This risk is
mitigated by setting the email connector to only act on one email at a time. To do this:
2. In the Settings options that pop up, set Concurrency Control to On. Then, set the
Degree of Parallelism to 1.
Next steps
Complete Tutorial: Send weekly email reminders based on spreadsheet data. It teaches
you how to return data from a script to the flow.
You can also check out the Automated task reminders sample scenario to learn how to
combine Office Scripts and Power Automate with Teams Adaptive Cards.
Tutorial: Send weekly email reminders
based on spreadsheet data
Article • 12/05/2023
This tutorial teaches you how to return information from an Office Script for Excel as
part of an automated Power Automate workflow. You'll make a script that looks
through a schedule and works with a flow to send reminder emails. This flow will run on
a regular schedule, providing these reminders on your behalf.
Tip
If you're new to Office Scripts, we recommend starting with Tutorial: Create and
format an Excel table.
Office Scripts use TypeScript and this tutorial is intended for people with beginner
to intermediate-level knowledge of JavaScript or TypeScript. If you're new to
JavaScript, we recommend starting with the Mozilla JavaScript tutorial .
Prerequisites
You'll need access to Office Scripts and Power Automate for this tutorial. Please review
the Platform support if the Automate tab doesn't appear. The Power Automate sign-up
FAQ has information on getting started with Power Automate.
3. Add a row to the table with your name, email address, and start and end dates that
overlap with the current date.
) Important
The script you'll write uses the first matching entry in the table, so make sure
your name is above any row with the current week.
3. You should now have an empty script. You want a script that gets an email address
from the spreadsheet. Change main to return a string, like this:
TypeScript
TypeScript
5. The dates in the table are stored using Excel's date serial number . You need to
convert those dates to JavaScript dates in order to compare them. Add the
following helper function outside of the main function.
TypeScript
6. Now, you need to figure out which person is on call right now. Their row will have
a start and end date surrounding the current date. The script will assume only one
person is on call at a time. Scripts can return arrays to handle multiple values, but
you can return the first matching email address for this tutorial. Add the following
code to the end of the main function.
TypeScript
// Look for the first row where today's date is between the row's start
and end dates.
let currentDate = new Date();
for (let row = 0; row < tableValues.length; row++) {
let startDate = convertDate(tableValues[row][2] as number);
let endDate = convertDate(tableValues[row][3] as number);
if (startDate <= currentDate && endDate >= currentDate) {
// Return the first matching email address.
return tableValues[row][1].toString();
}
}
7. The final script should look like this:
TypeScript
// Look for the first row where today's date is between the row's
start and end dates.
let currentDate = new Date();
for (let row = 0; row < tableValues.length; row++) {
let startDate = convertDate(tableValues[row][2] as number);
let endDate = convertDate(tableValues[row][3] as number);
if (startDate <= currentDate && endDate >= currentDate) {
// Return the first matching email address.
return tableValues[row][1].toString();
}
}
}
2. In the menu that's displayed on the left side of the screen, select Create. This
brings you to list of ways to create new workflows.
3. Under the Start from blank section, select Scheduled cloud flow.
4. Next, set the schedule for this flow. Your spreadsheet has a new on-call assignment
starting every Monday in the first half of 2024. Set the flow to run first thing
Monday mornings. Use the following options to configure the flow to run on
Monday each week.
5. Select Create.
7. In the Add an action task pane, search for "Excel run script". Choose the Excel
Online (Business) connector's Run script action. This action runs a script from your
OneDrive on a workbook. If you want to use a script stored in your team's
SharePoint library, you should use the Run script from a SharePoint library action.
8. You may be asked to sign in to your Microsoft 365 account. Do so to continue the
tutorial.
9. Next, you'll select the workbook and script to use in the flow step. For the tutorial,
you'll use the workbook you created in your OneDrive, but you could use any
workbook in a OneDrive or SharePoint site. Specify the following parameters for
the Run script action:
11. End the flow by sending the reminder email. In the Add an action task pane,
search for "send an email". Choose the Office 365 Outlook connector's Send an
email (V2) action.
7 Note
This tutorial uses Outlook. Feel free to use your preferred email service
instead, though some options may be different.
12. For the To parameter, select the text box and select Enter custom value. Use the
dynamic content control to add the email address returned by the script. This will
be labelled result with the Excel icon next to it. You can provide whatever subject
and body text you'd like.
If your flow fails to send an email, double-check in the spreadsheet that a valid
email is listed for the current date range at the top of the table.
Next steps
Visit Run Office Scripts with Power Automate to learn more about connecting Office
Scripts with Power Automate.
You can also check out the Automated task reminders sample scenario to learn how to
combine Office Scripts and Power Automate with Teams Adaptive Cards.
Fundamentals for Office Scripts in Excel
Article • 10/24/2023
This article will introduce you to the technical aspects of Office Scripts. You'll learn the
critical parts of the TypeScript-based script code and how the Excel objects and APIs
work together.
If you would prefer to get started with an interactive experience, try Tutorial: Create and
format an Excel table or visit our samples.
Learn the basics of JavaScript. You should feel comfortable with concepts like
variables, control flow, functions, and data types. Mozilla offers a good,
comprehensive tutorial on JavaScript .
Learn about types in TypeScript. TypeScript builds on JavaScript by ensuring at
compile-time that the right types are used for method calls and assignments. The
TypeScript documentation on object types , type inference , and type
compatibility will be the most useful.
TypeScript
Power Automate allows you to connect scripts in flows. Data is passed between the
scripts and the flow through the parameters and returns of the main function. How to
integrate Office Scripts with Power Automate is covered in detail in Run Office Scripts
with Power Automate.
The complete list of Office Scripts API objects is detailed in the ExcelScript package.
Workbook
Every script is provided a workbook object of type Workbook by the main function. This
represents the top level object through which your script interacts with the Excel
workbook.
The following script gets the active worksheet from the workbook and logs its name.
TypeScript
Ranges
A range is a group of contiguous cells in the workbook. Scripts typically use A1-style
notation (e.g., B3 for the single cell in column B and row 3 or C2:F4 for the cells from
columns C through F and rows 2 through 4) to define ranges.
Ranges have three core properties: values, formulas, and format. These properties get or
set the cell values, formulas to be evaluated, and the visual formatting of the cells. They
are accessed through getValues , getFormulas , and getFormat . Values and formulas can
be changed with setValues and setFormulas , while the format is a RangeFormat object
comprised of several smaller objects that are individually set.
Range sample
The following sample shows how to create sales records. This script uses Range objects
to set the values, formulas, and parts of the format.
TypeScript
Running this script creates the following data in the current worksheet:
When you are using the cell value, it's important to tell TypeScript what value you are
expecting to get from a cell or range. A cell contains one of the following types: string ,
number , or boolean . In order for your script to treat the returned values as one of those
The following script gets the average price from the table in the previous sample. Note
the code priceRange.getValues() as number[][] . This asserts the type of the range
values to be a number[][] . All the values in that array can then be treated as numbers in
the script.
TypeScript
Create a table
Create tables by using data-filled ranges. Formatting and table controls (such as filters)
are automatically applied to the range.
The following script creates a table using the ranges from the previous sample.
TypeScript
// Add a table that has headers using the data from B2:E5.
sheet.addTable("B2:E5", true);
}
Running this script on the worksheet with the previous data creates the following table:
Create a chart
Create charts to visualize the data in a range. Scripts allow for dozens of chart varieties,
each of which can be customized to suit your needs.
The following script creates a simple column chart for three items and places it 100
pixels below the top of the worksheet.
TypeScript
// Set the margin of the chart to be 100 pixels from the top of the
screen.
chart.setTop(100);
}
Running this script on the worksheet with the previous table creates the following chart:
Collections
When an Excel object has a collection of one or more objects of the same type, it stores
them in an array. For example, a Workbook object contains a Worksheet[] . This array is
accessed by the Workbook.getWorksheets() method. get methods that are plural, such
as Worksheet.getCharts() , return the entire object collection as an array. You'll see this
pattern throughout the Office Scripts APIs: the Worksheet object has a getTables()
method that returns a Table[] , the Table object has a getColumns() method that
returns a TableColumn[] , as so on.
The returned array is a normal array, so all the regular array operations are available for
your script. You can also access individual objects within the collection using the array
index value. For example, workbook.getTables()[0] returns the first table in the
collection. For more information on using the built-in array functionality with the Office
Scripts framework, see Work with collections.
Individual objects are also accessed from the collection through a get method. get
methods that are singular, such as Worksheet.getTable(name) , return a single object and
require an ID or name for the specific object. This ID or name is usually set by the script
or through the Excel UI.
The following script gets all tables in the workbook. It then ensures the headers are
displays, the filter buttons are visible, and the table style is set to "TableStyleLight1".
TypeScript
) Important
Do not manually add objects to collection arrays. Use the add methods on the
parent objects For example, add a Table to a Worksheet with the
Worksheet.addTable method.
The following script creates a table in Excel on the first worksheet in the workbook. Note
that the created table is returned by the addTable method.
TypeScript
Tip
Most Excel objects have a setName method. This gives you an easy way to access
Excel objects later in the script or in other scripts for the same workbook.
Verify an object exists in the collection
Scripts often need to check if a table or similar object exists before continuing. Use the
names given by scripts or through the Excel UI to identify necessary objects and act
accordingly. get methods return undefined when the requested object is not in the
collection.
The following script requests a table named "MyTable" and uses an if...else statement
to check if the table was found.
TypeScript
A common pattern in Office Scripts is to recreate a table, chart, or other object every
time the script is run. If you don't need the old data, it's best to delete the old object
before creating the new one. This avoids name conflicts or other differences that may
have been introduced by other users.
The following script removes the table named "MyTable", if it is present, then adds a
new table with the same name.
TypeScript
7 Note
As with adding objects, do not manually remove objects from collection arrays. Use
the delete methods on the collection-type objects. For example, remove a Table
from a Worksheet using Table.delete .
TypeScript
Chart
Comment
PivotTable
Range
RangeFormat
Shape
Table
Workbook
Worksheet
For information specific to the PivotTable object model, see Work with PivotTables in
Office Scripts.
See also
Tutorial: Create and format an Excel table
Tutorial: Clean and normalize Excel workbook data
Office Scripts API reference
Work with PivotTables in Office Scripts
Using built-in JavaScript objects in Office Scripts
Best practices in Office Scripts
Office Scripts Dev Center
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Run Office Scripts with Power Automate
Article • 02/08/2024
Power Automate lets you add Office Scripts to a larger, automated workflow. You can
use Power Automate to do things like add the contents of an email to a worksheet's
table or create actions in your project management tools based on workbook
comments.
) Important
To use Office Scripts in Power Automate , you must have a business license of
Microsoft 365. The Office 365 Enterprise E1 and Office 365 F3 licenses can use
Scripts with Power Automate, but don't have Power Automate integrations directly
in Excel.
Tip
Looking to automatically run a script without connecting to other apps? Use the
Script scheduling feature.
Get started
If you are new to Power Automate, we recommend visiting Get started with Power
Automate. There, you can learn more about all the automation possibilities available to
you. The documents here focus on how Office Scripts work with Power Automate and
how that can help improve your Excel experience.
Step-by-step tutorials
There are three step-by-step tutorials for Power Automate and Office Scripts. These
show how to combine the automate services and pass data between a workbook and a
flow.
This opens a task pane with several options to begin connecting your Office Scripts to
larger automated solutions. Select any option to begin. Your flow is supplied with the
current workbook.
Tip
You can also start making a flow from the More options (…) menu on an individual
script.
Excel connector
The Excel Online (Business) connector gives your flows access to Excel workbooks. There
are two actions that call Office Scripts.
Run script. This is the action to use with scripts stored in the default location of
your OneDrive.
Run script from SharePoint library. This is the action to use when scripts are
stored in your team's SharePoint site.
Run script
For the Run script action, the script location is always in your OneDrive.
For admins who have enabled Conditional Access policies for unmanaged devices in
their tenant, it's a best practice to disable Power Automate on unmanaged devices. This
process is detailed in the blog post Control Access to Power Apps and Power Automate
with Azure AD Conditional Access Policies .
Learn the details of how to pass data to and from your scripts with the following
documentation.
Example
The following screenshot shows a Power Automate flow that's triggered whenever a new
response to a Form is submitted. The flow runs a script that adds the satisfaction value
from the Form to a table. The current average satisfaction is returned and sent as an
email.
The main function of the script specifies the new satisfaction value as an input
parameter ( newData ). The script returns the average satisfaction value from the table.
TypeScript
7 Note
The script parameter is of type string because that is the type the Forms action
returns for all values.
Find full examples with step-by-step walkthroughs in Office Scripts samples and
scenarios. Many use Office Scripts in the center of Power Automate flows.
See also
Tutorial: Update a spreadsheet from a Power Automate flow
Pass data to and from scripts in Power Automate
Troubleshooting information for Power Automate with Office Scripts
Get started with Power Automate
Excel Online (Business) connector reference documentation
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Best practices in Office Scripts
Article • 03/30/2023
These patterns and practices are designed to help your scripts run successfully every
time. Use them to avoid common pitfalls as you start automating your Excel workflow.
) Important
Occasionally, the Action Recorder may use an API that isn't supported outside of
Excel on the web. Users of that script on other platforms receive a warning when
viewing that script.
TypeScript
The TypeScript ? operator checks if the object exists before calling a method. This can
make your code more streamlined if you don't need to do anything special when the
object doesn't exist.
TypeScript
// The ? ensures that the delete() API is only called if the object exists.
workbook.getWorksheet('Index')?.delete();
The following script requires two tables named "Table1" and "Table2" to be present. The
script first checks if the tables are present and then ends with the return statement and
an appropriate message if they're not.
TypeScript
// Continue...
}
If the verification is happening in a separate function, you still must end the script by
issuing the return statement from the main function. Returning from the subfunction
doesn't end the script.
The following script has the same behavior as the previous one. The difference is that
the main function calls the inputPresent function to verify everything. inputPresent
returns a boolean ( true or false ) to indicate whether all required inputs are present.
The main function uses that boolean to decide on continuing or ending the script.
TypeScript
// Continue...
}
However, if your script is running as part of a Power Automate flow, you may want to
stop the flow from continuing. A throw statement stops the script and tells the flow to
stop as well.
The following script shows how to use the throw statement in the table-checking
example.
TypeScript
Consider the following snippet that performs a large data update on a range.
TypeScript
range.setValues(someLargeValues);
If someLargeValues is larger than Excel on the web can handle, the setValues() call fails.
The script then also fails with a runtime error. The try...catch statement lets your script
recognize this condition, without immediately ending the script and showing the default
error.
One approach for giving the script user a better experience is to present them a custom
error message. The following snippet shows a try...catch statement logging more
error information to better help the reader.
TypeScript
try {
range.setValues(someLargeValues);
} catch (error) {
console.log(`The script failed to update the values at location
${range.getAddress()}. Please inspect and run again.`);
console.log(error);
return; // End the script (assuming this is in the main function).
}
Another approach to dealing with errors is to have fallback behavior that handles the
error case. The following snippet uses the catch block to try an alternate method break
up the update into smaller pieces and avoid the error.
Tip
For a full example on how to update a large range, see Write a large dataset.
TypeScript
try {
range.setValues(someLargeValues);
} catch (error) {
console.log(`The script failed to update the values at location
${range.getAddress()}. Trying a different approach.`);
handleUpdatesInSmallerBatches(someLargeValues);
}
// Continue...
}
7 Note
Using try...catch inside or around a loop slows down your script. For more
performance information, see Avoid using try...catch blocks.
See also
Troubleshooting Office Scripts
Troubleshooting information for Power Automate with Office Scripts
Platform limits with Office Scripts
Improve the performance of your Office Scripts
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Use built-in JavaScript objects in Office
Scripts
Article • 11/17/2022
JavaScript provides several built-in objects that you can use in your Office Scripts,
regardless of whether you're scripting in JavaScript or TypeScript (a superset of
JavaScript). This article describes how to use some of the built-in JavaScript objects in
Office Scripts for Excel.
7 Note
For a complete list of all built-in JavaScript objects, see Mozilla's Standard built-in
objects article.
Array
The Array object provides a standardized way to work with arrays in your script. While
arrays are standard JavaScript constructs, they relate to Office Scripts in two major ways:
ranges and collections.
The following script searches the A1:D4 range for any number format containing a "$".
The script sets the fill color in those cells to "yellow".
TypeScript
7 Note
Do not manually add or remove objects from these collection arrays. Use the add
methods on the parent objects and the delete methods on the collection-type
objects. For example, add a Table to a Worksheet with the Worksheet.addTable
method and remove the Table using Table.delete .
The following script logs the type of every shape in the current worksheet.
TypeScript
Typescript
Date
The Date object provides a standardized way to work with dates in your script.
Date.now() generates an object with the current date and time, which is useful when
adding timestamps to your script's data entry.
The following script adds the current date to the worksheet. Note that by using the
toLocaleDateString method, Excel recognizes the value as a date and changes the
TypeScript
The Work with dates section of the samples has more date-related scripts.
Math
The Math object provides methods and constants for common mathematical
operations. These provide many functions also available in Excel, without the need to
use the workbook's calculation engine. This saves your script from having to query the
workbook, which improves performance.
The following script uses Math.min to find and log the smallest number in the A1:D4
range. Note that this sample assumes the entire range contains only numbers, not
strings.
TypeScript
console.log(minimum);
}
See also
Standard built-in objects
Office Scripts Code Editor environment
Office Scripts Code Editor environment
Article • 11/01/2023
Office Scripts are written in either TypeScript or JavaScript and use the Office Scripts
JavaScript APIs to interact with an Excel workbook. The Code Editor is based on Visual
Studio Code, so if you've used that environment before, you'll feel right at home.
Office Scripts are largely self-contained pieces of code. Only a small part of TypeScript's
functionality is used. Therefore, you can edit scripts without having to learn the
intricacies of TypeScript. The Code Editor also handles the installation, compilation, and
execution of code, so you don't need to worry about anything but the script itself. It's
possible to learn the language and create scripts without previous programming
knowledge. However, if you're new to programming, we recommend learning some
fundamentals before proceeding with Office Scripts.
Learn the basics of JavaScript. You should feel comfortable with concepts like
variables, control flow, functions, and data types. Mozilla offers a good,
comprehensive tutorial on JavaScript .
Learn about types in TypeScript. TypeScript builds on JavaScript by ensuring at
compile-time that the right types are used for method calls and assignments. The
TypeScript documentation on object types , type inference , and type
compatibility will be the most useful.
IntelliSense
IntelliSense is a set of Code Editor features that help you write code. It provides auto-
complete, syntax error highlighting, and inline API documentation.
IntelliSense gives suggestions as you type, similar to the suggested text in Excel.
Pressing the Tab or Enter key inserts the suggested member. Trigger IntelliSense at the
current cursor location by pressing the Ctrl+Space keys. These suggestions are
especially useful when completing a method. The method signature displayed by
IntelliSense contains a list of arguments it needs, each argument's type, whether a given
argument is required or optional, and the return type of the method.
Hover the cursor over a method, class, or other code object to see more information.
Hover over a syntax error or code suggestion, represented by a red or yellow squiggly
line, to see suggestions on how to fix the problem. Often, IntelliSense provides a "Quick
Fix" option to automatically change the code.
The Office Scripts Code Editor uses the same IntelliSense engine as Visual Studio Code.
To learn more about the feature, visit Visual Studio Code's IntelliSense Features .
Keyboard shortcuts
Most of the keyboard shortcuts for Visual Studio Code also work in the Office Scripts
Code Editor. Use the following PDFs to learn about the available options and get the
most out of the Code Editor:
Scripts support calls to external services. Use these services to supply data and other
information to your workbook.
U Caution
External calls may result in sensitive data being exposed to undesirable endpoints.
Your admin can establish Information Rights Management (IRM) or firewall
protection against such calls.
) Important
Calls to external APIs can only be made through the Excel application, not through
Power Automate under normal circumstances. External calls are also not supported
for scripts stored on a SharePoint site.
TypeScript
7 Note
Scripts that return other information can return a Promise of that type. For
example, if your script needs to return an Employee object, the return signature
would be : Promise <Employee>
You'll need to learn the external service's interfaces to make calls to that service. If you
are using fetch or REST APIs , you need to determine the JSON structure of the
returned data. For both input to and output from your script, consider making an
interface to match the needed JSON structures. This gives the script more type safety.
You can see an example of this in Using fetch from Office Scripts.
Any JSON data retrieved by fetch must match an interface defined in the script. The
returned value must be assigned to a specific type because Office Scripts do not support
the any type. You should refer to the documentation for your service to see what the
names and types of the returned properties are. Then, add the matching interface or
interfaces to your script.
The following script uses fetch to retrieve JSON data from the test server in the given
URL. Note the JSONData interface to store the data as a matching type.
TypeScript
/**
* An interface that matches the returned JSON structure.
* The property names match exactly.
*/
interface JSONData {
userId: number;
id: number;
title: string;
completed: boolean;
}
You'll have to use HTTP with Azure AD or other equivalent actions to pull data from or
push it to an external service.
2 Warning
External calls made through the Power Automate Excel Online connector fail in
order to help uphold existing data loss prevention policies. However, scripts that
are run through Power Automate are done so outside of your organization, and
outside of your organization's firewalls. For additional protection from malicious
users in this external environment, your admin can control the use of Office Scripts.
Your admin can either disable the Excel Online connector in Power Automate or
turn off Office Scripts for Excel through the Office Scripts administrator controls.
See also
Use JSON to pass data to and from Office Scripts
Using built-in JavaScript objects in Office Scripts
Use external fetch calls in Office Scripts
Office Scripts sample scenario: Graph water-level data from NOAA
Office Scripts file storage and ownership
Article • 01/11/2024
The details of how scripts are stored and shared depend on your Microsoft 365
subscription. Select the relevant tab to learn more.
) Important
Office Scripts is in preview for personal and family Microsoft 365 subscriptions. If
you encounter any issues, please report them through the Feedback button in
Excel.
File storage
For business and education
Office Scripts are stored in your OneDrive by default. The .osts files are found in the
/Documents/Office Scripts/ folder. Any edits made to these .osts files, such as
renaming or deleting files, will be reflected in the Code Editor and Script Gallery.
Excel only recognizes and runs a script if it's in your OneDrive folder, a Sharepoint
folder, or shared with the workbook. This means Excel needs internet connectivity
to access Office Scripts.
OneDrive
Scripts that are shared with one of your workbooks remain in the script creator's
OneDrive. They are not copied to any of your local or OneDrive folders when you
run the shared script in Excel. The Move button shown when renaming a script
moves the script to a new location. The Make a Copy button of the Code Editor
saves a separate copy of the script in your OneDrive. Changes to the copy don't
affect the original script.
Unless you share your personal scripts, no one else can access them. Your OneDrive
settings control the shared access and permissions for all script .osts files,
independent of any Excel settings. Scripts can't be linked from a local disk or
custom cloud locations.
SharePoint
Office Scripts that are saved to a SharePoint site are owned by your team. You and
members of your organization with the appropriate access can run and edit scripts
from SharePoint. You'll also see these scripts appear in the Automate tab's Script
Gallery.
To load a script from SharePoint, go to All scripts and select View more scripts at
the bottom of the list. This brings up a file picker where you can choose .osts files
from any SharePoint site to which you have access. Note that scripts from
SharePoint that you've already opened will be displayed in the list of recent scripts.
To move a script to SharePoint, open a script in the Code Editor and click on the
script name, as if you're renaming it. In the callout, click the Move button. This
opens a file picker. Select the destination folder in your SharePoint site. Moving the
script to the new location can take up to a minute.
To save a copy of a script to SharePoint, go to the More options (…) menu and
select Save as. This opens a file picker where you can select folders in your
SharePoint site. Saving to a new location creates a copy of the script at that
location. The original version is still on your OneDrive or other SharePoint location.
) Important
Scripts with external calls can't be run from SharePoint. You'll receive an error
saying "Network access calls are not supported at this time for scripts saved to
a SharePoint site".
7 Note
Power Automate supports running scripts stored on SharePoint with the Run
script from SharePoint library (Preview) action. This action is currently in
preview and is subject to change based on feedback. If you encounter any
issues with this action, please report them through the Help > Give Feedback
option in Power Automate.
Share scripts
For business and education
To give users who are outside of the SharePoint site access to the script, share the
script with an Excel workbook. This means you're linking the script with the file, not
attaching it. Whoever has access to the Excel file will also be able to view, run, or
make a copy of the script.
7 Note
Admin settings for Conditional Access in OneDrive and SharePoint affect Office
Scripts. For more information, see the Conditional Access section of Platform
limits and requirements with Office Scripts.
When you delete a script in Excel, it goes to your OneDrive or SharePoint recycle
bin. To restore a deleted script, follow the steps listed in How to recover missing,
deleted or corrupted items in SharePoint and OneDrive for work or school .
Restoring an .osts file returns it to the All scripts list.
A deleted script is unshared with the workbook. When you restore a script, it does
not retain its script access. You will need to share the script again.
Restored scripts still work as expected with Power Automate flows. You don't need
to recreate the flow connector.
Office Scripts follow the retention and deletion policies specified by Microsoft
OneDrive and Microsoft SharePoint. To learn how to handle scripts that were
created and shared by a user being removed from your organization, see Learn
about retention for SharePoint and OneDrive.
During editing, files are temporarily stored in the browser. You must save the script
before closing the Excel window to save it to the OneDrive location. Don't forget to
save the file after edits, or else those edits will only be in the browser's version of
the file.
To specifically audit Office Scripts related activity as an admin, take the following steps.
3. (One time only) On the Search tab, select Start recording user and admin activity.
) Important
It may take an hour or two after turning on recording before all activities
across the tenant are recorded.
4. Set the desired search options and select Search. Filter the File, folder, or site field
to .osts . This reveals who in your organization is creating or modifying scripts.
See also
Sharing Office Scripts in Excel
Troubleshooting Office Scripts
Office Scripts settings in M365
Undo the effects of Office Scripts
Get user input for scripts
Article • 09/14/2023
Adding parameters to your script lets other users provide data for the script, without
needing to edit code. When your script is run through the ribbon or a button, a prompt
pops up that asks for input.
) Important
Currently, only Excel on the web users will be prompted to enter data for
parameterized scripts. Power Automate flows also support giving data to scripts
through parameters.
TypeScript
/**
* This script applies a background color to cells over a certain value.
* @param highlightThreshold The value used for comparisons.
* @param color A string representing the color to make the high value
cells.
* This must be a color code representing the color of the background,
* in the form #RRGGBB (e.g., "FFA500") or a named HTML color (e.g.,
"orange").
*/
function main(
workbook: ExcelScript.Workbook,
highlightThreshold: number,
color: string) {
// Get the used cells in the current worksheet.
const currentSheet = workbook.getActiveWorksheet();
const usedRange = currentSheet.getUsedRange();
Optional parameters
Optional parameters don't need the user to provide a value. This implies your script
either has default behavior or this parameter is only needed in a corner case. They're
denoted in your script with the optional modifier ? . For example, in function
parameter location has the value "Seattle" unless something else is provided.
When the script is run, users get a dropdown list with those two options.
TypeScript
/**
* A script to apply the current tax rate to sales figures.
* @param taxRate The current sales tax rate in the region as a decimal
number (enter 12% as .12).
*/
function main(workbook: ExcelScript.Workbook, taxRate: number)
7 Note
Type restrictions
When adding input parameters and return values, consider the following allowances and
restrictions.
1. The first parameter must be of type ExcelScript.Workbook . Its parameter name
doesn't matter.
3. Arrays (both [] and Array<T> styles) of the previously listed types are supported.
Nested arrays are also supported.
4. Union types are allowed if they're a union of literals belonging to a single type
(such as "Left" | "Right" , not "Left" | 5 ).
5. Object types are allowed if they contain properties of type string , number ,
boolean , supported arrays, or other supported objects. The following example
TypeScript
interface Position {
id: number;
title: string;
}
6. Objects must have their interface or class definition defined in the script. An object
can also be defined anonymously inline, as in the following example.
TypeScript
See also
Pass data to and from scripts in Power Automate
Run Office Scripts in Excel with buttons
Set conditional formatting for cross-column comparisons
Pass data to and from scripts in Power
Automate
Article • 11/29/2023
Power Automate chains together separate programs into a single automated workflow.
Each connector has different parameters it accepts and different values it returns. Your
scripts can be written to expand the "Run script" Power Automate action to get
additional input or give output.
Input for your script is specified by adding parameters to the main function. Output
from the script is declared by adding a return type to main .
7 Note
When you create a "Run script" block in your flow, the accepted parameters and
returned types are populated. If you change the parameters or return types of your
script, you'll need to redo the "Run script" block of your flow. This ensures the data
is being parsed correctly.
The following screenshot shows what a script with the signature function
main(workbook: ExcelScript.Workbook, location: string = "Seattle") would display.
The dropdown menus created by type unions also function the same in Power
Automate.
Return data from a script
Scripts can return data from the workbook to be used as dynamic content in a Power
Automate flow. To return an object, add the return type syntax to the main function. For
example, if you wanted to return a string value from the script, your main signature
would be function main(workbook: ExcelScript.Workbook): string .
Returned values are shown as dynamic content from the Run script action in the flow.
The dynamic content is named "result".
Acceptable types for returning data are the same as for parameters. Details on type
restrictions are found in the article Get user input for scripts.
See also
Tutorial: Update a spreadsheet from a Power Automate flow
Get user input for scripts
Run Office Scripts with Power Automate
Troubleshooting information for Power Automate with Office Scripts
Run Office Scripts in Excel from buttons
Article • 06/11/2024
Help your colleagues find and run your scripts by adding script buttons to a workbook.
7 Note
Script buttons aren't available during the Office Scripts preview for personal and
family Microsoft 365 subscriptions.
See also
Platform limits and requirements with Office Scripts
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Use JSON to pass data to and from
Office Scripts
Article • 11/29/2023
JSON (JavaScript Object Notation) is a format for storing and transferring data. Each
JSON object is a collection of name/value pairs that can be defined when created. JSON
is useful with Office Scripts because it can handle the arbitrary complexity of ranges,
tables, and other data patterns in Excel. JSON lets you parse incoming data from web
services and pass complex objects through Power Automate flows.
This article focuses on using JSON with Office Scripts. We recommend you first learn
more about the format from articles such as JSON Introduction from W3 Schools.
The following script shows JSON data being converted to a table. Note that the data is
not taken from an external source. That is covered later in this article.
TypeScript
/**
* Sample JSON data. This would be replaced by external calls or
* parameters getting data from Power Automate in a production script.
*/
const jsonData = [
{ "Action": "Edit", /* Action property with value of "Edit". */
"N": 3370, /* N property with value of 3370. */
"Percent": 17.85 /* Percent property with value of 17.85. */
},
// The rest of the object entries follow the same pattern.
{ "Action": "Paste", "N": 1171, "Percent": 6.2 },
{ "Action": "Clear", "N": 599, "Percent": 3.17 },
{ "Action": "Insert", "N": 352, "Percent": 1.86 },
{ "Action": "Delete", "N": 350, "Percent": 1.85 },
{ "Action": "Refresh", "N": 314, "Percent": 1.66 },
{ "Action": "Fill", "N": 286, "Percent": 1.51 },
];
/**
* This script converts JSON data to an Excel table.
*/
function main(workbook: ExcelScript.Workbook) {
// Create a new worksheet to store the imported data.
const newSheet = workbook.addWorksheet();
newSheet.activate();
/**
* This function turns a JSON object into an array to be used as a table
row.
*/
function convertJsonToRow(obj: object) {
const array: (string | number)[] = [];
// Loop over each property and get the value. Their order will be the same
as the column headers.
for (let value in obj) {
array.push(obj[value]);
}
return array;
}
/**
* This function gets the property names from a single JSON object.
*/
function getPropertiesFromJson(obj: object) {
const propertyArray: string[] = [];
// Loop over each property in the object and store the property name in an
array.
for (let property in obj) {
propertyArray.push(property);
}
return propertyArray;
}
Tip
If you know the structure of the JSON, you can create your own interface to make
getting specific properties easier. You can replace the JSON-to-array conversion
steps with type-safe references. The following code snippet shows those steps (now
commented out) replaced by calls that use a new ActionRow interface. Note that
this makes the convertJsonToRow function no longer necessary.
TypeScript
interface ActionRow {
Action: string;
N: number;
Percent: number;
}
TypeScript
// For Power Automate, replace the main signature in the previous sample
with this one
// and remove the sample data.
function main(workbook: ExcelScript.Workbook, jsonData: object[]) {
You'll then see an option in the Power Automate connector to add jsonData to the Run
script action.
TypeScript
// For external services, replace the main signature in the previous sample
with this one,
// add the fetch call, and remove the sample data.
async function main(workbook: ExcelScript.Workbook) {
// Replace WEB_SERVICE_URL with the URL of whatever service you need to
call.
const response = await fetch('WEB_SERVICE_URL');
const jsonData: object[] = await response.json();
ノ Expand table
Each transaction (each row) has a set of properties associated with it: "ID", "Date",
"Amount", and "Vendor". This can be modeled in an Office Script as an object.
TypeScript
The rows in the sample table correspond to the properties in the interface, so a script
can easily convert each row into a Transaction object. This is useful when outputting
the data for Power Automate. The following script iterates over each row in the table
and adds it to a Transaction[] .
TypeScript
TypeScript
TypeScript
// For each row, create a JSON object and assign each property to it based
on the table headers.
for (let i = 0; i < dataValues.length; i++) {
// Create a blank generic JSON object.
let jsonObject: { [key: string]: string } = {};
for (let j = 0; j < dataValues[i].length; j++) {
jsonObject[tableHeaders[j]] = dataValues[i][j] as string;
}
jsonArray.push(jsonObject);
}
See also
External API call support in Office Scripts
Sample: Use external fetch calls in Office Scripts
Run Office Scripts with Power Automate
How to use macro-enabled files in
Power Automate flows
Article • 05/14/2024
Power Automate flows support .xlsm files in the Excel Online (Business) connector .
However, only the Run script action lets you select .xlsm files through the file browser.
Other connector actions require you use the file ID.
Get the file ID with a Get File Metadata action from either the OneDrive for Business
or SharePoint connectors. Use the ID dynamic content returned from the Get file
metadata action as the "File" argument for Excel connector actions. Note that
parameters such as "Table" in the Add a row into a table action won't automatically
propagate a dropdown list of tables to choose. You'll need to enter the name of the
table or other Excel object.
) Important
The macros contained in the .xlsm files cannot be run through Power Automate.
Only Office Scripts are enabled there.
2 Warning
Some .xlsm files, especially those with ActiveX or Form controls, may not work in
the Excel online connector. Be sure to test before deploying your solution.
See also
Excel Online (Business) connector reference
Run Office Scripts with Power Automate
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our Provide product feedback
contributor guide.
Work with PivotTables in Office Scripts
Article • 05/01/2024
PivotTables let you analyze large collections of data quickly. With their power comes
complexity. The Office Scripts APIs let you customize a PivotTable to suit your needs, but
the scope of the API set makes getting started a challenge. This article demonstrates
how to perform common PivotTable tasks and explains important classes and methods.
7 Note
To better understand context for the terms used by the APIs, read Excel's PivotTable
documentation first. Start with Create a PivotTable to analyze worksheet data .
Object model
The PivotTable is the central object for PivotTables in the Office Scripts API.
The Workbook object has a collection of all the PivotTables. Each Worksheet also
contains a PivotTable collection that's local to that sheet.
A PivotTable contains PivotHierarchies. A hierarchy can be thought of as a column
in a table.
PivotHierarchies can be added as rows or columns (RowColumnPivotHierarchy),
data (DataPivotHierarchy), or filters (FilterPivotHierarchy).
Each PivotHierarchy contains exactly one PivotField. PivotTable structures outside
of Excel may contain multiple fields per hierarchy, so this design exists to support
future options. For Office Scripts, fields and hierarchies map to the same
information.
A PivotField contains multiple PivotItems. Each PivotItem is a unique value in the
field. Think of each item as a value in the table column. Items could also be
aggregated values, such as sums, if the field is being used for data.
The PivotLayout defines how the PivotFields and PivotItems are displayed.
PivotFilters filter data from the PivotTable using different criteria.
To look at how these relationships work in practice, start by downloading the sample
workbook. That data describes fruit sales from various farms. It's the base for all the
examples in this article. Run the sample scripts throughout the article to create and
explore PivotTables.
The following code snippet creates a PivotTable based on a range of data. The
PivotTable has no hierarchies, so the data is not yet grouped in any way.
TypeScript
A PivotTable can have as many or as few of its fields assigned to these specific
hierarchies. A PivotTable needs at least one data hierarchy to show summarized
numerical data and at least one row or column to pivot that summary on. The following
code snippet adds two row hierarchies and two data hierarchies.
TypeScript
farmPivot.addRowHierarchy(farmPivot.getHierarchy("Farm"));
farmPivot.addRowHierarchy(farmPivot.getHierarchy("Type"));
farmPivot.addDataHierarchy(farmPivot.getHierarchy("Crates Sold at Farm"));
farmPivot.addDataHierarchy(farmPivot.getHierarchy("Crates Sold
Wholesale"));
Layout ranges
Each part of the PivotTable maps to a range. This lets your script get data from the
PivotTable for use later in the script or to be returned in a Power Automate flow. These
ranges are accessed through the PivotLayout object acquired from
PivotTable.getLayout() . The following diagram shows the ranges that are returned by
The following sample finds the first PivotTable in the workbook and logs the values in
the "Grand Total" cells (as highlighted in green in the image below).
TypeScript
function main(workbook: ExcelScript.Workbook) {
// Get the first PivotTable in the workbook.
const pivotTable = workbook.getPivotTables()[0];
// Get the range with the "grand totals" for the PivotTable columns.
const grandTotalRange = pivotDataRange.getLastRow();
FilterPivotHierarchies
PivotFilters
Slicers
FilterPivotHierarchies
FilterPivotHierarchies add an additional hierarchy to filter every data row. Any row
with an item that is filtered out is excluded from the PivotTable and its summaries. Since
these filters are based on items, they only work on discrete values. If "Classification" is a
filter hierarchy in the sample, users can select the values of "Organic" and
"Conventional" for the filter. Similarly, if "Crates Sold Wholesale" is selected, the filter
options would be the individual numbers, such as 120 and 150, instead of numerical
ranges.
FilterPivotHierarchies are created with all values selected. This means that nothing is
filtered until the user manually interacts with the filter control or a PivotManualFilter is
set on the field belonging to the FilterPivotHierarchy .
farmPivot.addFilterHierarchy(farmPivot.getHierarchy("Classification"));
PivotFilters
The PivotFilters object is a collection of filters applied to a single field. Since each
hierarchy has exactly one field, you should always use the first field in
PivotHierarchy.getFields() when applying filters. There are four filter types.
Typically, only one of the four types of filters is created and applied to the field. If the
script tries to use incompatible filters, an error is thrown with the text "The argument is
invalid or missing or has an incorrect format."
The following code snippet adds two filters. The first is a manual filter that selects items
in an existing "Classification" filter hierarchy. The second filter removes any farms that
have fewer than 300 "Crates Sold Wholesale". Note that this filters out the "Sum" of
those farms, not the individual rows from the original data.
TypeScript
const classificationField =
farmPivot.getFilterHierarchy("Classification").getFields()[0];
classificationField.applyFilter({
manualFilter: {
selectedItems: ["Organic"] /* The included items. */
}
});
Slicers
Slicers filter data in a PivotTable (or standard table). They are moveable objects in the
worksheet that allow for quick filtering selections. A slicer operates in a similar fashion
to the manual filter and PivotFilterHierarchy . Items from the PivotField are toggled
to include or exclude them from the PivotTable.
The following code snippet adds a slicer for the "Type" field. It sets the selected items to
be "Lemon" and "Lime", then moves the slicer 400 pixels to the left.
TypeScript
const fruitSlicer = pivotSheet.addSlicer(
farmPivot, /* The table or PivotTale to be sliced. */
farmPivot.getHierarchy("Type").getFields()[0] /* What source to use as
the slicer options. */
);
fruitSlicer.selectItems(["Lemon", "Lime"]);
fruitSlicer.setLeft(400);
Summarize by
The following code snippet changes "Crates Sold Wholesale" to show each item's
standard deviation, instead of the sum.
TypeScript
wholesaleSales.setSummarizeBy(ExcelScript.AggregationFunction.standardDeviat
ion);
Show values as
DataPivotHierarchy.setShowAs applies a calculation to the values of a data hierarchy.
Instead of the default sum, you can show values or percentages relative to other parts of
the PivotTable. Use a ShowAsRule to set how data hierarchy values are shown.
The following code snippet changes the display for "Crates Sold at Farm". The values will
be shown as a percentage of the grand total for the field.
TypeScript
Some ShowAsRule s need another field or item in that field as a comparison. The
following code snippet again changes the display for "Crates Sold at Farm". This time,
the field will show each value's difference from the value of the "Lemons" in that farm
row. If a farm has not sold any lemons, the field shows "#N/A".
TypeScript
See also
Fundamentals for Office Scripts in Excel
Office Scripts API reference
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Troubleshoot Office Scripts
Article • 01/26/2024
As you develop Office Scripts, you may make mistakes. It's okay. You have the tools to
help find the problems and get your scripts working perfectly.
7 Note
For troubleshooting advice specific to Office Scripts with Power Automate, see
Troubleshoot Office Scripts running in Power Automate.
Script errors
Office Scripts errors fall into one of two categories:
Compile-time errors
Compile-time errors and warnings are initially shown in the Code Editor. These are
shown by the wavy red underlines in the editor. They're also displayed under the
Problems tab at the bottom of the Code Editor task pane. Selecting the error gives more
details about the problem and suggests solutions. Compile-time errors should be
addressed before running the script.
You may also see orange warning underlines and grey informational messages. These
indicate performance suggestions or other possibilities where the script may have
unintentional effects. Such warnings should be examined closely before dismissing
them.
Runtime errors
Runtime errors happen because of logic issues in the script. This could be because an
object used in the script isn't in the workbook, a table is formatted differently than
anticipated, or some other slight discrepancy between the script's requirements and the
current workbook. The following script generates an error when a worksheet named
"TestSheet" is not present.
TypeScript
Some runtime errors are caused by exceeding the limits of the platform, such as trying
to write too much data at once with Excel on the web. See Platform limits and
requirements with Office Scripts for a full list of potential pitfalls.
Console messages
Both compile-time and runtime errors display error messages in the console when a
script runs. They give a line number where the problem was encountered. Keep in mind
that the root cause of any issue may be a different line of code than what is indicated in
the console.
The following image shows the console output for the explicit any compiler error. Note
the text [5, 16] at the beginning of the error string. This indicates the error is on line 5,
starting at character 16.
The follow image shows the console output for a runtime error. Here, the script tries to
add a worksheet with a the name of an existing worksheet. Again, note the "Line 2"
preceding the error to show which line to investigate.
Console logs
Print messages to the screen with the console.log statement. These logs can show you
the current value of variables or which code paths are being triggered. To do this, call
console.log with any object as a parameter. Usually, a string is the easiest type to read
in the console.
TypeScript
Strings passed to console.log are displayed in the Code Editor's logging console, at the
bottom of the task pane. Logs are found on the Output tab, though the tab
automatically gains focus when a log is written.
) Important
When using Excel with Teams, Office Scripts are only supported in Teams on the
web (not Teams for Windows, Mac, iOS, or Android).
7 Note
There is a known issue that prevents scripts stored in SharePoint from always
appearing in the recently used list. This occurs when your admin turns off Exchange
Web Services (EWS). Your SharePoint-based scripts are still accessible and usable
through the file dialog.
The access token expiry UTC time is earlier than current UTC time.: Too much
time has passed between signing into the service and scheduling the script.
Reopen the script in the Code Editor or reload the workbook and try to schedule
again.
Help resources
Stack Overflow is a community of developers willing to help with coding problems.
Often, you'll be able to find the solution to your problem through a quick Stack
Overflow search. If not, ask your question and tag it with the "office-scripts" tag. Be sure
to mention you're creating an Office Script, not an Office Add-in.
See also
Best practices in Office Scripts
Platform limits with Office Scripts
Improve the performance of your Office Scripts
Troubleshoot Office Scripts running in PowerAutomate
Undo the effects of Office Scripts
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Troubleshoot Office Scripts running in
Power Automate
Article • 08/15/2024
Power Automate runs scripts on your behalf in independent Excel sessions. This causes
some behavioral changes that may create issues with certain scripts or scenarios. There
are also limitations and behaviors from the Power Automate platform script writers
should know. Be sure to read the articles Troubleshoot Office Scripts and Platform limits
and requirements with Office Scripts, as much of that information also applies to scripts
in flows.
Tip
If you're just starting to use Office Scripts with Power Automate, please start with
Run Office Scripts with Power Automate to learn about the platforms.
) Important
To use Office Scripts in Power Automate , you must have a business license of
Microsoft 365. The Office 365 Enterprise E1 and Office 365 F3 licenses can use
Scripts with Power Automate, but don't have Power Automate integrations directly
in Excel.
Some relative reference APIs throw errors in Power Automate. Others have a default
behavior that implies a user's state. When designing your scripts, be sure to use
absolute references for worksheets and ranges. This makes your Power Automate flow
consistent, even if worksheets are rearranged.
ノ Expand table
Class Method
Chart activate
Range select
Workbook getActiveCell
Workbook getActiveChart
Workbook getActiveSlicer
Workbook getSelectedRange
Workbook getSelectedRanges
ノ Expand table
Workbook getActiveWorksheet Returns either the first worksheet in the workbook or the
worksheet currently activated by the Worksheet.activate
method.
Worksheet activate Marks the worksheet as the active worksheet for purposes of
Workbook.getActiveWorksheet .
Additionally, Power Automate doesn't trigger a data refresh for formulas that use
workbook links.
Script methods that do nothing in Power Automate flows
The following methods do nothing in a script when called through Power Automate.
They still return successfully and don't throw any errors.
ノ Expand table
Class Method
PivotTable refresh
Workbook refreshAllPivotTables
Worksheet refreshAllPivotTables
ノ Expand table
Workbook refreshAllDataConnections Only refreshes PowerBI sources. For other sources, the
method returns successfully but does nothing.
If your script uses dates or times, there may be behavioral differences when the script is
tested locally versus when it is run through Power Automate. Power Automate allows
you to convert, format, and adjust times. See Working with Dates and Times inside of
your flows for instructions on how to use those functions in Power Automate and Pass
data to and from scripts in Power Automate to learn how to provide that time
information for the script.
The signature of a script is stored with the Excel Business (Online) connector when it is
created. Remove the old connector and create a new one to get the latest parameters
and return values for the Run script action.
Power Automate returns the error *API* is not defined , where *API* specifies a library
such as TextEncoder , when running a script that uses an unsupported API.
See also
Troubleshoot Office Scripts
Run Office Scripts with Power Automate
Excel Online (Business) connector reference documentation
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Improve the performance of your Office
Scripts
Article • 04/11/2024
TypeScript
Office Scripts APIs ensure any data in the workbook or script is accurate and up-to-date
when necessary. You don't need to worry about these synchronizations for your script to
run correctly. However, an awareness of this script-to-cloud communication can help
you avoid unneeded network calls.
TypeScript
/**
* This script provides the count of negative numbers that are present
* in the used range of the current worksheet.
*/
function main(workbook: ExcelScript.Workbook) {
// Get the working range.
let usedRange = workbook.getActiveWorksheet().getUsedRange();
7 Note
TypeScript
/**
* This script adds a row to "MyTable", if that table is present.
*/
function main(workbook: ExcelScript.Workbook) {
let table = workbook.getTable("MyTable");
The following sample shows how to change the calculation mode. It also demonstrates
how to manually recalculate the workbook with Application.calculate.
TypeScript
/**
* This script adjusts the calculation mode of the workbook and makes a
manual recalculation.
* Wrap the CalculationMode changes around code that repeatedly updates
values.
*/
function main(workbook: ExcelScript.Workbook) {
const application = workbook.getApplication();
// ...
// ...
Case-by-case help
As the Office Scripts platform expands to work with Power Automate , Adaptive Cards,
and other cross-product features, the details of the script-workbook communication
become more intricate. If you need help making your script run faster, please reach out
through Microsoft Q&A. Be sure to tag your question with "office-scripts-dev" so
experts can find it and help.
See also
Fundamentals for Office Scripts in Excel
MDN web docs: Loops and iteration
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our Provide product feedback
contributor guide.
Platform limits and requirements with
Office Scripts
Article • 10/03/2024
There are some platform limitations of which you should be aware when developing
Office Scripts. This article details the browser support and data limits for Office Scripts
for Excel.
Platform support
To use Office Scripts, you'll need the following.
1. Excel on the web, Excel for Windows (Version 2210 or higher), or Excel for Mac.
2. OneDrive for Business.
3. Any of the following Microsoft 365 subscription licenses:
7 Note
If you meet these requirements and are still not seeing the Automate tab, it's
possible that your admin has disabled the feature or there's some other problem
with your environment. Please follow the steps under Automate tab not appearing
or Office Scripts unavailable to start using Office Scripts.
) Important
To use Office Scripts in Power Automate , you must have a business license of
Microsoft 365. The Office 365 Enterprise E1 and Office 365 F3 licenses can use
Scripts with Power Automate, but don't have Power Automate integrations directly
in Excel.
Data limits
There are limits on how much Excel data can be transferred at once and how many
individual Power Automate transactions can be conducted.
Excel
Excel on the web has the following limitations when making calls to the workbook
through a script.
When you exceed one of the Excel data limits, you receive this error message: "The
response payload size has exceeded the limit."
If you're encountering errors when dealing with large datasets, try using multiple smaller
ranges instead of larger ranges. For an example, see the Write a large dataset sample.
You can also use APIs like Range.getSpecialCells to target specific cells instead of large
ranges.
Excel limits that aren't specific to Office Scripts can be found in the article Excel
specifications and limits .
Power Automate
The following limitations with the Power Automate platform are the ones you're most
likely to encounter.
Each user is limited to 1,600 calls to the Run script action per day. This limit resets
at 12:00 AM UTC.
There's a 120-second timeout for synchronous Power Automate operations. For
long-running scripts, you must either optimize your script or split your Excel
automation into multiple script calls.
The maximum size of parameters passed to the Run script action is 30,000,000
bytes (28.6MB).
Additional Power Automate platform usage limitations can be found in the following
articles.
You'll have to use HTTP with Azure AD or other equivalent actions to pull data from or
push it to an external service.
2 Warning
External calls made through the Power Automate Excel Online connector fail in
order to help uphold existing data loss prevention policies. However, scripts that
are run through Power Automate are done so outside of your organization, and
outside of your organization's firewalls. For additional protection from malicious
users in this external environment, your admin can control the use of Office Scripts.
Your admin can either disable the Excel Online connector in Power Automate or
turn off Office Scripts for Excel through the Office Scripts administrator controls.
Teams support
) Important
When using Excel with Teams, Office Scripts are only supported in Teams on the
web (not Teams for Windows, Mac, iOS, or Android).
7 Note
Some browsers refer to this setting as "all cookies", instead of "third-party cookies".
Conditional Access
Conditional Access policies restrict access to SharePoint and OneDrive for unmanaged
devices. If your device isn't managed by the tenant, you may not have access to specific
scripts, or may only be able to access them through the browser.
If you script is blocked by Conditional Access policies, you receive one of two error
messages. These messages also surface in Power Automate if your flow is run from an
unmanaged device.
"Due to organizational policies, you can’t access this resource from this untrusted
device."
"We can't find this script. It may have been deleted by another user." (If your
version of Excel is older.)
) Important
Using an older version of Excel to open workbooks with scripts shared in them has no
effect on the script itself.
See also
Excel specifications and limits
Troubleshoot Office Scripts
Undo the effects of Office Scripts
Improve the performance of your Office Scripts
TypeScript restrictions in Office Scripts
Article • 11/17/2022
Office Scripts use the TypeScript language. For the most part, any TypeScript or
JavaScript code will work in Office Scripts. However, there are a few restrictions enforced
by the Code Editor to ensure your script works consistently and as intended with your
Excel workbook.
Explicit any
You cannot explicitly declare a variable to be of type any in Office Scripts (that is, let
value: any; ). The any type causes issues when processed by Excel. For example, a
Range needs to know that a value is a string , number , or boolean . You will receive a
compile-time error (an error prior to running the script) if any variable is explicitly
defined as the any type in the script.
In the previous screenshot, [2, 14] Explicit Any is not allowed indicates that line #2,
column #14 defines any type. This helps you locate the error.
To get around this issue, always define the type of the variable. If you are uncertain
about the type of a variable, you can use a union type . This can be useful for variables
that hold Range values, which can be of type string , number , or boolean (the type for
Range values is a union of those: string | number | boolean ).
Implicit any
TypeScript variable types can be implicitly defined. If the TypeScript compiler is unable
to determine the type of a variable (either because type is not defined explicitly or type
inference isn't possible), then it's an implicit any and you will receive a compilation-time
error.
The most common case on any implicit any is in a variable declaration, such as let
value; . There are two ways to avoid this:
Assign the variable to an implicitly identifiable type ( let value = 5; or let value
= workbook.getWorksheet(); ).
Generator functions
Array.sort
Restricted identifiers
The following words can't be used as identifiers in a script. They are reserved terms.
Excel
ExcelScript
console
TypeScript
interface MyTable {
getName(): string
}
The following code sample demonstrates this scenario. It generates an error that says
failed to load [code] [library] .
TypeScript
See also
Fundamentals for Office Scripts in Excel
Improve the performance of your Office Scripts
Undo the changes made by Office
Scripts
Article • 06/18/2024
You cannot undo changes made to the Excel workbook by a script with the Excel's Undo
command. Instead, you must restore a previous version of the workbook from your
cloud storage.
Version history
Office's version history is an easy way to restore an older workbook through the Excel
UI. The feature only works for files stored in OneDrive or SharePoint Online.
From the Excel workbook in which the script was run, use the following steps to undo
the effects.
See also
View previous versions of Office files
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Office Scripts samples and scenarios
Article • 12/28/2023
This section contains Office Scripts based solutions that help end users achieve
automation of daily tasks. It contains realistic scenarios that users face and provides
detailed solutions.
) Important
Be sure you meet the prerequisites for Office Scripts before trying the samples. The
requirements for your Microsoft 365 subscription and account are found under
Platform support.
Basics
ノ Expand table
Project Details
Ranges: Work with the grid These samples show how to work the Range object, which is
central to most scripts.
Conditional formatting samples These samples show how to apply different styles of
conditional formatting to a range.
Data validation samples: These samples show how to use data validation to mandate
Dropdown lists, prompts, and specific conditions for cell data and how the user is alerted
warning pop-ups to these rules.
Row and column visibility samples A collection of samples that demonstrate how to show,
hide, and freeze rows and columns.
Quick scenarios
Be sure to download the sample workbooks included with each sample. That lets you
skip setup and understand the core concept the sample demonstrates.
ノ Expand table
Project Details
Copy multiple Excel tables This sample combines data from multiple Excel tables into a single
into a single table table that includes all the rows.
Create a workbook table of This sample creates a table of contents with links to each
contents worksheet.
Count blank rows in a This sample detects if there are any blank rows in sheets where you
specific sheet or in all anticipate data to be present and then report the blank row count
sheets for usage in a Power Automate flow.
Manage calculation mode This sample shows how to use the calculation mode and calculate
in Excel methods in Excel using Office Scripts.
Move rows across tables This sample shows how to move rows across tables by saving
filters, then processing and reapplying the filters.
Notify people with This sample adds comments to a cell including @mentioning a
comments colleague.
Output Excel data as JSON This solution shows how to output Excel table data as JSON to use
in Power Automate.
Remove hyperlinks from This sample clears all of the hyperlinks from the current worksheet.
each cell in an Excel
worksheet
Set conditional formatting This sample applies formatting based on values in adjacent
for cross-column columns. It also gets user input through script parameters.
comparisons
Project Details
Use external fetch calls This sample uses fetch to get information from GitHub for the
script.
Cross-application scenarios
Use Power Automate to connect other applications to Excel. Have your scripts power
emails, forms, Teams messages, and more. These samples include step-by-step
instructions to create each Power Automate flow.
ノ Expand table
Project Details
Combine worksheets This sample uses Office Scripts and Power Automate to pull data from
into a single workbook other workbooks into a single workbook.
Convert CSV files to This sample uses Office Scripts and Power Automate to create .xlsx files
Excel workbooks from .csv files.
Cross-reference This sample uses Office Scripts and Power Automate to cross-reference
workbooks and validate information in different workbooks.
Email chart and table This sample uses Office Scripts and Power Automate actions to create a
images chart and send that chart as an image by email.
Record day-to-day This sample uses a scheduled Power Automate flow to record daily
changes in Excel and readings and report the changes.
report them with a flow
Run a script on all Excel This sample performs a set of automation tasks on all files situated in a
files in a folder folder on OneDrive for Business (can also be used for a SharePoint
folder). It performs calculations on the Excel files, adds formatting, and
inserts a comment that @mentions a colleague.
Write a large dataset This sample shows how to work with a large range as smaller
subranges. This helps flows handle data transfer limits and operation
timeouts.
Real-world scenarios
Office Scripts can automate parts of your daily routine. These day-to-day tasks often
exist in unique ecosystems, with Excel workbooks that are set up in particular ways.
These larger scenario samples demonstrate such real-world use-cases. They include
both the Office Scripts and the workbooks, so you can see the scenario from end to end.
ノ Expand table
Scenario Details
Analyze web This scenario features a script that parses web traffic records to determine
downloads a user's country of origin. It showcases the skills of text parsing, using
subfunctions in scripts, applying conditional formatting, and working with
tables.
Fetch and graph This scenario uses an Office Script to pull data from an external source
water-level data (the NOAA Tides and Currents database ) and graph the resulting
from NOAA information. It highlights the skills of using fetch to get data and using
charts.
Grade calculator This scenario features a script that validates an instructor's record for their
class's grades. It showcases the skills of error checking, cell formatting, and
regular expressions.
Schedule interviews This scenario shows how to use an Excel spreadsheet to manage interview
in Teams meeting times and make a flow to schedules meetings in Teams.
Task reminders as This scenario uses an Office Script in a Power Automate flow to send
Teams cards reminders to coworkers to update a project's status. It highlights the skills
of Power Automate integration and data transfer to and from scripts.
ノ Expand table
Project Details
Game of Life The "Ready Player Zero" blog by Yutao Huang on the Excel Tech Community
includes a script to model John Conway's The Game of Life .
Punch clock This script was contributed by Brian Gonzalez . The scenario features a
button script and a script button that records the current time.
Seasons greetings This script was contributed by Leslie Black in the spirit of the holiday
animation season! It's a fun script that shows a singing Christmas tree in Excel using
Office Scripts.
The following samples are simple scripts for you to try on your own workbooks. They
form the building blocks to larger solutions. Expand these scripts to extend your
solution and solve common problems.
TypeScript
TypeScript
TypeScript
TypeScript
// Get the cell to the right of the active cell and set its value and
color.
let rightCell = activeCell.getOffsetRange(0,1);
rightCell.setValue("Right cell");
console.log(`The right cell's address is: ${rightCell.getAddress()}`);
rightCell.getFormat().getFont().setColor("Magenta");
rightCell.getFormat().getFill().setColor("Cyan");
// Get the cell to the above of the active cell and set its value and
color.
// Note that this operation will fail if the active cell is in the top
row.
let aboveCell = activeCell.getOffsetRange(-1, 0);
aboveCell.setValue("Above cell");
console.log(`The above cell's address is: ${aboveCell.getAddress()}`);
aboveCell.getFormat().getFont().setColor("White");
aboveCell.getFormat().getFill().setColor("Black");
}
TypeScript
// Get the cell that's one row above and one column to the left of the
active cell.
let cornerCell = activeCell.getOffsetRange(-1,-1);
// Get a range that includes all the cells surrounding the active cell.
let surroundingRange = cornerCell.getResizedRange(2, 2)
// Copy the formatting from the active cell to the new range.
surroundingRange.copyFrom(
activeCell, /* The source range. */
ExcelScript.RangeCopyType.formats /* What to copy. */
);
}
TypeScript
// Set the color of the current cell to that random hexadecimal code.
range.getCell(row, col).getFormat().getFill().setColor(colorString);
}
}
}
TypeScript
Single formula
This script sets a cell's formula, then displays how Excel stores the cell's formula and
value separately.
TypeScript
// Set A1 to 2.
let a1 = selectedSheet.getRange("A1");
a1.setValue(2);
TypeScript
TypeScript
// In each formula range: get the current value, clear the contents, and
set the value as the old one.
// This removes the formula but keeps the result.
formulaCells.getAreas().forEach((range) => {
let currentValues = range.getValues();
range.clear(ExcelScript.ClearApplyTo.contents);
range.setValues(currentValues);
});
}
See also
Sudhi Ramamurthy's "Range basics" on YouTube
Office Scripts samples and scenarios
Tutorial: Create and format an Excel table
Conditional formatting samples
Article • 12/29/2023
This sample workbook contains worksheets ready to test with the sample scripts.
Cell value
Cell value conditional formatting applies a format to every cell that contains a value
meeting a given criteria. This helps quickly spot important data points.
The following sample applies cell value conditional formatting to a range. Any value less
than 60 will have the cell's fill color changed and the font made italic.
TypeScript
ratingColumn.addConditionalFormat(ExcelScript.ConditionalFormatType.cellValu
e).getCellValue();
// Create the condition, in this case when the cell value is less than
60
let rule: ExcelScript.ConditionalCellValueRule = {
formula1: "60",
operator: ExcelScript.ConditionalCellValueOperator.lessThan
};
cellValueConditionalFormatting.setRule(rule);
Color scale
Color scale conditional formatting applies a color gradient across a range. The cells with
the minimum and maximum values of the range use the colors specified, with other cells
scaled proportionally. An optional midpoint color provides more contrast.
This following sample applies a red, white, and blue color scale to the selected range.
TypeScript
// Set the colors for the three parts of the scale: minimum, midpoint,
and maximum.
conditionalFormatting.getColorScale().setCriteria({
minimum: {
color: "#5A8AC6", /* A pale blue. */
type:
ExcelScript.ConditionalFormatColorCriterionType.lowestValue
},
midpoint: {
color: "#FCFCFF", /* Slightly off-white. */
formula: '=50', type:
ExcelScript.ConditionalFormatColorCriterionType.percentile
},
maximum: {
color: "#F8696B", /* A pale red. */
type:
ExcelScript.ConditionalFormatColorCriterionType.highestValue
}
});
}
Data bar
Data bar conditional formatting adds a partially-filled bar in the background of a cell.
The fullness of the bar is defined by the value in the cell and the range specified by the
format.
The following sample creates data bar conditional formatting on the selected ranged.
The scale of the data bar goes from 0 to 1200.
TypeScript
Icon set
Icon set conditional formatting adds icons to each cell in a range. The icons come from
a specified set. Icons are applied based on an ordered array of criteria, with each
criterion mapping to a single icon.
The following sample applies the "three traffic light" icon set conditional formatting to a
range.
TypeScript
conditionalFormatting.getIconSet().setStyle(ExcelScript.IconSet.threeTraffic
Lights1);
conditionalFormatting.getIconSet().setCriteria([
{ // Use the red light as the default for positive values.
formula: '=0', operator:
ExcelScript.ConditionalIconCriterionOperator.greaterThanOrEqual,
type: ExcelScript.ConditionalFormatIconRuleType.number
},
{ // The yellow light is applied to all values 6 and greater. The
replaces the red light when applicable.
formula: '=6', operator:
ExcelScript.ConditionalIconCriterionOperator.greaterThanOrEqual,
type: ExcelScript.ConditionalFormatIconRuleType.number
},
{ // The green light is applied to all values 8 and greater. As with
the yellow light, the icon is replaced when the new criteria is met.
formula: '=8', operator:
ExcelScript.ConditionalIconCriterionOperator.greaterThanOrEqual,
type: ExcelScript.ConditionalFormatIconRuleType.number
}
]);
}
Preset
Preset conditional formatting applies a specified format to a range based on common
scenarios, such as blank cells and duplicate values. The full list of preset criteria is
provided by the ConditionalFormatPresetCriterion enum.
The following sample gives a yellow fill to any blank cell in the range.
TypeScript
// Set a rule to apply the conditional format when cells are left blank.
const blankRule: ExcelScript.ConditionalPresetCriteriaRule = {
criterion: ExcelScript.ConditionalFormatPresetCriterion.blanks
};
presetFormat.setRule(blankRule);
}
Text comparison
Text comparison conditional formatting formats cells based on their text content. The
formatting is applied when the text begins with, contains, ends with, or doesn't contain
the given substring.
The following sample marks any cell in the range that contains the text "review".
TypeScript
// Set the conditional format to provide a light red fill and make the
font bold.
textConditionFormat.getFormat().getFill().setColor("#F8696B");
textConditionFormat.getFormat().getFont().setBold(true);
// Apply the condition rule that the text contains with "review".
const textRule: ExcelScript.ConditionalTextComparisonRule = {
operator: ExcelScript.ConditionalTextOperator.contains,
text: "review"
};
textConditionFormat.setRule(textRule);
}
Top/bottom
Top/bottom conditional formatting marks the highest or lowest values in a range. The
highs and lows are based on either raw values or percentages.
The following sample applies conditional formatting to show the two highest numbers
in the range.
TypeScript
// Set the fill color to green and the font to bold for the top 2 values
in the range.
const topBottomFormat =
dataRange.addConditionalFormat(ExcelScript.ConditionalFormatType.topBottom).
getTopBottom();
topBottomFormat.getFormat().getFill().setColor("green");
topBottomFormat.getFormat().getFont().setBold(true);
topBottomFormat.setRule({
rank: 2, /* The numeric threshold. */
type: ExcelScript.ConditionalTopBottomCriterionType.topItems /* The
type of the top/bottom condition. */
});
}
Custom conditions
Custom conditional formatting allows for complex formulas to define when formatting is
applied. Use this when the other options aren't enough.
The following sample sets a custom conditional formatting on the selected range. A
light-green fill and bold font are applied to a cell if the value is larger than the value in
the row's previous column.
TypeScript
Data validation helps the user ensure consistency in a worksheet. Use these features to
limit what can be entered into a cell and provide warnings or errors to users when those
conditions aren't met. To learn more about data validation in Excel, see Apply data
validation to cells .
TypeScript
// Apply the data validation to the first cell in the selected range.
const targetCell = selectedRange.getCell(0,0);
const dataValidation = targetCell.getDataValidation();
TypeScript
/**
* This script creates a text prompt that's shown in C2:C8 when a user
enters the cell.
*/
function main(workbook: ExcelScript.Workbook) {
// Get the data validation object for C2:C8 in the current worksheet.
const selectedSheet = workbook.getActiveWorksheet();
const dataValidation =
selectedSheet.getRange("C2:C8").getDataValidation();
TypeScript
/**
* This script creates a data validation rule for the range B2:B5.
* All values in that range must be a positive number.
* Attempts to enter other values are blocked and an error message appears.
*/
function main(workbook: ExcelScript.Workbook) {
// Get the range B2:B5 in the active worksheet.
const currentSheet = workbook.getActiveWorksheet();
const positiveNumberOnlyCells = currentSheet.getRange("B2:B5");
// Create an alert to appear when data other than positive numbers are
entered.
const positiveNumberOnlyAlert: ExcelScript.DataValidationErrorAlert = {
message: "Positive numbers only.",
showAlert: true,
style: ExcelScript.DataValidationAlertStyle.stop,
title: "Invalid data"
};
rangeDataValidation.setErrorAlert(positiveNumberOnlyAlert);
}
JavaScript Date samples
Article • 09/11/2023
TypeScript
// Get the current date and time with the JavaScript Date object.
let date = new Date(Date.now());
TypeScript
See also
Use built-in JavaScript objects in Office Scripts
Add images to a workbook
Article • 10/25/2023
This sample shows how to work with images using an Office Script in Excel.
Scenario
Images help with branding, visual identity, and templates. They help make a workbook
more than just a giant table.
The first sample copies an image from one worksheet to another. This could be used to
put your company's logo in the same position on every sheet.
The second sample copies an image from a URL. This could be used to copy photos that
a colleague stored in a shared folder to a related workbook. Please note that this sample
can't be adapted to work with a local image file, as that isn't supported by Office Scripts.
TypeScript
/**
* This script transfers an image from one worksheet to another.
*/
function main(workbook: ExcelScript.Workbook)
{
// Get the worksheet with the image on it.
let firstWorksheet = workbook.getWorksheet("FirstSheet");
) Important
This sample won't work in Power Automate because of the fetch call.
TypeScript
/**
* Converts an ArrayBuffer containing a .png image into a base64-encoded
string.
*/
function convertToBase64(input: ArrayBuffer) {
const uInt8Array = new Uint8Array(input);
const count = uInt8Array.length;
These samples demonstrate how to show, hide, and freeze rows and columns.
Hide columns
This script hides columns "D", "F", and "J".
TypeScript
TypeScript
TypeScript
TypeScript
Filter a table
This sample filters an existing table using the values in one of the columns.
TypeScript
TypeScript
/**
* Convert a column into a set so it only contains unique values.
*/
function columnToSet(column: ExcelScript.TableColumn): string[] {
const range = column.getRangeBetweenHeaderAndTotal().getValues() as
string[][];
const columnSet: string[] = [];
range.forEach((value) => {
if (!columnSet.includes(value[0])) {
columnSet.push(value[0]);
}
});
return columnSet;
}
// Get the table header above the current cell by referencing its column.
const entireColumn = cell.getEntireColumn();
const intersect = entireColumn.getIntersection(currentTable.getRange());
const headerCellValue = intersect.getCell(0, 0).getValue() as string;
If you wish to learn more about how to save the filter prior to clearing it (and re-
apply later), see Move rows across tables by saving filters, a more advanced
sample.
TypeScript
// Set the formula of the fourth column to be the product of the values
found
// in that row's second and third columns.
const combinedColumn = table.getColumn(4).getRangeBetweenHeaderAndTotal();
combinedColumn.setFormula(`=[@[${nameOfColumn2}]]*[@[${nameOfColumn3}]]`);
}
Jan 45 5
Feb 45 3
Mar 45 6
ノ Expand table
Jan 45 5 225
Feb 45 3 135
Mar 45 6 270
Combine data from multiple Excel tables
into a single table
Article • 10/25/2023
This sample combines data from multiple Excel tables into a single table that includes all
the rows. It assumes that all tables being used have the same structure.
TypeScript
// Get the header values for the first table in the workbook.
// This also saves the table list before we add the new, combined table.
const tables = workbook.getTables();
const headerValues = tables[0].getHeaderRowRange().getTexts();
console.log(headerValues);
// If the table is not empty, add its rows to the combined table.
if (rowCount > 0) {
combinedTable.addRows(-1, dataValues);
}
}
}
TypeScript
// Create a new table with the same headers as the other tables.
const headerValues = workbook.getWorksheet(sheetNames[0]).getTables()
[0].getHeaderRowRange().getTexts();
const targetRange =
newSheet.getRange('A1').getResizedRange(headerValues.length-1,
headerValues[0].length-1);
targetRange.setValues(headerValues);
const combinedTable = newSheet.addTable(targetRange.getAddress(), true);
This sample shows how to create a table of contents for the workbook. Each entry in the
table of contents is a hyperlink to one of the worksheets in the workbook.
TypeScript
// Loop through all worksheets in the workbook, except the first one.
for (let i = 1; i < worksheets.length; i++) {
// Create a row for each worksheet with its index and linked name.
tocRange.getCell(i, 0).setValue(i);
tocRange.getCell(i, 1).setHyperlink({
textToDisplay: worksheets[i].getName(),
documentReference: `'${worksheets[i].getName()}'!A1`
});
};
Count blank rows on a given sheet: Traverses the used range on a given worksheet
and returns a blank row count.
Count blank rows on all sheets: Traverses the used range on all of the worksheets
and returns a blank row count.
7 Note
For your script, a blank row is any row where there's no data. The row can have
formatting.
// Return the number of empty rows for use in a Power Automate flow.
return emptyRows;
}
Sample code: Count blank rows on all sheets
TypeScript
// Return the number of empty rows for use in a Power Automate flow.
return emptyRows;
}
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Manage calculation mode in Excel
Article • 11/17/2022
This sample shows how to use the calculation mode and calculate methods in Excel
using Office Scripts. You can try the script on any Excel file.
Scenario
Workbooks with large numbers of formulas can take a while to recalculate. Rather than
letting Excel control when calculations happen, you can manage them as part of your
script. This will help with performance in certain scenarios.
The sample script sets the calculation mode to manual. This means that the workbook
will only recalculate formulas when the script tells it to (or you manually calculate
through the UI ). The script then displays the current calculation mode and fully
recalculates the entire workbook.
workbook.getApplication().setCalculationMode(ExcelScript.CalculationMode.man
ual);
// Get and log the calculation mode.
const calcMode = workbook.getApplication().getCalculationMode();
console.log(calcMode);
// Manually calculate the file.
workbook.getApplication().calculate(ExcelScript.CalculationType.full);
}
Selects rows from the source table where the value in a column is equal to some
value ( FILTER_VALUE in the script).
Moves all selected rows into the target table in another worksheet.
Reapplies the relevant filters to the source table.
TypeScript
// You can change these names to match the data in your workbook.
const TARGET_TABLE_NAME = 'Table1';
const SOURCE_TABLE_NAME = 'Table2';
// Get the intersection between table address and the entire row where
we found the match. This provides the address of the range to remove.
let address =
sourceRange.getIntersection(sourceRange.getCell(i,0).getEntireRow()).getAddr
ess();
rowAddressToRemove.push(address);
}
}
sourceTable.getColumnByName(columnName).getFilter().apply(originalTableFilte
rs[columnName]);
});
}
In the first variant, the rows are selected by applying the table filter and reading
the visible range.
In the second, the rows are selected by reading the values and extracting the row
values (which is what the sample on this page uses).
Notify people with comments
Article • 12/05/2023
Example scenario
The team lead maintains the shift schedule. They assign an employee ID to the shift
record. If the team lead wishes to notify the employee, they add a comment that
@mentions the employee. The employee is emailed with a custom message from the
worksheet. Subsequently, the employee can view the workbook and respond to the
comment at their convenience.
Solution
1. The script extracts employee information from the employee worksheet.
2. The script then adds a comment (including the relevant employee email) to the
appropriate cell in the shift record.
3. Existing comments in the cell are removed before adding the new comment.
TypeScript
Excel table data can be represented as an array of objects in the form of JSON . Each
object represents a row in the table. This helps extract the data from Excel in a
consistent format that is visible to the user. The data can then be given to other systems
through Power Automate flows.
A variation of this sample also includes the hyperlinks in one of the table columns. This
allows additional levels of cell data to be surfaced in the JSON.
You can change the interface TableData structure to match your table columns.
Note that for column names with spaces, be sure to place your key in quotation
marks, such as with "Event ID" in the sample. For more information about working
with JSON, read Use JSON to pass data to and from Office Scripts.
TypeScript
return objectArray;
}
interface TableData {
"Event ID": string
Date: string
Location: string
Capacity: string
Speakers: string
}
[{
"Event ID": "E107",
"Date": "2020-12-10",
"Location": "Montgomery",
"Capacity": "10",
"Speakers": "Debra Berger"
}, {
"Event ID": "E108",
"Date": "2020-12-11",
"Location": "Montgomery",
"Capacity": "10",
"Speakers": "Delia Dennis"
}, {
"Event ID": "E109",
"Date": "2020-12-12",
"Location": "Montgomery",
"Capacity": "10",
"Speakers": "Diego Siciliani"
}, {
"Event ID": "E110",
"Date": "2020-12-13",
"Location": "Boise",
"Capacity": "25",
"Speakers": "Gerhart Moller"
}, {
"Event ID": "E111",
"Date": "2020-12-14",
"Location": "Salt Lake City",
"Capacity": "20",
"Speakers": "Grady Archie"
}, {
"Event ID": "E112",
"Date": "2020-12-15",
"Location": "Fremont",
"Capacity": "25",
"Speakers": "Irvin Sayers"
}, {
"Event ID": "E113",
"Date": "2020-12-16",
"Location": "Salt Lake City",
"Capacity": "20",
"Speakers": "Isaiah Langer"
}, {
"Event ID": "E114",
"Date": "2020-12-17",
"Location": "Salt Lake City",
"Capacity": "20",
"Speakers": "Johanna Lorenz"
}]
7 Note
The script always extracts hyperlinks from the 4th column (0 index) of the table. You
can change that order or include multiple columns as hyperlink data by modifying
the code under the comment // For the 4th column (0 index), extract the
hyperlink and use that instead of text.
TypeScript
let object = {}
for (let j = 0; j < values[i].length; j++) {
// For the 4th column (0 index), extract the hyperlink and use that
instead of text.
if (j === 4) {
object[objectKeys[j]] = range.getCell(i, j).getHyperlink().address;
} else {
object[objectKeys[j]] = values[i][j];
}
}
objectArray.push(object as TableData);
}
return objectArray;
}
interface TableData {
"Event ID": string
Date: string
Location: string
Capacity: string
"Search link": string
Speakers: string
}
[{
"Event ID": "E107",
"Date": "2020-12-10",
"Location": "Montgomery",
"Capacity": "10",
"Search link": "https://www.google.com/search?q=Montgomery",
"Speakers": "Debra Berger"
}, {
"Event ID": "E108",
"Date": "2020-12-11",
"Location": "Montgomery",
"Capacity": "10",
"Search link": "https://www.google.com/search?q=Montgomery",
"Speakers": "Delia Dennis"
}, {
"Event ID": "E109",
"Date": "2020-12-12",
"Location": "Montgomery",
"Capacity": "10",
"Search link": "https://www.google.com/search?q=Montgomery",
"Speakers": "Diego Siciliani"
}, {
"Event ID": "E110",
"Date": "2020-12-13",
"Location": "Boise",
"Capacity": "25",
"Search link": "https://www.google.com/search?q=Boise",
"Speakers": "Gerhart Moller"
}, {
"Event ID": "E111",
"Date": "2020-12-14",
"Location": "Salt Lake City",
"Capacity": "20",
"Search link": "https://www.google.com/search?q=salt+lake+city",
"Speakers": "Grady Archie"
}, {
"Event ID": "E112",
"Date": "2020-12-15",
"Location": "Fremont",
"Capacity": "25",
"Search link": "https://www.google.com/search?q=Fremont",
"Speakers": "Irvin Sayers"
}, {
"Event ID": "E113",
"Date": "2020-12-16",
"Location": "Salt Lake City",
"Capacity": "20",
"Search link": "https://www.google.com/search?q=salt+lake+city",
"Speakers": "Isaiah Langer"
}, {
"Event ID": "E114",
"Date": "2020-12-17",
"Location": "Salt Lake City",
"Capacity": "20",
"Search link": "https://www.google.com/search?q=salt+lake+city",
"Speakers": "Johanna Lorenz"
}]
This sample clears all of the hyperlinks from the current worksheet. It traverses the
worksheet and if there is any hyperlink associated with the cell, it clears the hyperlink yet
retains the cell value as is. Also logs the time it takes to complete traversal.
7 Note
TypeScript
cell.getFormat().getFont().setUnderline(ExcelScript.RangeUnderlineStyle.none
);
cell.getFormat().getFont().setColor('Black');
clearedCount++;
}
}
}
TypeScript
Filter a table
This sample filters an existing table using the values in one of the columns.
TypeScript
TypeScript
/**
* Convert a column into a set so it only contains unique values.
*/
function columnToSet(column: ExcelScript.TableColumn): string[] {
const range = column.getRangeBetweenHeaderAndTotal().getValues() as
string[][];
const columnSet: string[] = [];
range.forEach((value) => {
if (!columnSet.includes(value[0])) {
columnSet.push(value[0]);
}
});
return columnSet;
}
// Get the table header above the current cell by referencing its column.
const entireColumn = cell.getEntireColumn();
const intersect = entireColumn.getIntersection(currentTable.getRange());
const headerCellValue = intersect.getCell(0, 0).getValue() as string;
If you wish to learn more about how to save the filter prior to clearing it (and re-
apply later), see Move rows across tables by saving filters, a more advanced
sample.
TypeScript
// Set the formula of the fourth column to be the product of the values
found
// in that row's second and third columns.
const combinedColumn = table.getColumn(4).getRangeBetweenHeaderAndTotal();
combinedColumn.setFormula(`=[@[${nameOfColumn2}]]*[@[${nameOfColumn3}]]`);
}
Jan 45 5
Feb 45 3
Mar 45 6
ノ Expand table
Jan 45 5 225
Feb 45 3 135
Mar 45 6 270
Set conditional formatting for cross-
column comparisons
Article • 09/14/2023
This sample shows how to apply conditional formatting to a range. The conditions used
are comparing values to those in an adjacent column. Additionally, this sample uses
parameters to get user input. This lets the person running the script select the range, the
type of comparison, and the colors.
/**
* Formats a range on the current sheet based on values in an adjacent
column.
* @param rangeAddress The A1-notation range to format.
* @param compareTo The adjacent column to compare against.
* @param colorIfGreater The color of the cell if the value is greater than
the adjacent column.
* @param colorIfEqual The color of the cell if the value is equal to the
adjacent column.
* @param colorIfLess The color of the cell if the value is less than the
adjacent column.
*/
function main(
workbook: ExcelScript.Workbook,
rangeAddress: string, compareTo: "Left" | "Right",
colorIfGreater: "Red" | "Green" | "Yellow" | "None",
colorIfLess: "Red" | "Green" | "Yellow" | "None",
colorIfEqual: "Red" | "Green" | "Yellow" | "None"
) {
// Get the specified range.
const selectedSheet = workbook.getActiveWorksheet();
const range = selectedSheet.getRange(rangeAddress);
// Get the address of the first adjacent cell of the adjacent column.
let adjacentColumn: string;
if (compareTo == "Left") {
adjacentColumn = range.getColumnsBefore().getCell(0, 0).getAddress();
} else {
adjacentColumn = range.getColumnsAfter().getCell(0, 0).getAddress();
}
range.addConditionalFormat(ExcelScript.ConditionalFormatType.cellValue).getC
ellValue(),
colorIfGreater,
formula,
ExcelScript.ConditionalCellValueOperator.greaterThan);
setConditionalFormatting(
range.addConditionalFormat(ExcelScript.ConditionalFormatType.cellValue).getC
ellValue(),
colorIfEqual,
formula,
ExcelScript.ConditionalCellValueOperator.equalTo);
setConditionalFormatting(
range.addConditionalFormat(ExcelScript.ConditionalFormatType.cellValue).getC
ellValue(),
colorIfLess,
formula,
ExcelScript.ConditionalCellValueOperator.lessThan);
}
function setConditionalFormatting(
conditionalFormat: ExcelScript.CellValueConditionalFormat,
color: "Red" | "Green" | "Yellow" | "None",
formula: string,
operator: ExcelScript.ConditionalCellValueOperator
) {
// Pick the fill and font colors based on the preset color choices.
if (color == "Red") {
conditionalFormat.getFormat().getFont().setColor("#9C0006");
conditionalFormat.getFormat().getFill().setColor("#FFC7CE");
} else if (color == "Green") {
conditionalFormat.getFormat().getFont().setColor("#001600");
conditionalFormat.getFormat().getFill().setColor("#C6EFCE");
} else if (color == "Yellow") {
conditionalFormat.getFormat().getFont().setColor("#9C5700");
conditionalFormat.getFormat().getFill().setColor("#FFEB9C");
} else { /* None */
return;
}
This script gets basic information about a user's GitHub repositories. It shows how to
use fetch in a simple scenario. For more information about using fetch or other
external calls, read External API call support in Office Scripts. For information about
working with JSON objects, like what is returned by the GitHub APIs, read Use JSON
to pass data to and from Office Scripts.
Learn more about the GitHub APIs being used in the GitHub API reference . You can
also see the raw API call output by visiting
https://api.github.com/users/{USERNAME}/repos in a web browser (be sure to replace
the {USERNAME} placeholder with your GitHub ID).
This sample shows how to pull data from multiple workbooks into a single, centralized
workbook. It uses two scripts: one to retrieve information from a workbook and another
to create new worksheets with that information. It combines the scripts in a Power
Automate flow that acts on an entire OneDrive folder.
) Important
This sample only copies the values from the other workbooks. It does not preserve
formatting, charts, tables, or other objects.
Solution
1. Create a new Excel file in your OneDrive. The file name "Combination.xlsx" is used
in this sample.
2. Create and save the two scripts from this sample.
3. Create a folder in your OneDrive and add one or more workbooks with data to it.
The folder name "output" is used in this sample.
4. Build a flow (as described in the Power Automate flow section of this article) to
perform these steps:
a. List all the files the "output" folder.
b. Use the Return worksheet data script to get the data from every worksheet in
each of the workbooks.
c. Use the Add worksheets script to create a new worksheet in the
"Combination.xlsx" workbook for every worksheet in all the other files.
/**
* This script returns the values from the used ranges on each worksheet.
*/
function main(workbook: ExcelScript.Workbook): WorksheetData[] {
// Create an object to return the data from each worksheet.
let worksheetInformation: WorksheetData[] = [];
// Get the data from every worksheet, one at a time.
workbook.getWorksheets().forEach((sheet) => {
let values = sheet.getUsedRange()?.getValues();
worksheetInformation.push({
name: sheet.getName(),
data: values as string[][]
});
});
return worksheetInformation;
}
// An interface to pass the worksheet name and cell values through a flow.
interface WorksheetData {
name: string;
data: string[][];
}
/**
* This script creates a new worksheet in the current workbook for each
WorksheetData object provided.
*/
function main(workbook: ExcelScript.Workbook, workbookName: string,
worksheetInformation: WorksheetData[]) {
// Add each new worksheet.
worksheetInformation.forEach((value) => {
let sheet = workbook.addWorksheet(`${workbookName}.${value.name}`);
// An interface to pass the worksheet name and cell values through a flow.
interface WorksheetData {
name: string;
data: string[][];
}
Power Automate flow: Combine worksheets
into a single workbook
1. Sign into Power Automate and create a new Instant cloud flow.
3. Get all the workbooks you want to combine from their folder. Add an action and
choose the OneDrive for Business connector's List files in folder action. For the
Folder field, use the file picker to select the "output" folder.
4. Add an action to run the Return worksheet data script to get all the data from
each of the workbooks. Choose the Excel Online (Business) connector's Run script
action. Use the following values for the action. Note that when you add the Id for
the file, Power Automate will wrap the action in a For each control, so the action
will be performed on every file.
Select the Switch to input entire array button to add the array object directly,
instead of individual items for the array. Do this before entering result.
6. Save the flow. The flow designer should look like the following image.
7. Use the Test button on the flow editor page or run the flow through your My flows
tab. Be sure to allow access when prompted.
Troubleshooting
A resource with the same name or identifier already exists: This error likely
indicates the "Combination.xlsx" workbook already has a worksheet with the same
name. This will happen if you run the flow multiple times with the same
workbooks. Create a new workbook each time to store the combined data or use
different file names in the "output" folder.
The argument is invalid or missing or has an incorrect format: This error can
mean that the generated worksheet name doesn't meet Excel's requirements .
This is likely because the name is too long. If the worksheet names will be more
than 30 characters replace the code in "Add worksheets" that calls addWorksheet
with something that shortens the string. Since the workbook name itself might be
too long, add an incrementing number to the end of the worksheet name. Declare
this number outside of the forEach loop.
TypeScript
let worksheetNumber = 1;
// Add each new worksheet.
worksheetInformation.forEach((value) => {
let worksheetName = `${workbookName}.${value.name}`;
let sheet =
workbook.addWorksheet(`${worksheetName.substr(0,30)}${worksheetNumber++
}`);
Additionally, if the workbook names are longer than 30 characters, you'll need to
shorten them in the flow. First, you must create a variable in the flow to track the
workbook count. This will avoid identical shortened names being passed to the
script. Add an Initialize variable action before the flow (of Type "Integer") and an
Increment variable action between the two Run script actions. Then, instead of
using Name as the workbookName in "Run script 1", use the expression
substring(items('Apply_to_each')?['Name'],0,min(length(items('Apply_to_each')?
['Name']),20)) and the dynamic content from your variable. This shortens the
Rather than making the flow and script more complicated, it might be easier
to guarantee the file and worksheet names are short enough.
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Convert CSV files to Excel workbooks
Article • 02/07/2024
Many services export data as comma-separated value (CSV) files. This solution
automates the process of converting those CSV files to Excel workbooks in the .xlsx file
format. It uses a Power Automate flow to find files with the .csv extension in a
OneDrive folder and an Office Script to copy the data from the .csv file into a new Excel
workbook.
Solution
1. Store the .csv files and a blank "Template" .xlsx file in a OneDrive folder.
2. Create an Office Script to parse the CSV data into a range.
3. Create a Power Automate flow to read the .csv files and pass their contents to the
script.
Sample files
Download convert-csv-example.zip to get the Template.xlsx file and two sample .csv
files. Extract the files into a folder in your OneDrive. This sample assumes the folder is
named "output".
Add the following script to the sample workbook. In Excel, use Automate > New Script
to paste the code and save the script. Save it as Convert CSV and try the sample
yourself!
/**
* Convert incoming CSV data into a range and add it to the workbook.
*/
function main(workbook: ExcelScript.Workbook, csv: string) {
let sheet = workbook.getWorksheet("Sheet1");
/*
* For each row, match the comma-separated sections.
* For more information on how to use regular expressions to parse CSV
files,
* see this Stack Overflow post:
https://stackoverflow.com/a/48806378/9227753
*/
const csvMatchRegex = /(?:,|\n|^)("(?:(?:"")*[^"]*)*"|[^",\n]*|(?:\n|$))/g
rows.forEach((value, index) => {
if (value.length > 0) {
let row = value.match(csvMatchRegex);
2. Set the flow to Repeat every "1" "Day" and select Create.
3. Get the template Excel file. This is the basis for all the converted .csv files. In the
flow builder, select the + button and Add an action. Select the OneDrive for
Business connector's Get file content action. Provide the file path to the
"Template.xlsx" file.
File: /output/Template.xlsx
4. Rename the Get file content step. Select the current title, "Get file content", in the
action task pane. Change the name to "Get Excel template".
5. Add an action that gets all the files in the "output" folder. Choose the OneDrive for
Business connector's List files in folder action. Provide the folder path that
contains the .csv files.
Folder: /output
6. Add a condition so that the flow only operates on .csv files. Add the Condition
control action. Use the following values for the Condition.
Choose a value: Name (dynamic content from List files in folder). Note that
this dynamic content has multiple results, so a For each control surrounds the
Condition.
ends with (from the dropdown list)
Choose a value: .csv
7. The rest of the flow is under the If yes section, since we only want to act on .csv
files. Get an individual .csv file by adding an action that uses the OneDrive for
Business connector's Get file content action. Use the Id from the dynamic content
from List files in folder.
8. Rename the new Get file content step to "Get .csv file". This helps distinguish this
file from the Excel template.
9. Make the new .xlsx file, using the Excel template as the base content. Add an
action that uses the OneDrive for Business connector's Create file action. Use the
following values.
11. Save the flow. The flow designer should look like the following image.
12. Use the Test button on the flow editor page or run the flow through your My flows
tab. Be sure to allow access when prompted.
13. You should find new .xlsx files in the "output" folder, alongside the original .csv
files. The new workbooks contain the same data as the CSV files.
Troubleshooting
Script testing
To test the script without using Power Automate, assign a value to csv before using it.
Add the following code as the first line of the main function and select Run.
TypeScript
csv = `1, 2, 3
4, 5, 6
7, 8, 9`;
1. Replace the commas with semicolons in the regular expression statement. This
starts with let row = value.match .
TypeScript
2. Replace the comma with a semicolon in the check for the blank first cell. This starts
with if (row[0].charAt(0) .
TypeScript
3. Replace the comma with a semicolon in the line that removes the separation
character from the displayed text. This starts with row[index] = cell.indexOf .
TypeScript
7 Note
If your file uses tabs or any other character to separate the values, replace the ; in
the above substitutions with \t or whatever character is being used.
TypeScript
let rowCount = 0;
TypeScript
rowCount++;
if (rowCount % 5000 === 0) {
console.log("Syncing 5000 rows.");
}
2 Warning
If your CSV file is very large, you may have problems timing out in Power
Automate. You'll need to divide the CSV data into multiple files before converting
them into Excel workbooks.
Note that this sample doesn't create the .csv files in the flow, so this change needs to
happen in your custom part of the flow. You could also read and rewrite the .csv files
with the BOM, if you don't control how those files are created.
TypeScript
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our Provide product feedback
contributor guide.
Cross-reference Excel files with Power
Automate
Article • 04/05/2024
This solution shows how to compare data across two Excel files to find discrepancies. It
uses Office Scripts to analyze data and Power Automate to communicate between the
workbooks.
This sample passes data between workbooks using JSON objects. For more
information about working with JSON, read Use JSON to pass data to and from Office
Scripts.
Example scenario
You're an event coordinator who is scheduling speakers for upcoming conferences. You
keep the event data in one spreadsheet and the speaker registrations in another. To
ensure the two workbooks are kept in sync, you use a flow with Office Scripts to
highlight any potential problems.
1. event-data.xlsx
2. speaker-registrations.xlsx
Add the following scripts to try the sample yourself! In Excel, use Automate > New
Script to paste the code and save the scripts with the suggested names.
// Log the event data to the console and return it for a flow.
let stringResult = JSON.stringify(records);
console.log(stringResult);
return stringResult;
}
// Compare the data in the table to the keys passed into the script.
let keysObject = JSON.parse(keys) as EventData[];
let speakerSlotsRemaining = keysObject.map(value => value.capacity);
let overallMatch = true;
// Iterate over every row looking for differences from the other
worksheet.
let rows = range.getValues();
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
let [eventId, date, location, capacity] = row;
let match = false;
// Look at each key provided for a matching Event ID.
for (let keyIndex = 0; keyIndex < keysObject.length; keyIndex++) {
let event = keysObject[keyIndex];
if (event.eventId === eventId) {
match = true;
speakerSlotsRemaining[keyIndex]--;
// If there's a match on the event ID, look for things that don't
match and highlight them.
if (event.date !== date) {
overallMatch = false;
range.getCell(i, 1).getFormat()
.getFill()
.setColor("FFFF00");
}
if (event.location !== location) {
overallMatch = false;
range.getCell(i, 2).getFormat()
.getFill()
.setColor("FFFF00");
}
break;
}
}
1. Sign into Power Automate and create a new Instant cloud flow.
3. In the flow builder, select the + button and Add an action. Select the Excel Online
(Business) connector's Run script action. Use the following values for the action.
4. Rename this step. Select the current name "Run script" in the task pane and
change it to "Get event data".
5. Add a second action that uses the Excel Online (Business) connector's Run script
action. This action uses the returned values from the Get event data script as input
for the Validate event data script. Use the following values for the action.
6. Rename this step as well. Select the current name "Run script 1" in the task pane
and change it to "Validate speaker registration".
7. This sample uses Outlook as the email client. For this sample, add the Office 365
Outlook connector's Send and email (V2) action. You could use any email
connector that Power Automate supports. This action uses the returned values
from the Validate speaker registration script as the email body content. Use the
following values for the action.
10. You should receive an email saying "Mismatch found. Data requires your review."
This indicates there are differences between rows in speaker-registrations.xlsx and
rows in event-data.xlsx. Open speaker-registrations.xlsx to see several highlighted
cells where there are potential problems with the speaker registration listings.
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Use Office Scripts and Power Automate
to email images of a chart and table
Article • 06/11/2024
This sample uses Office Scripts and Power Automate to create a chart. It then emails
images of the chart and its base table.
Example scenario
Calculate to get latest results.
Create chart.
Get chart and table images.
Email the images with Power Automate.
Input data
Output chart
Email that was received through Power Automate flow
Solution
This solution has two parts:
TypeScript
// Get only the "Customer Name" and "Amount due" columns, then remove the
"Total" row.
const selectColumns = rows.map((row) => {
return [row[2], row[5]];
});
table.setShowTotals(true);
selectColumns.splice(selectColumns.length - 1, 1);
console.log(selectColumns);
// Get images of the chart and table, then return them for a Power
Automate flow.
const chartImage = chart.getImage();
const tableImage = table.getRange().getImage();
return { chartImage, tableImage };
}
3. Add a New step that uses the Excel Online (Business) connector with the Run
script action. Use the following values for the action.
4. This sample uses Outlook as the email client. You could use any email connector
Power Automate supports, but the rest of the steps assume that you chose
Outlook. Add a New step that uses the Office 365 Outlook connector and the
Send and email (V2) action. Use the following values for the action.
HTML
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Record day-to-day changes in Excel and
report them with a Power Automate
flow
Article • 04/05/2024
Power Automate and Office Scripts combine to handle repetitive tasks for you. In this
sample, you're tasked with recording a single numerical reading in a workbook every
day and reporting the change since yesterday. You'll build a flow to get that reading, log
it in the workbook, and report the change through an email.
TypeScript
// Add a row with the date, new value, and a formula calculating the
difference.
const currentDate = new Date(Date.now()).toLocaleDateString();
const newRow = [currentDate, newData, "=[@Reading]-
OFFSET([@Reading],-1,0)"];
table.addRow(-1, newRow);
// Return the difference between the newData and the previous entry.
const difference = Number.parseFloat(newData) - previousValue;
console.log(difference);
return difference.toString();
}
3. Select Create.
4. In a real flow, you'll add a step that gets your data. The data can come from
another workbook, a Teams adaptive card, or any other source. To test the sample,
make a test number. Add an action and choose the Initialize variable action. Give
it the following values.
a. Name: Input
b. Type: Integer
c. Value: 190000
5. Add an action and choose the Excel Online (Business) connector's Run script
action. Use the following values for the action.
a. Location: OneDrive for Business
b. Document Library: OneDrive
c. File: daily-readings.xlsx (Chosen through the file browser)
d. Script: Record daily value
e. newData: Input (dynamic content)
6. The script returns the daily reading difference as dynamic content named "result".
For the sample, you can email the information to yourself. Add an action and
choose the Outlook connector's Send an email (V2) action (or whatever email
client you prefer). Use the following values to complete the action.
a. To: Your email address
b. Subject: Daily reading change
c. Body: "Difference from yesterday:" result (dynamic content from Excel)
7. Save the flow and try it out. Use the Test button on the flow editor page. Be sure to
allow access when prompted.
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Run a script on all Excel files in a folder
Article • 04/05/2024
This project performs a set of automation tasks on all files situated in a folder on
OneDrive for Business. It could also be used on a SharePoint folder. It performs
calculations on the Excel files, adds formatting, and inserts a comment that
@mentions a colleague.
TypeScript
// Set the fill color to yellow for the cell with the highest value in the
"Amount Due" column.
highestAmountDue.getFormat().getFill().setColor("FFFF00");
3. In the flow builder, select the + button and Add an action. Use the OneDrive for
Business connector's List files in folder action. Use the following values for the
action.
5. Under the True branch, add a new action. Select the Excel Online (Business)
connector's Run script action. Use the following values for the action.
6. Save the flow. The flow designer should look like the following image.
7. Try it out! Use the Test button on the flow editor page or run the flow through
your My flows tab. Be sure to allow access when prompted.
The Range.setValues() API puts data in a range. This API has limitations depending on
various factors, such as data size and network settings. This means that if you attempt to
write a massive amount of information to a workbook as a single operation, you'll need
to write the data in smaller batches in order to reliably update a large range.
The first part of the sample shows how to write a large dataset in Excel. The second part
expands the example to be part of a Power Automate flow. This is necessary if your
script takes longer to run than the Power Automate action timeout.
For performance basics in Office Scripts, please read Improve the performance of your
Office Scripts.
7 Note
You can change the number of total rows being written by changing the value of
SAMPLE_ROWS . You can change the number of cells to write as a single action by
TypeScript
console.log(`Generating data...`)
let data: (string | number | boolean)[][] = [];
// Generate six columns of random data per row.
for (let i = 0; i < SAMPLE_ROWS; i++) {
data.push([i, ...[getRandomString(5), getRandomString(20),
getRandomString(10), Math.random()], "Sample data"]);
}
console.log(`Calling update range function...`);
const updated = updateRangeInBatches(sheet.getRange("B2"), data,
CELLS_IN_BATCH);
if (!updated) {
console.log(`Update did not take place or complete. Check and run
again.`);
}
}
function updateRangeInBatches(
startCell: ExcelScript.Range,
values: (string | boolean | number)[][],
cellsInBatch: number
): boolean {
return true;
}
/**
* A helper function that computes the target range and updates.
*/
function updateNextBatch(
startingCell: ExcelScript.Range,
data: (string | boolean | number)[][],
rowsPerBatch: number,
totalRowsUpdated: number
) {
const newStartCell = startingCell.getOffsetRange(totalRowsUpdated, 0);
const targetRange = newStartCell.getResizedRange(rowsPerBatch - 1,
data[0].length - 1);
console.log(`Updating batch at range ${targetRange.getAddress()}`);
const dataToUpdate = data.slice(totalRowsUpdated, totalRowsUpdated +
rowsPerBatch);
try {
targetRange.setValues(dataToUpdate);
} catch (e) {
throw `Error while updating the batch range: ${JSON.stringify(e)}`;
}
return;
}
/**
* A helper function that computes the target range given the target range's
starting cell
* and selected range and updates the values.
*/
function updateTargetRange(
targetCell: ExcelScript.Range,
values: (string | boolean | number)[][]
) {
const targetRange = targetCell.getResizedRange(values.length - 1,
values[0].length - 1);
console.log(`Updating the range: ${targetRange.getAddress()}`);
try {
targetRange.setValues(values);
} catch (e) {
throw `Error while updating the whole range: ${JSON.stringify(e)}`;
}
return;
}
// Credit: https://www.codegrepper.com/code-
examples/javascript/random+text+generator+javascript
function getRandomString(length: number): string {
var randomChars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var result = '';
for (var i = 0; i < length; i++) {
result += randomChars.charAt(Math.floor(Math.random() *
randomChars.length));
}
return result;
}
function main(
workbook: ExcelScript.Workbook,
startRow: number,
batchSize: number
): string[][] {
// This script only reads the first worksheet in the workbook.
const sheet = workbook.getWorksheets()[0];
// Get the next batch or the rest of the rows, whichever is smaller.
const rowCountToRead = Math.min(batchSize, (lastRowindex - startRow + 1));
const rangeToRead = sheet.getRangeByIndexes(startRow, 0, rowCountToRead,
lastColumnIndex + 1);
return rangeToRead.getValues() as string[][];
}
function main(
workbook: ExcelScript.Workbook,
data: string[][],
currentRow: number,
batchSize: number
): boolean {
// Get the first worksheet.
const sheet = workbook.getWorksheets()[0];
// If the script wrote less data than the batch size, signal the end of
the flow.
return batchSize > data.length;
}
Name: currentRow
Type: Integer
Value: 0
4. Add an action to set the number of rows to be read in a single batch. Depending
on the number of columns, this may need to be smaller to avoid the data transfer
limits. Make a new Initialize variable action with the following values.
Name: batchSize
Type: Integer
Value: 10000
5. Add a Do until control. The flow will read chunks of the data until it has all been
copied. You'll use the value of -1 to indicate the end of the data has been reached.
Give the control the following values.
6. The remaining steps are added inside the Do control. Next, call the script to read
the data. Add the Excel Online (Business) connector's Run script action. Rename it
to Read data. Use the following values for the action.
Name: currentRow
Value: batchSize (dynamic content)
9. Add a Condition control to check if the scripts have read everything. The "Write
data at row location" script returns true when it has written fewer rows than the
batch size allows. This means it's at the end of the data set. Create the Condition
control action with the following values.
10. Under the True section of the Condition control, set the currentRow variable to be
-1. Add a Set variable action with the following values.
Name: currentRow
Value: -1
11. Save the flow. The flow designer should look like the following image.
12. Use the Test button on the flow editor page or run the flow through your My flows
tab. Be sure to allow access when prompted.
13. The "TargetWorkbook.xlsx" file should now have the data from "SampleData.xlsx".
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Office Scripts sample scenario: Analyze
web downloads
Article • 10/25/2023
In this scenario, you're tasked with analyzing download reports from your company's
website. The goal of this analysis is to determine if the web traffic is coming from the
United States or elsewhere in the world.
Your colleagues upload the raw data to your workbook. Each week's set of data has its
own worksheet. There is also the Summary worksheet with a table and chart that shows
week-over-week trends.
You'll develop a script that analyzes weekly downloads data in the active worksheet. It
will parse the IP address associated with each download and determine whether or not
it came from the US. The answer will be inserted in the worksheet as a boolean value
("TRUE" or "FALSE") and conditional formatting will be applied to those cells. The IP
address location results will be totaled on the worksheet and copied to the summary
table.
Setup instructions
1. Download sample workbook to your OneDrive.
3. Under the Automate tab, select New Script and paste the following script into the
editor.
TypeScript
if (logRange.getColumnCount() !== 8) {
console.log(`Verify that you are on the correct worksheet. Either
the week's data has been already processed or the content is incorrect.
The following columns are expected: ${[
"Time Stamp", "IP Address", "kilobytes", "user agent code",
"milliseconds", "Request", "Results", "Referrer"
]}`);
return;
}
// Get the range that will contain TRUE/FALSE if the IP address is
from the United States (US).
let isUSColumn = logRange
.getLastColumn()
.getOffsetRange(0, 1);
// Autofit columns.
currentWorksheet.getUsedRange().getFormat().autofitColumns();
/**
* A function to add summary data on the worksheet.
*/
function addSummaryData() {
// Add a summary row and table.
let summaryHeader = [["Year", "Week", "US", "Other"]];
let countTrueFormula =
"=COUNTIF(" + isUSColumn.getAddress() + ', "=TRUE")/' +
(newCol.length - 1);
let countFalseFormula =
"=COUNTIF(" + isUSColumn.getAddress() + ', "=FALSE")/' +
(newCol.length - 1);
let summaryContent = [
[
'=TEXT(A2,"YYYY")',
'=TEXTJOIN(" ", FALSE, "Wk", WEEKNUM(A2))',
countTrueFormula,
countFalseFormula
]
];
let summaryHeaderRow = currentWorksheet.getRange("J1:M1");
let summaryContentRow = currentWorksheet.getRange("J2:M2");
console.log("2");
summaryHeaderRow.setValues(summaryHeader);
console.log("3");
summaryContentRow.setValues(summaryContent);
console.log("4");
conditionalFormatTrue.getCellValue().getFormat().getFill().setColor("#8
FA8DB");
conditionalFormatTrue.getCellValue().setRule({
formula1: "=TRUE",
operator: ExcelScript.ConditionalCellValueOperator.equalTo
});
conditionalFormatFalse.getCellValue().getFormat().getFill().setColor("#
F8CCAD");
conditionalFormatFalse.getCellValue().setRule({
formula1: "=FALSE",
operator: ExcelScript.ConditionalCellValueOperator.equalTo
});
}
/**
* Translate an IP address into an integer.
* @param ipAddress: IP address to verify.
*/
function ipAddressToInteger(ipAddress: string): number {
// Split the IP address into octets.
let octets = ipAddress.split(".");
// Create a number for each octet and do the math to create the
integer value of the IP address.
let fullNum =
// Define an arbitrary number for the last octet.
111 +
parseInt(octets[2]) * 256 +
parseInt(octets[1]) * 65536 +
parseInt(octets[0]) * 16777216;
return fullNum;
}
/**
* Return the row number where the ip address is found.
* @param ipLookupTable IP look-up table.
* @param n IP address to number value.
*/
function findIP(ipLookupTable: number[][], n: number): number {
for (let i = 0; i < ipLookupTable.length; i++) {
if (ipLookupTable[i][0] <= n && ipLookupTable[i][1] >= n) {
return i;
}
}
return -1;
}
In this scenario, you need to plot the water level at the National Oceanic and
Atmospheric Administration's Seattle station . You'll use external data to populate a
spreadsheet and create a chart.
You'll develop a script that uses the fetch command to query the NOAA Tides and
Currents database . That will get the water level recorded across a given time span. The
information will be returned as JSON , so part of the script will translate that into range
values. Once the data is in the spreadsheet, it will be used to make a chart.
For more information about working with JSON, read Use JSON to pass data to and
from Office Scripts.
Setup instructions
1. Open the workbook in Excel.
2. Under the Automate tab, select New Script and paste the following script into the
editor.
TypeScript
/**
* Gets data from the National Oceanic and Atmospheric Administration's
Tides and Currents database.
* That data is used to make a chart.
*/
async function main(workbook: ExcelScript.Workbook) {
// Get the current sheet.
let currentSheet = workbook.getActiveWorksheet();
console.log(strQuery);
// Note that we're only taking the data part of the JSON and
excluding the metadata.
const noaaData: NOAAData[] = JSON.parse(stringifiedJson).data;
/**
* An interface to wrap the parts of the JSON we need.
* These properties must match the names used in the JSON.
*/
interface NOAAData {
t: string; // Time
v: number; // Level
}
}
3. Rename the script to NOAA Water Level Chart and save it.
In this scenario, you're an instructor tallying every student's end-of-term grades. You've
been entering the scores for their assignments and tests as you go. Now, it is time to
determine the students' fates.
You'll develop a script that totals the grades for each point category. It will then assign a
letter grade to each student based on the total. To help ensure accuracy, you'll add a
couple checks to see if any individual scores are too low or high. If a student's score is
less than zero or more than the possible point value, the script will flag the cell with a
red fill and not total that student's points. This will be a clear indication of which records
you need to double-check. You'll also add some basic formatting to the grades so you
can quickly view the top and bottom of the class.
Setup instructions
1. Download sample workbook to your OneDrive.
3. Under the Automate tab, select New Script and paste the following script into the
editor.
TypeScript
workbook.getActiveWorksheet().getUsedRange().clearAllConditionalFormats
();
// Use regular expressions to read the max score from the assignment,
mid-term, and final scores columns.
let maxScores: string[] = [];
const assignmentMaxMatches = (studentData[0][1] as
string).match(/\d+/);
const midtermMaxMatches = (studentData[0][2] as string).match(/\d+/);
const finalMaxMatches = (studentData[0][3] as string).match(/\d+/);
// Use the first (and only) match from the regular expressions as the
max scores.
maxScores = [assignmentMaxMatches[0], midtermMaxMatches[0],
finalMaxMatches[0]];
studentsRange.getColumn(5).getFormat().setHorizontalAlignment(ExcelScri
pt.HorizontalAlignment.center);
}
/**
* Helper function to apply conditional formatting.
* @param value Cell value to use in conditional formatting formula1.
* @param range Target range.
* @param fontColor Font color to use.
* @param fillColor Fill color to use.
* @param operator Operator to use in conditional formatting.
*/
function setCellValueConditionalFormatting(
value: string,
range: ExcelScript.Range,
fontColor: string,
fillColor: string,
operator: ExcelScript.ConditionalCellValueOperator) {
// Determine the formula1 based on the type of value parameter.
let formula1: string;
if (isNaN(Number(value))) {
// For cell value equalTo rule, use this format: formula1:
"=\"A\"",
formula1 = `=\"${value}\"`;
} else {
// For number input (greater-than or less-than rules), just append
'='.
formula1 = `=${value}`;
}
conditionalFormatting.getCellValue().getFormat().getFont().setColor(fon
tColor);
conditionalFormatting.getCellValue().getFormat().getFill().setColor(fil
lColor);
conditionalFormatting.getCellValue().setRule({ formula1, operator });
}
The solution has three steps that are combined in a single Power Automate flow.
1. A script extracts data from a table and returns an array of objects as JSON data.
2. The data is then sent to the Teams Create a Teams meeting action to send invites.
3. The same JSON data is sent to another script to update the status of the invitation.
For more information about working with JSON, read Use JSON to pass data to and
from Office Scripts.
Setup instructions
3. Change at least one of the email addresses to your own so that you receive an
invite.
TypeScript
// Convert the table rows into InterviewInvite objects for the flow.
let invites: InterviewInvite[] = [];
dataRows.forEach((row) => {
const inviteSent = row[1] as boolean;
if (!inviteSent) {
const startTime = new Date(Math.round(((row[6] as number) - 25569) *
86400 * 1000));
const finishTime = new Date(startTime.getTime() + MEETING_DURATION *
60 * 1000);
const candidateName = row[2] as string;
const interviewerName = row[4] as string;
invites.push({
ID: row[0] as string,
Candidate: candidateName,
CandidateEmail: row[3] as string,
Interviewer: row[4] as string,
InterviewerEmail: row[5] as string,
StartTime: startTime.toISOString(),
FinishTime: finishTime.toISOString(),
Message: generateInviteMessage(MESSAGE_TEMPLATE, candidateName,
interviewerName)
});
}
});
console.log(JSON.stringify(invites));
return invites;
}
function generateInviteMessage(
messageTemplate: string,
candidate: string,
interviewer: string) : string {
return messageTemplate.replace("_Candidate_",
candidate).replace("_Interviewer_", interviewer);
}
// The interview invite information.
interface InterviewInvite {
ID: string
Candidate: string
CandidateEmail: string
Interviewer: string
InterviewerEmail: string
StartTime: string
FinishTime: string
Message: string
}
2. Create another new script with the following code. This will mark rows as invited.
TypeScript
if (inviteSent) {
inviteSentColumn.getRangeBetweenHeaderAndTotal().getCell(row,
0).setValue(true);
console.log(`Invite for ${inviteSent.Candidate} has been sent.`);
}
}
}
1. Name the second script Record Sent Invites for the flow.
3. In the flow builder, select the + button and Add an action. Use the Excel Online
(Business) connector's Run script action. Complete the action with the following
values.
4. Add an action that uses the Microsoft Teams connector's Create a Teams meeting
action. As you select dynamic content from the Excel connector, a For each block
will be generated for your flow. Complete the connector with the following values.
5. In the same For each block, add another Run script action. Use the following
values.
6. Save the flow. The flow designer should look like the following image.
7. Use the Test button on the flow editor page or run the flow through your My flows
tab. Be sure to allow access when prompted.
In this scenario you're managing a project. You use an Excel worksheet to track your
employees' status every month. You often need to remind people to fill out their status,
so you've decided to automate that reminder process.
You'll create a Power Automate flow to message people with missing status fields and
apply their responses to the spreadsheet. To do this, you'll develop a pair of scripts to
handle the working with the workbook. The first script gets a list of people with blank
statuses and the second script adds a status string to the right row. You'll also make use
of Teams Adaptive Cards to have employees enter their status directly from the
notification.
Prerequisites
This scenario uses Power Automate and Microsoft Teams .
Setup instructions
TypeScript
/**
* This script looks for missing status reports in a project management
table.
*
* @returns An array of Employee objects (containing their names and
emails).
*/
function main(workbook: ExcelScript.Workbook): Employee[] {
// Get the first worksheet and the first table on that worksheet.
let sheet = workbook.getFirstWorksheet()
let table = sheet.getTables()[0];
// Loop through the table and check each row for completion.
for (let i = 0; i < bodyRangeValues.length; i++) {
let row = bodyRangeValues[i];
if (row[STATUS_REPORT_INDEX] === "") {
// Save the email to return.
people.push({ name: row[NAME_INDEX].toString(), email:
row[EMAIL_INDEX].toString() });
}
}
/**
* An interface representing an employee.
* An array of Employees will be returned from the script
* for the Power Automate flow.
*/
interface Employee {
name: string;
email: string;
}
3. Next, we need a second script to process the status report cards and put the new
information in the spreadsheet. In the Code Editor task pane, select New Script
and paste the following script into the editor.
TypeScript
/**
* This script applies the results of a Teams Adaptive Card about
* a status update to a project management table.
*
* @param senderEmail - The email address of the employee updating
their status.
* @param statusReportResponse - The employee's status report.
*/
function main(workbook: ExcelScript.Workbook,
senderEmail: string,
statusReportResponse: string) {
// Get the first worksheet and the first table in that worksheet.
let sheet = workbook.getFirstWorksheet();
let table = sheet.getTables()[0];
// Loop through the table and check each row for a matching email
address.
for (let i = 0; i < tableRowCount && !statusAdded; i++) {
let row = bodyRangeValues[i];
Tip
If you haven't created a flow before, please check out our tutorial Start using
scripts with Power Automate to learn the basics.
3. Choose Manually trigger a flow from the options and select Create.
4. The flow needs to call the Get People script to get all the employees with empty
status fields. In the flow builder, select the + button and Add an action. Select the
Excel Online (Business) connector's Run script action. Provide the following entries
for the flow step:
JSON
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Update your Status Report"
},
{
"type": "Image",
"altText": "",
"url": "https://i.imgur.com/f5RcuF3.png"
},
{
"type": "TextBlock",
"text": "This is a reminder to update your status report for this
month's review. You can do so right here in this card, or by adding it
directly to the spreadsheet.",
"wrap": true
},
{
"type": "Input.Text",
"placeholder": "My status report for this month is...",
"id": "response",
"isMultiline": true
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit",
"id": "submit"
}
]
}
7. For the Recipient field, add email from the dynamic content (the selection will
have the Excel logo by it). Adding email causes the flow step to be surrounded by
a For each block. That means the array will be iterated over by Power Automate.
10. Save the flow. The flow designer should look like the following image.
Running the flow
To test the flow, make sure any table rows with blank status use an email address tied to
a Teams account (you should probably use your own email address while testing). Use
the Test button on the flow editor page or run the flow through your My flows tab. Be
sure to allow access when prompted.
You should receive an Adaptive Card from Power Automate through Teams. Once you fill
out the status field in the card, the flow will continue and update the spreadsheet with
the status you provide.
Before running the flow
The scenario idea and script used in this sample was contributed by Office Scripts
community member Brian Gonzalez .
In this scenario, you'll create a time sheet for an employee that allows them to record
their start and end times with a button. Based on what's previously been recorded,
selecting the button will either start their day (clock in) or end their day (clock out).
Setup instructions
1. Download the sample workbook to your OneDrive.
3. Under the Automate tab, select New Script and paste the following script into the
editor.
TypeScript
/**
* This script records either the start or end time of a shift,
* depending on what is filled out in the table.
* It is intended to be used with a Script Button.
*/
function main(workbook: ExcelScript.Workbook) {
// Get the first table in the timesheet.
const timeSheet = workbook.getWorksheet("MyTimeSheet");
const timeTable = timeSheet.getTables()[0];
// Get the last rows for the Clock In and Clock Out columns.
let clockInLastRow =
clockInColumn.getRangeBetweenHeaderAndTotal().getLastRow();
let clockOutLastRow =
clockOutColumn.getRangeBetweenHeaderAndTotal().getLastRow();
// Add the current time to a column based on the state of the table.
if (clockInLastRow.getValue() as string === "") {
// If the Clock In column has an empty value in the table, add a
start time.
clockInLastRow.setValue(date.toLocaleString());
} else if (clockOutLastRow.getValue() as string === "") {
// If the Clock Out column has an empty value in the table,
// add an end time and calculate the shift duration.
clockOutLastRow.setValue(date.toLocaleString());
const clockInTime = new Date(clockInLastRow.getValue() as string);
const clockOutTime = new Date(clockOutLastRow.getValue() as
string);
const clockDuration = Math.abs((clockOutTime.getTime() -
clockInTime.getTime()));
durationColumn.getRangeBetweenHeaderAndTotal().getLastRow().setValue(du
rationString);
} else {
// If both columns are full, add a new row, then add a start time.
timeTable.addRow()
clockInLastRow.getOffsetRange(1,
0).setValue(date.toLocaleString());
}
}
/**
* A function to write a time duration as a string.
*/
function getDurationMessage(delta: number) {
// Adapted from here:
// https://stackoverflow.com/questions/13903897/javascript-return-
number-of-days-hours-minutes-seconds-between-two-dates
if (days >= 1) {
durationString += days;
durationString += (days > 1 ? " days" : " day");
if (hours >= 1) {
durationString += hours;
durationString += (hours > 1 ? " hours" : " hour");
if (minutes >= 1) {
durationString += " and ";
}
}
if (minutes >= 1) {
durationString += minutes;
durationString += (minutes > 1 ? " minutes" : " minute");
}
return durationString;
}
7. Add a script button. Go to the More options (…) menu in the Script details page
and select Add in workbook.
The duration is only recorded if it's longer than a minute. Manually edit the "Clock
In" time to test larger durations.
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Seasons greetings
Article • 10/25/2023
This script was contributed by Leslie Black in the spirit of the holiday season! It's a fun
script that shows a singing tree in Excel using Office Scripts.
Enjoy!
Watch the Seasons greetings script in action on the "Les's IT Blog" YouTube channel .
TypeScript
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setFlashingStarAndSmileRed(workbook) //red
setFlashingStarAndSmileYellow(workbook) //yellow
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setFlashingStarAndSmileRed(workbook) //red
setFlashingStarAndSmileYellow(workbook) //yellow
blink(workbook)
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
setOuterEdgeRed(workbook) //red
setOuterEdgeYellow(workbook) //yellow
unblink(workbook)
console.log('Routine finished');
Office Scripts and VBA macros have a lot in common. They both allow users to automate
solutions through an easy-to-use action recorder and allow edits of those recordings.
Both frameworks are designed to empower people who may not consider themselves
programmers to create small programs in Excel.
The fundamental difference is that VBA macros are developed for desktop solutions and
Office Scripts are designed for secure, cross-platform, cloud-based solutions.
This article describes the main differences between VBA macros (as well as VBA in
general) and Office Scripts. Since Office Scripts are only available for Excel, that is the
only host being discussed here.
ノ Expand table
Excel on Excel for Excel Excel Other Office Power
the web Windows for Mac for iOS products Automate
Users require an enterprise or educational license to use or create Office Scripts. For the
full list of supported licenses, see Platform support. VBA is built-in to the desktop
versions of Excel and requires no special licensing.
Security
VBA macros have the same security clearance as Excel. This gives them full access to
your desktop. Office Scripts only have access to the workbook, not the machine hosting
the workbook. Additionally, no JavaScript authentication tokens can be shared with
scripts. This means the script has neither the tokens of the signed-in user nor are there
any API capabilities for signing in to an external service, so they are unable to use
existing tokens to make external calls on behalf of the user.
Admins have three options for VBA macros: allow all macros on the tenant, allow no
macros on the tenant, or allow only macros with signed certificates. This lack of
granularity makes it hard to isolate a single bad actor. Currently, Office Scripts can be off
for an entire tenant, on for an entire tenant, or on for a group of users in a tenant.
Admins also have control over who can share scripts with others and who can use
scripts in Power Automate.
Coverage
Currently, VBA offers a more complete coverage of Excel features, particularly those
available on the desktop client. Office Scripts cover nearly all of the scenarios for Excel
on the web. Additionally, as new features debut on the web, Office Scripts will support
them for both the Action Recorder and JavaScript APIs.
Office Scripts don't support Excel-level events. Scripts are only run when a user manually
starts them or when a Power Automate flow calls the script.
Power Automate
VBA doesn't have a Power Automate connector. All supported VBA scenarios involve a
user attending to the macro's execution.
Office Scripts can be run through Power Automate. Your workbook can be updated
through scheduled or event-driven flows, letting you automate workflows without even
opening Excel. Try Tutorial: Update a spreadsheet from a Power Automate flow to start
learning about Power Automate. You can also check out the Automated task reminders
sample to see Office Scripts connected to Teams through Power Automate in a real-
world scenario.
See also
Office Scripts in Excel
Run Office Scripts with Power Automate
Differences between Office Scripts and Office Add-ins
Troubleshooting Office Scripts
Excel VBA reference
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
Differences between Office Scripts and
Office Add-ins
Article • 03/30/2023
Understand the differences between Office Scripts and Office Add-ins to know when to
use each one. Office Scripts are designed to be quickly made by anyone looking to
improve their workflow. Office Add-ins integrate with the Office UI for a more interactive
experience through ribbon buttons and task panes. Office Add-ins can also expand
built-in Excel functions by providing custom functions.
Office Scripts run to completion with a manual button selection or as a step in Power
Automate , whereas Office Add-ins continue running depending on how they are
configured. For example, you can configure an Office Add-in to continue running even
when its task pane is closed. This means that Office Add-ins maintain state during a
session, whereas Office Scripts don't maintain an internal state between runs. If the
solution you're building requires a maintained state, you should visit the Office Add-ins
documentation to learn more about Office Add-ins.
The rest of this article describes on the main differences between Office Add-ins and
Office Scripts.
Platform support
The following table shows which features are supported by which platforms and
products.
ノ Expand table
APIs
While the Office JavaScript APIs for Office Add-ins and the Office Scripts APIs share
some functionality, they are different platforms. The Office Scripts APIs are an optimized,
synchronous subset of the Excel JavaScript API model. The major difference is usage of
the load / sync paradigm with add-ins. Additionally, add-ins offer APIs for events and a
broader set of functionality outside of Excel, known as the Common APIs.
Office Add-ins offer greater connectivity to external web services and libraries. Office
Scripts are limited to specific external calls.
Events
Office Scripts do not support workbook-level events. Scripts are either triggered by
users selecting the Run button for a script or through Power Automate. Every script runs
the code in a single main function, then ends.
UX and UI controls
Office Scripts can only interact with the workbook, not the task pane. If you need
authentication, dialog windows, or additional UX and UI controls, you'll need to create
an Office Add-in instead of an Office Script.
See also
Office Scripts in Excel
Differences between Office Scripts and VBA macros
Troubleshooting Office Scripts
Build an Excel task pane add-in
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.
When to use Power Query or Office
Scripts
Article • 03/30/2023
Power Query and Office Scripts are both powerful automation solutions for Excel.
Both solutions let Excel users clean and transform data in workbooks. A single Power
Query or Office Script can be refreshed and rerun on new data to produce consistent
results, which saves you time and lets you work with the resulting information faster.
This article provides a general overview of when you might favor one platform over the
other. In general, Power Query is good for pulling and transforming data from large,
external data sources and Office Scripts are good for quick, Excel-centric solutions and
Power Automate integrations.
Power Query has built-in data connections to hundreds of sources. Power Query is
specially designed for data retrieval, transformation, and combination tasks. When you
need data from one of those sources, Power Query gives you a no-code way of bringing
that data into Excel in the shape you need.
These Power Query connections are designed for large datasets. They do not have the
same transfer limits as Power Automate or Excel on the web.
Office Scripts offer a lightweight solution for smaller data sources or data sources not
covered by Power Query connectors. This includes using fetch or REST APIs or getting
information from ad-hoc data sources, such as a Teams adaptive card.
Nearly everything you can do manually through the Excel UI is doable with Office
Scripts. They're great for applying consistent formatting to workbooks. Scripts create
charts, PivotTables, shapes, images, and other worksheet visualizations. Scripts also give
you precise control over the positions, sizes, colors, and other attributes of these
visualizations.
Formatting can be applied with Power Query through Excel templates . However,
templates are updated at the individual or organization level, whereas Office Scripts
offer more granular access control.
Power Query is used in the SQL Server Power Automate connector. The Transform
data using Power Query action lets you build a query in Power Automate. While this is a
powerful tool for use with SQL Server, it does limit Power Query to that input source, as
shown in the following flow screenshot.
Platform dependencies
Office Scripts is currently available for Excel on the web, Excel for Windows, and Excel for
Mac. The full Power Query experience is currently only available for Excel for Windows.
Both can be used through Power Automate, which lets the flow work with Excel
workbooks stored in OneDrive.
See also
Power Query Portal
Power Query with Excel
Run Office Scripts with Power Automate
6 Collaborate with us on
GitHub Office Scripts feedback
Office Scripts is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.