Task guide
Write a custom function in Google Sheets
A Google Sheets custom function is a top-level Apps Script function you call from a cell like a built-in formula, with an optional @customfunction tag for formula autocomplete. This guide converts Celsius to Fahrenheit for one cell or a range.
1 · Prepare
Put these pieces in place
- Open the spreadsheet where you want the formula and put a few Celsius numbers in column A.
- Write the script inside that spreadsheet, using Extensions and then Apps Script. A custom function works only in the file its script belongs to.
- Pick a name in capital letters that no built-in Sheets function already uses.
Change these values
- Function name
CELSIUS_TO_FAHRENHEITThis is the name you type in a cell, as in =CELSIUS_TO_FAHRENHEIT(A2). Change it in both functions if you rename it.
- The calculation
Math.round((celsius * 9 / 5 + 32) * 10) / 10This converts the value and keeps one decimal place. Replace it with your own math.
- Error message
CELSIUS_TO_FAHRENHEIT needs a number.This is the message shown in the cell when the value is text instead of a number.
2 · Review before running
What the script can access and change
Permissions you approve
- Nothing to approve. A custom function does not open the authorization dialog.
- This function sees only the values passed to it in the formula. Custom functions can use limited services that do not need permission, including UrlFetchApp to call a website. They cannot send email or reach Drive, because Gmail and Drive need approval.
Effects of one run
- Shows a result in the cell holding the formula, and in the cells below it when every nonblank value in a range can be converted.
- Recalculates on its own whenever a value it depends on changes.
- Writes nothing to the sheet by itself and changes none of the source cells.
3 · Copy
Paste this into the Apps Script editor
Create or open a script file, replace the example values marked above, then save the project.
/**
* Converts a Celsius temperature to Fahrenheit.
*
* @param {number|string|boolean|Date|null|undefined|Array<Array<number|string|boolean|Date|null|undefined>>} input One Celsius value, or a range of them.
* @return {number|string|Array<Array<number|string>>} The Fahrenheit value, or a grid of values the same shape as the input.
* @customfunction
*/
function CELSIUS_TO_FAHRENHEIT(input) {
if (Array.isArray(input)) {
return input.map((row) => row.map((cell) => celsiusCellToFahrenheit(cell)));
}
return celsiusCellToFahrenheit(input);
}
/**
* @param {number|string|boolean|Date|null|undefined} cell
* @return {number|string}
*/
function celsiusCellToFahrenheit(cell) {
if (cell === '' || cell === null || cell === undefined) return '';
const celsius = Number(cell);
if (isNaN(celsius)) {
throw new Error('CELSIUS_TO_FAHRENHEIT needs a number. It received: ' + cell);
}
return Math.round((celsius * 9 / 5 + 32) * 10) / 10;
} 4 · Run safely
Follow these steps in order
Add a few test values
In A2:A5, put 100, 0, leave A4 empty, and put the word warm in A5. That gives you one round number, one easy answer, one blank, and one mistake to test with.
Paste both functions and save
Open Extensions, choose Apps Script, paste the code, and save. Keep the comment block above the function. The @customfunction line is what makes the name appear in the formula suggestions in the sheet.
Try one cell
In cell B2, type =CELSIUS_TO_FAHRENHEIT(A2) and press Enter. With 100 in A2 you get 212.
See what an invalid range does
In cell C2, type =CELSIUS_TO_FAHRENHEIT(A2:A20). Because the range includes warm, the function throws an error. C2 shows the error and no values spill into the cells below it.
Remove the mistake and spill the results
Clear A5, then enter =CELSIUS_TO_FAHRENHEIT(A2:A20) in C2 again. One formula fills the results down the column, and blank cells stay blank. To adapt the function, rename it and replace the calculation. Keep the blank check and the number check so bad values give a clear message instead of a wrong answer.
5 · Confirm
How to tell it worked
With 100 in A2, =CELSIUS_TO_FAHRENHEIT(A2) shows 212. With warm in A5, =CELSIUS_TO_FAHRENHEIT(A2:A20) shows an error in C2 and does not spill. Clear A5 and enter the formula again to get results for each number while blank cells stay blank.
If the result is different
Troubleshooting
- The cell shows #NAME?
- Sheets does not know the name yet. Save the Apps Script project, check the spelling in the cell, and make sure the name does not end with an underscore (which marks functions private in Apps Script). The code must live in the script attached to this spreadsheet, not in a separate project.
- The cell shows #ERROR! and the message about needing a number.
- The throw new Error line produces this message. A cell you pointed at holds text, so fix the value or point the formula somewhere else. If it is in a range, the whole formula shows the error.
- The cell shows "Exceeded maximum execution time".
- A custom function gets about 30 seconds per call at the time of writing. See https://developers.google.com/apps-script/guides/services/quotas. Pass a smaller range, or split one huge formula into a few smaller ones.
- The tooltip says "You do not have permission to call GmailApp.sendEmail".
- Custom functions cannot use services that ask for access, such as Gmail or Drive. UrlFetchApp is allowed, so use it when a custom function needs to fetch a website.
- The cell shows "TypeError: input.getValue is not a function".
- Formulas pass raw cell values or 2D arrays, not SpreadsheetApp.Range objects. Read the cell values directly from the input argument instead of calling Range methods.
Technical details
Names used in this script
Open these details when you want to adapt the example or look up an exact service or method name.
Show Apps Script symbols and service pages
Apps Script symbols
Service pages
Keep going
Related tasks, basics, and apps
- Task guide Add a custom menu to a Google Sheet
Use an onOpen() simple trigger and SpreadsheetApp.getUi().createMenu() to add a custom menu bar item that shows which cell is currently selected.
- Task guide Copy unique rows to a clean tab
The script reads your list, keeps the first row for each email address, and rewrites a tab named Clean. The source tab is never changed.
- Task guide Add a timestamp when a row changes
Change a status cell and the script stamps the same row with the current date and time. There is nothing to install beyond saving the script.
- Object reference Range
A Range represents one cell such as A2 or a rectangular block of rows and columns in a Sheet. Use getValue() for one cell and getValues() or setValues() for a 2D array of rows.
- Basics Bound scripts and standalone scripts
Every Apps Script project is either attached to one Google file or standing on its own. The choice decides how your code reaches your data, who can see it, and where you find it later.
- Basics Custom functions in Google Sheets
A Google Sheets custom function runs in a silent sandbox with its own rules: 30-second timeouts, raw 2D arrays instead of Range objects, no personal services, and no cell edits.
- Google app Google Sheets
SpreadsheetApp lets a Google Sheets script read a Sheet or Range, add a custom menu or formula, and run repeatable actions across rows.
- Diagnostic TypeError: X is not a function
Why calling Range methods on a custom function parameter fails and how to handle single values and 2D arrays.
- Book chapter Write custom functions for Sheets formulas
Write Apps Script custom functions that Sheets formulas call, accept a cell or a range, and spill a 2D array.