Build a GENAI() custom function for Sheets
Call Claude directly from a Northwind Sheet cell with =GENAI(prompt) — with caching baked in.
Published Jun 24, 2025
Northwind’s team lives in spreadsheets, and half the small writing jobs that land there — tidying a subject line, summarising a note, rephrasing a blurb — are quick for an AI but tedious by hand. Copying each cell into a chat window and pasting the answer back is the slow part, not the thinking.
This builds a custom function, =GENAI(), that calls Claude straight from a
cell. Type a prompt, get the answer in the next column, and fill it down like
any other formula. It also caches every result, so re-opening the sheet or
copying a formula does not re-bill you for an answer Claude has already given.
What you’ll need
- An Anthropic API key stored as
ANTHROPIC_API_KEYin Script Properties — see Store API keys and secrets securely. - A bound script — open the spreadsheet, then Extensions → Apps Script — so the function is available in that sheet.
- Nothing else.
CacheServiceis built in and needs no setup.
The function
// Default Claude model. Haiku is fast and cheap — ideal for the
// short, high-volume jobs a cell formula tends to throw at it.
const DEFAULT_MODEL = 'claude-haiku-4-5-20251001';
// How long a result stays in the cache, in seconds (6 hours).
const CACHE_TTL_SECONDS = 6 * 60 * 60;
// Token ceiling per call. Keeps replies cell-sized and costs predictable.
const MAX_TOKENS = 512;
/**
* Calls Claude with a prompt and returns the text answer.
* Identical prompts are served from cache, so they never re-bill.
* @param {string} prompt - The instruction to send to Claude.
* @param {string} [model] - Optional model override.
* @returns {string} Claude's reply.
* @customfunction
*/
function GENAI(prompt, model = DEFAULT_MODEL) {
// 1. An empty cell means nothing to do — return blank, no API call.
if (!prompt) return '';
// 2. Build a cache key from a hash of the model and prompt, so the
// same request always maps to the same slot.
const cache = CacheService.getScriptCache();
const key = 'genai:' + Utilities.base64Encode(
Utilities.computeDigest(
Utilities.DigestAlgorithm.SHA_1, model + ':' + prompt));
// 3. Serve a cached answer if we have one.
const hit = cache.get(key);
if (hit) return hit;
// 4. Cache miss — call the Anthropic API. The key lives in Script
// Properties and is never written into the sheet or the code.
const apiKey = PropertiesService.getScriptProperties()
.getProperty('ANTHROPIC_API_KEY');
const res = UrlFetchApp.fetch('https://api.anthropic.com/v1/messages', {
method: 'post',
contentType: 'application/json',
headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' },
payload: JSON.stringify({
model,
max_tokens: MAX_TOKENS,
messages: [{ role: 'user', content: prompt }],
}),
muteHttpExceptions: true,
});
// 5. Pull the text out of the response, store it, and return it.
const data = JSON.parse(res.getContentText());
const text = (data.content?.[0]?.text ?? '').trim();
cache.put(key, text, CACHE_TTL_SECONDS);
return text;
}
How it works
GENAIis marked@customfunction, so Sheets exposes it as a formula you can type into any cell, just like=SUMor=VLOOKUP.- If the prompt cell is empty it returns an empty string straight away — no wasted API call when you fill the formula down past your data.
- It builds a cache key by SHA-1 hashing the model and prompt together. The hash keeps the key short and unique, and including the model means switching models does not collide with an old answer.
- It checks
CacheServicefor that key. A hit returns instantly with no network call — this is what stops re-opens and copies from re-billing. - On a miss it reads the API key from Script Properties and posts the prompt to
Anthropic’s Messages API.
muteHttpExceptionskeeps a bad response from throwing a raw error into the cell. - It extracts the reply text, stores it in the cache for
CACHE_TTL_SECONDS, and returns it for Sheets to display.
Example run
With the function in place, put a prompt in a formula and reference your data:
| A (raw note) | B (formula) | B (result) |
|---|---|---|
| meeting moved to thurs 3pm | =GENAI("Rewrite as a friendly subject line: " & A2) | Quick update: our meeting’s now Thursday at 3pm |
| client wants the logo bigger | =GENAI("Rewrite as a friendly subject line: " & A3) | A small tweak — making your logo bigger |
Fill the formula down and every row gets its own answer. Edit a cell in column A and only that row re-runs; everything else is served from cache.
Use it
Type the formula straight into a cell, concatenating your instruction with a cell reference:
=GENAI("Rewrite as a friendly subject line: " & A2)
Pass a second argument to override the model for a heavier job:
=GENAI("Summarise this support thread in one sentence: " & A2, "claude-sonnet-4-6")
Watch out for
- Custom functions time out after 30 seconds.
GENAI()is built for short prompts — for long jobs or large batches, use a bound script with a button or menu instead of a cell formula. - Recalculation can fan out fast. Filling the formula down 500 rows fires 500 API calls on first run; the cache covers re-runs, not the first pass. Watch your Anthropic spend on big sheets.
- The 6-hour cache means an answer can go stale — that is the trade-off for not re-billing. Editing the upstream cell changes the prompt, so it re-runs naturally; identical prompts will not.
CacheServicevalues are capped at 100 KB each. TheMAX_TOKENSof 512 keeps replies well under that, but raising it for verbose output could push a result past the limit and skip caching.- Custom functions run anonymously and cannot read your identity, so the API key must come from Script Properties — it cannot be passed in as an argument.
Related
Build a GENAI_ARRAY() function for whole columns
Process ranges in one efficient batched call — one prompt, many rows answered in parallel.
Updated Jun 28, 2025
Build retrieval-augmented Q&A over your data
Answer Northwind questions grounded in your own Sheet data — pass relevant rows as context.
Updated Feb 27, 2026
Parse semi-structured listings into tables
Extract recipes, specs, or ads from Northwind content into clean spreadsheet rows.
Updated Mar 7, 2026
Generate and test email subject lines
A/B test AI-written Northwind subject lines for open rate — outputs ranked by past performance.
Updated Mar 3, 2026
Build an AI weekly-report narrator
Turn Northwind metrics into a written executive summary — numbers in, prose out.
Updated Feb 23, 2026