XLKitLearn · Reference

XLKitLearn Documentation

Acknowledgements

Many thanks to (in alphabetical order) Mateo Abella, Hugo Cayssials, Kevin McNicholas for co-authoring this manual with me. Their help was invaluable in making this happen.

Introduction

Using this guide

This guide contains one section for each of the add-in's key functionality areas, followed by a reference guide to all the Excel functions available in the add-in.

Looking to quickly get started? Each section starts with a "quickstart" guide.

→

Looking for a specific excel function? Use the search box in the table of contents on the left.

XLKitLearn is compatible with Excel for Windows, Mac, and the web. In Excel, open Home → Add-ins → More Add-ins, search for XLKitLearn, and add it to your workbook.

Guide · Predict

Predict

Fit and compare predictive models, evaluate their performance, and score new observations directly from Excel.

Quickstart

→

Are you currently taking CBS's Business Analytics core class? That class does not use XLKitLearn's Predict module—instead, it directly uses XLKitLearn's machine-learning prediction functions. Click here for details.

Imagine you run a pizza shop and want to give customers more accurate delivery estimates. In this quickstart, you'll use XLKitLearn's Predict module to learn from 100 completed orders and estimate delivery times based on distance, order size, rain, time of day, and driver experience. Along the way, you'll train and evaluate a model, then use it to predict delivery times for new orders. Follow along with the steps below...

Step 1 of 11
Loading screenshot…
Excel with the XLKitLearn Predict pane open
Open

Open the Predict tab

  1. Download the sample workbook by clicking here, and open it. The "Data" tab contains the 100 completed pizza orders we will use to predict delivery times (the last column). Each row represents one completed order; each column describes that order, such as its distance, number of pizzas, weather, or delivery time.
  2. On Excel's Home tab, click XLKitLearn. The add-in pane opens on the right.
  3. At the top of the pane, click Predict.
Guide · GenAI

GenAI

Access powerful GenAI functions directly from the Excel grid.

Quickstart

You run a pizza shop, which gets new online reviews every day. Reading them all takes would take a long time. In this quickstart, you'll use XLKitLearn's GenAI functions to ask an AI model to read five customer reviews and label each one Positive or Negative, without leaving Excel. Because the answers land in ordinary cells, you can then count or filter them with the Excel formulas you already know. Follow along with the steps below... To run this quickstart demo, you'll need an OpenRouter API key - see below for details.

Step 1 of 6
Loading screenshot…
Five pizza reviews in Excel with the XLKitLearn GenAI tab open
Open

Add the reviews and open the GenAI tab

  1. Download or copy the example below. The spreadsheet contains five reviews your shop received this week.

    Open the downloaded workbook, or paste the copied example into cell A1.

  2. Column A contains the reviews. Some are too long to show in full, which doesn't matter: the AI model reads the whole cell.
  3. Columns B and C are empty for now. Column B will hold the AI model's responses, and column C the labels you extract from them.
  4. On Excel's Home tab, click XLKitLearn. The add-in pane opens on the right.
  5. At the top of the pane, activate the GenAI tab.
Guide · Simulate

Simulate

Run your spreadsheet model thousands of times with random inputs and see the full range of results, directly from Excel.

Quickstart

You run a pizza shop. Each pizza sells for $15, and every ball of dough costs $3, whether you use it or not. Based on historical data, you know that your customers order an average of 40 pizzas every evening, with a standard deviation of 6.3 pizzas. To meet this demand, you mix and knead enough dough to make 40 balls every afternoon, and you expect to make (40 × $15) - (40 × $3) = $480 a night. But orders change from night to night: on busy nights you run out of dough and turn customers away, and on quiet nights dough goes in the bin. In this quickstart, you'll use XLKitLearn's Simulate module to play out 1,000 random evenings and find out your shop's true expected profit. Follow along with the steps below...

Step 1 of 6
Loading screenshot…
Pizza shop model in Excel with the XLKitLearn Simulate pane open
Open

Set up the model

  1. Your shop is about to open, and you've made 40 balls of pizza dough. Download or copy the example below; the spreadsheet contains a model that calculates the shop's profit on any given night.

    Open the downloaded workbook, or paste the copied example into cell A1.

  2. The first three rows contain data pertaining to the shop's operations.
  3. The fourth row simulates the number of orders on any specific night. It uses XLKitLearn's SIMNORMAL function, which takes the mean and standard deviation of a normal random variable, and returns a single random draw from that distribution. The small icon next to the number indicates that the cell holds a simulated number - every time Excel recalculates, the number will change. Press F9 a few times: each press plays out a different evening.
  4. Your shop doesn't sell half pizzas, so the simulated number of pizzas needs to be rounded. Row 5 rounds the simulated number of pizzas. Notice that the rounded number does not contain the "simulated number" icon because that number is not directly simulated - it is derived from a simulated number. XLKitLearn only displays the icon next to numbers that were directly simulated.
  5. The number of pizzas sold cannot exceed demand, and cannot exceed the number of dough balls prepared. Row six calculates the total number of pizzas actually sold by finding the minimum of these two numbers.
  6. Finally, this cell calculates the total profit that night - revenues from the pizzas actually sold minus the cost of preparing 40 dough balls.
  7. You're now ready to set up the simulation in XLKitLearn. On Excel's Home tab, click XLKitLearn. The add-in pane opens on the right.
  8. At the top of the pane, activate the Simulate tab.
Guide · Optimize

Optimize

Find the best decision for a linear model by maximizing or minimizing an objective subject to constraints.

XLKitLearn's optimize module is compatible with Excel's solver add-in. Any settings you specify in XLKitLearn will appear in solver, and vice versa. XLKitLearn only supports linear optimization problems, but it can solve much larger linear optimization problems than Excel's solver add-in.

Quickstart

You run a pizza shop, and it's time to plan tonight's prep. You sell three pizzas: Cheese, Pepperoni, and a Philly tomato pie (a thick, square-cut pizza usually eaten at room temperature and sold by the tray in Philadelphia). Each pizza earns the store a different profit and uses different amounts of dough, cheese, and prep time, and you only have so much of each to go around. You've also committed to fulfill a catering order of 25 tomato pies for a party. In this quickstart, you'll use XLKitLearn's Optimize module to decide how many of each pizza to make to maximize your profit without running out of anything. Follow along with the steps below...

Step 1 of 5
Loading screenshot…
Excel with the pizza shop data pasted and the XLKitLearn Optimize pane open
Set up

Set up the optimization model in Excel

  1. Download or copy the example below; the spreadsheet contains the data pertaining to the shop's operations that we will be working with in this section.

    Open the downloaded workbook, or paste the copied example into cell A1.

  2. Row 2 lists the profit per pizza.
  3. Row 7 will hold the solution (how many pizzas to make to maximize profit) once XLKitLearn's optimize module has found it.
  4. Rows 3-5 list the quantity of each resource each type of pizza uses. Column E contains formulas - for example, cell E3 contains the formula =SUMPRODUCT(B3:D3,$B$7:$D$7), which multiplies the number of pizzas made by the number of dough balls required for each, thus calculating the total number of dough balls required for a given solution. Column G lists the total amount of that resource available, and column F indicates that the total amount utilized should be no larger than the amount available.
  5. Cell D9 contains the catering minimum - the number of tomato pies will have to be at least that number.
  6. Cell B11 contains the objective function =SUMPRODUCT(B2:D2,B7:D7) - the total profit for a given solution. This is the number we will try to make as large as possible.
  7. On Excel's Home tab, click XLKitLearn. The add-in pane opens on the right.
  8. At the top of the pane, activate the Optimize tab.
Reference guide

Function reference

The list below is a comprehensive list of every function in the add-in. Use the search on the left to filter these functions.

Spilled range Click to run

Machine learning - model fitting

Fit reusable models and use them to generate predictions for new data.

Fits a linear regression to a dataset, to predict a continuous outcome using one or more other variables. The data you provide to the function should include one column for every variable, and one row for each observation, with the variable names in the first row. There are two ways to specify the dependent and independent variables in your linear regression model:

  • To choose the predictors yourself, for example to use only some of the columns, write the outcome, a tilde (~), then the predictors joined with +. For example, if your data is in A7:C13, with columns sales, ads and price, you would write =XKL.FITLINEARREGRESSION(A7:C13,"sales ~ ads + price"). See the "Predict" section above for more details on XLKitLearn's formula language.
  • To predict one specific column using every other column in the table as a predictor, write just the outcome column's name. For example, =XKL.FITLINEARREGRESSION(A7:C13,"sales") uses both ads and price.
Sample function call
=XKL.FITLINEARREGRESSION(data, formula)
Parameters
data

The training data, including a header row with column names. The formula refers to variables by these header names.

formula

The outcome and predictors in quotes, for example "sales ~ ads + price". Use the header names exactly as they appear in data. Or give just the outcome's name, for example "sales", to use every other column as a predictor.

Returns

A fitted model, shown in the cell as a small card, that you can use in XKL.PREDICT to make predictions.

It also exposes the following elements through dot notation:

  • .coefficients: the coefficient table, with standard errors, 95% confidence intervals, p-values and significance stars. If the model is in cell A5, type =A5.coefficients in an empty cell. The full table appears, filling the cells below and to the right.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Fits a logistic regression to a dataset, to predict the probability of a yes/no outcome (such as whether a delivery will arrive late) using one or more other variables. The data you provide to the function should include one column for every variable, and one row for each observation, with the variable names in the first row. There are two ways to specify the dependent and independent variables in your logistic regression model:

  • To choose the predictors yourself, for example to use only some of the columns, write the outcome, a tilde (~), then the predictors joined with +. If your data is in A7:C27, with columns late, distance and orders_waiting, you would write =XKL.FITLOGISTICREGRESSION(A7:C27,"late ~ distance + orders_waiting"). See the "Predict" section above for more details on XLKitLearn's formula language.
  • To use every other column in the table as a predictor, write just the outcome's name. With the same data, =XKL.FITLOGISTICREGRESSION(A7:C27,"late") uses both distance and orders_waiting.

Note that to fit a logistic regression, the outcome column must contain 0s or 1s only.

Sample function call
=XKL.FITLOGISTICREGRESSION(data, formula)
Parameters
data

The training data, including the header row. The formula refers to columns by these header names, and the outcome column must contain only 0 and 1.

formula

The outcome and predictors in quotes, for example "late ~ distance + orders_waiting". Use the header names exactly as they appear in data. Or give just the outcome's name, for example "late", to use every other column as a predictor. Note that the outcome column must contain 0s and 1s only.

Returns

A fitted model, shown in the cell as a small card, that you can use in XKL.PREDICT to make predictions.

It also exposes the following elements through dot notation:

  • .coefficients: the coefficient table, with standard errors, 95% confidence intervals, p-values and significance stars. If the model is in cell A5, type =A5.coefficients in an empty cell. The full table appears, filling the cells below and to the right.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Fits a k-nearest-neighbors (KNN) model to a dataset to predict an outcome variable based on one or more predictor variables. The model can predict the outcome for a new row of predictors by looking at the training set, finding the k rows with predictors closest to the new predictors, and averaging the outcome for those rows. There are two ways to specify the dependent and independent variables in your model:

  • To choose the predictors yourself, for example to use only some of the columns, write the outcome, a tilde (~), then the predictors joined with +. If your data is in A7:C15, with columns corresponding to total_spend, visits, and club_membership, you would write =XKL.FITKNN(A7:C15,"total_spend ~ visits + club_membership",3) to fit a k-nearest-neighbors model that looks at the 3 nearest neighbors.
  • To use every other column in the table as a predictor, write just the outcome's name. With the same data, =XKL.FITKNN(A7:C15,"total_spend",3) uses both visits and club_membership.
Sample function call
=XKL.FITKNN(data, formula, k, [row_to_exclude])
Parameters
data

The training data, including the header row. The formula refers to columns by these header names.

formula

The outcome and predictors in quotes, for example "total_spend ~ visits + club_membership". Use the header names exactly as they appear in data. Or give just the outcome's name, for example "total_spend", to use every other column as a predictor.

k

How many neighbors to use. A positive whole number, no larger than the number of training rows.

row_to_exclude optional

You can leave a training row out when building the model, which lets you test the model fairly: predict that row with XKL.PREDICT and compare the prediction with its real outcome. Give the row as a number: 1 selects the first row below the header, 2 the second, and so on (note: only one row can be left out). Omit this to use every row.

Returns

A fitted model, shown in the cell as a small card, that you can use in XKL.PREDICT to make predictions.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Machine learning - helpers

Evaluate model performance, inspect classification results, and transform data for modeling and visualization.

Calculates R-squared, which measures how well a model's predictions of a number, such as weekly sales, match what actually happened. A score of 1 means the predictions are perfect, and 0 means the model is no better than predicting the average. For example, an R-squared of 0.8 means the model explains 80% of the variation in sales (how much sales go up and down from week to week).

Sample function call
=XKL.RSQUARED(y_true, y_pred)
Parameters
y_true

The actual value for each case, in a single row or column, for example the number of slices sold each week. Use numbers only, and give at least two values.

y_pred

The model's prediction for each case, in the same order as y_true and with the same number of values. These usually come from XKL.PREDICT: select its output without the header row.

Returns

A single number, at most 1, showing roughly how much of the variation in y_true the predictions explain. Higher is better. 1 means every prediction is exactly right. 0 means the model does no better than predicting the average of y_true every time. Below 0 means the model does worse than that. This can happen on test data when a model overfits.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Calculates the RMSE (root mean squared error), which tells you how far off a model's predictions of a number typically are, in the same units as what you're predicting. For example, a pizza shop that predicts weekly sales to decide how much dough to prepare needs to know how many slices those predictions are usually off by. An RMSE of 5 means they're typically off by about 5 slices. Lower is better, and 0 means every prediction is exactly right.

RMSE or R-squared: The R-squared, which you can calculate using XKL.SQUARED is a scaled version of the RMSE that falls between 0 and 1. The RMSE tells you how big the errors are in real units.

How it's calculated: for each case, take the error (actual minus predicted) and square it. Average the squares, then take the square root. Because the errors are squared, a few large misses raise RMSE more than many small ones.

Sample function call
=XKL.RMSE(y_true, y_pred)
Parameters
y_true

The actual value for each case, in a single row or column, for example the number of slices sold each week. Use numbers only.

y_pred

The model's prediction for each case, in the same order as y_true and with the same number of values. These usually come from XKL.PREDICT: select its output without the header row.

Returns

A single number, 0 or more, in the same units as y_true, showing roughly how far off a typical prediction is. Lower is better: 0 means every prediction is exactly right. There is no fixed cutoff for a good RMSE, so compare it with the size of the values you are predicting, or with other models' RMSE on the same data.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Calculates the AUC (area under the curve), which evaluates how well a classification model tells two groups apart, such as customers who bought vs. didn't, or posts that break the rules vs. posts that don't. It checks the model's predicted probabilities against the actual outcomes, and calculates the area under the ROC curve, which you can draw using XKL.ROCCURVE. The score is usually between 0.5 and 1. A score of 1 means the model separates the groups perfectly, and 0.5 means it is no better than guessing.

Comparing models: calculate each model's AUC against the same actual outcomes. The model with the higher AUC is better at telling the groups apart. For example, fit one model using XKL.FITLOGISTICREGRESSION and another with XKL.FITKNN. Then get each one's predicted probabilities with XKL.PREDICT and calculate the AUC of each.

(Advanced) Three or more groups: XKL.AUC also works when there are more than two groups. Give one probability column per group, in alphabetical order of the group names: for low, medium and high, the columns go high, low, medium. Columns are matched to groups by position, not by their headers, so the wrong order gives a wrong score.

Sample function call
=XKL.AUC(y_true, y_pred)
Parameters
y_true

The actual outcome for each case, in a single row or column. Usually this is 0 or 1, for example 1 if the customer bought and 0 if they didn't. Include at least one of each. Text outcomes such as "yes" and "no" also work; see y_pred for which probability to give.

y_pred

The model's predicted probability for each case, in the same order as y_true.

For 0/1 outcomes, you can simply provide each case's probability of 1, in a single column.

Alternatively, you can provide a table containing the probability of each outcome, with the columns sorted in alphabetical order. For example, if the valid outcomes in y_true are low, medium, and high, the first column should list the probability of high, the second the probability of low, and the last column the probability of medium. These probabilities can be obtained directly from XKL.PREDICT: select the whole output for that function except for the header row.

Returns

A single number between 0 and 1. Higher is better: 1 means a perfect ranking and 0.5 means the model does no better than chance. A value well below 0.5 usually means y_pred holds the probability of the wrong outcome, for example the probability of 0 instead of 1. If this happens, check y_pred and recalculate.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Builds a confusion matrix: a table that counts how often a classification model's predictions were right and wrong, compared with what actually happened. For example, for deliveries that are either late (1) or on time (0), a late delivery counts as a positive and an on-time delivery as a negative. The table shows how many:

  • True positives: late deliveries the model correctly predicted as late
  • False negatives: late deliveries it wrongly predicted as on time
  • False positives: on-time deliveries it wrongly predicted as late
  • True negatives: on-time deliveries it correctly predicted as on time

From probabilities to predictions: XKL.CONFUSIONMATRIX needs predicted outcomes, such as 0 or 1, not probabilities. If your model produces probabilities, for example from XKL.PREDICT, choose a threshold and turn each probability into a prediction, for example =IF(B12>=0.5,1,0). A lower threshold catches more of the 1s but also flags more of the 0s by mistake. XKL.ROCCURVE shows this trade-off across every threshold, and XKL.AUC sums it up in a single number. Use XKL.CONFUSIONMATRIX once you've chosen a threshold, to see exactly how many of each kind of mistake the model makes.

(Advanced) Three or more groups: the table works the same way, with one row and one column per group.

Sample function call
=XKL.CONFUSIONMATRIX(y_true, y_pred)
Parameters
y_true

The actual outcome for each case, in a single row or column, for example 1 if a delivery was late and 0 if it was on time. Outcomes can be numbers or text.

y_pred

The model's predicted outcome for each case, in the same order as y_true. Use the same labels as y_true, for example 0 and 1 in both. These must be predicted outcomes, not probabilities. See above for how to turn probabilities into predictions.

Returns

A table that spills below and to the right of the cell. The top-left cell reads "Actual / predicted", the first column lists the actual outcomes, and the first row lists the predicted outcomes, both in alphabetical order. For 0/1 outcomes, the four counts are:

  • Actual 0, predicted 0: true negatives
  • Actual 0, predicted 1: false positives
  • Actual 1, predicted 0: false negatives
  • Actual 1, predicted 1: true positives
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

An ROC curve charts the tradeoff between the true positive rate and false positive rate as a model's classification threshold changes. For example, a pizza shop that texts customers when a delivery might be late has to decide when to send the text: when the predicted chance of being late is above 0.5? Above 0.3? A lower threshold warns more of the customers whose delivery really is late, but also warns more customers whose delivery arrives on time. XKL.ROCCURVE shows this trade-off at every possible threshold, so you can choose the one that fits.

Each row of the output is one threshold. It shows the share of on-time deliveries the model would wrongly predict as late (the false positive rate) and the share of late deliveries it would correctly predict as late (the true positive rate). In general, these are the share of 0s predicted as 1, and the share of 1s predicted as 1. A curve that climbs steeply toward the top-left corner means the model catches most late deliveries while warning few on-time customers. A straight diagonal line means it is no better than guessing. The area under the curve is the AUC, a single number you can calculate with XKL.AUC.

Drawing the curve: select the output, including its header row, and choose Insert > Scatter.

Choosing a threshold: each point is a threshold you could use to turn probabilities into predictions. To see the exact counts behind any point, use that threshold with XKL.CONFUSIONMATRIX.

Sample function call
=XKL.ROCCURVE(y_true, y_pred)
Parameters
y_true

The actual outcome for each case, in a single row or column, for example 1 if a delivery was late and 0 if it was on time. There must be exactly two different outcomes. With text outcomes such as "no" and "yes", the one that comes second alphabetically (here "yes") is treated as the positive outcome.

y_pred

The model's predicted probability of 1 for each case, in a single row or column, in the same order as y_true. Unlike XKL.AUC, this must be a single column: if the probabilities come from XKL.PREDICT, select only its second column (the probability of 1), without the header.

Returns

A two-column table headed False positive rate and True positive rate, which spills below and to the right of the cell. There is one row per threshold, starting from the highest predicted probability and working down to the lowest, so both rates rise from top to bottom and the last row is (1, 1). If there are more than 20 different probabilities, 20 evenly spread thresholds are used.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Predicts the outcome for new data, such as next month's sales, using a model you have already built. Build the model first (either with a FIT function, or on the Predict tab with Output model object ticked). Then give XKL.PREDICT the model's cell and the new data for which you want to make a prediction. For example, if the model is in A5 and the new data is in A17:B20, you would write =XKL.PREDICT(A5,A17:B20).

Sample function call
=XKL.PREDICT(model, data)
Parameters
model

The cell holding the fitted model, for example A5.

data

The new rows, including a header row. The column names must match the predictors the model was trained on exactly, including capital letters. The outcome column is not needed.

Returns

A table of predictions, with one row for each row of new data. It fills the cells below the formula.

  • If the model predicts a number, such as sales, you get one column with the title Prediction.
  • If the model predicts a yes/no or a category, such as late or on time, you get one column for each possible answer, giving the probability of that answer. For logistic regression, the columns are titled 0 and 1, the two values in your outcome column (for example, 0 = on time and 1 = late).
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Turns items described by high-dimensional vectors (i.e. many numbers, representing many dimensions) into points on a two-dimensional graph (i.e., an "x value" and a "y value"), so you can plot them and see which items are similar. Similar items end up close together, and different items end up far apart.

It is particularly when applied to embeddings. Embedding models (which you can access using XKL.EMBED), turn each piece of text or image into a long list of numbers (often more than a thousand) which capture the "essence" of that text or image. You can't plot that many dimensions, but XKL.MDS reduces them to two per item. Plot those on a scatter chart, and you can see how the model grouped your items: for example, whether it put reviews about late deliveries together, apart from reviews about taste.

Drawing the map: plot the two output columns to see how close the items are to each other. If you would like to automatically create a plot with labels, use the "Create compound plot" feature in XLKitLearn's GenAI tab: select the first output column as the x-values, the second as the y-values, and the item names as labels, so you can tell which point is which. If you embedded images, you can use the images themselves as labels.

How it works: MDS (multidimensional scaling) measures the distance between every pair of rows, using all their columns. It then places the points on the map so that those distances are kept as closely as possible.

Reading the map: only the distances between points matter. The coordinates have no units, and the map can come out rotated or flipped, for example with a different seed, while showing the same picture.

Other data: XKL.MDS works with any table of numbers, not just embeddings. For example, you could map customers by how often they visit, how much they spend and how far away they live, to see which customers are alike. Columns with bigger numbers count more, so if one column is a price in dollars and another is a 1–5 rating, the price will dominate the map. Put the columns on similar scales first, for example with Excel's STANDARDIZE.

Sample function call
=XKL.MDS(data, [seed], [n_init])
Parameters
data

The numbers describing each item, with one row per item and one column per measure, for example one row per review and one column per number in its embedding. Select only the numbers: leave out the header row and any name column.

seed optional

MDS starts from random positions and improves them. The seed fixes that random start, so you get the same map every time. A different seed may give a rotated or flipped version of the same map. Defaults to 123.

n_init optional

How many times MDS starts from different random positions. It keeps the best map. More starts can give a slightly better map but take longer. Defaults to 25, and you rarely need to change it.

Returns

Two columns of numbers, with one row for each row of data, in the same order. Each row is that item's position on the map: the first column is across and the second is up. There is no header row. The output fills the cells below and to the right of the formula.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Turns a number into a probability between 0 and 1. It is the last step of a logistic regression.

When you fit a logistic regression, you get an intercept and a coefficient for each variable. For example, a pizza shop's model for late deliveries might be -4 + 0.8 × distance in miles. Plugging in a distance gives a number, but not a probability: a 2-mile delivery gives -2.4, and an 8-mile delivery gives 2.4. The sigmoid turns these numbers into probabilities: -2.4 becomes 0.08 (an 8% chance of being late), and 2.4 becomes 0.92 (92%). That is why a logistic regression's predictions are always between 0 and 1.

The sigmoid follows an S-shaped curve. 0 becomes 0.5, large positive numbers become probabilities close to 1, and large negative numbers become probabilities close to 0, without ever quite reaching them.

When you need it: usually you don't, because XKL.PREDICT does this step for you. Use XKL.SIGMOID when you want to work out a prediction yourself from the coefficients, for example to build a what-if calculator: change a delivery's distance and see how the chance of it being late changes.

The formula is 1 / (1 + EXP(-x)).

Sample function call
=XKL.SIGMOID(x)
Parameters
x

The number to turn into a probability. Usually you calculate it yourself from a logistic regression's coefficients: the intercept plus each coefficient times its variable, such as -4 + 0.8 × distance. To see the coefficients, use .coefficients on a model from XKL.FITLOGISTICREGRESSION, for example =A5.coefficients. Don't use the predictions from XKL.PREDICT: they are already probabilities. You can give a single cell, or a row or column of cells to convert several at once. With several cells, the results always come out side by side in a row, even if the numbers are in a column.

Returns

The probability for each number in x, between 0 and 1. For a single cell, you get one number. For a row or column of cells, you get a row of probabilities in the same order, filling the cells to the right.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Statistics

Estimate statistical models and inspect coefficient estimates and inference.

Fit a two-stage least squares instrumental variables regression using statsmodels. Write the formula as known_y ~ exog_x | endog_x | instruments, with multiple terms joined by +. Exogenous regressors are included automatically in the instrument matrix; the final section lists excluded instruments. An intercept is included by default. Use y ~ 1 | d | z for an intercept with no exogenous predictors, or y ~ 0 | d | z to omit the intercept. Use y ~ x - 1 | d | z for exogenous predictors without an intercept. Missing or nonfinite model values, collinear columns, and underidentified models return an error. Standard errors use the usual homoskedastic 2SLS covariance with residual degrees of freedom n - k.

Sample function call
=XKL.TWOSLSREG(data, formula)
Parameters
data

The observations, including a header row with unique column names for the outcome, regressors, and instruments.

formula

A formula in quotes, for example "y ~ x1 + x2 | d | z1 + z2". The sections specify the outcome and exogenous regressors, endogenous regressors, and excluded instruments.

Returns

A spilled coefficient table with variable names, coefficients, standard errors, 95% confidence intervals, p-values, and significance stars.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

GenAI - core

Send prompts to language models and create embeddings through OpenRouter.

Sends a prompt to an AI model, such as ChatGPT or Claude, and shows its answer in the cell. Use it, for example, to label hundreds of customer reviews as Positive or Negative. Each call costs a small amount of your OpenRouter credit, so XLKitLearn does not send the prompt as soon as you type the formula. The cell shows Ready to run until you select it and click the run icon at the bottom of the XLKitLearn pane. There are two ways to call this function:

  • To ask one question, write the prompt in quotes. To add a cell's text to the prompt, join it on with &. If a review is held in cell A9, you would write =XKL.LLM("Is this pizza review Positive or Negative? Reply with one word. Review: "&A9).
  • To ask a follow-up question, remember that AI models have no memory. Each call starts from scratch, so you must send the whole conversation so far. Put your first prompt, the model's first answer and your next prompt in one column, in that order. If they are in A9, A10 and A11, you would write =XKL.LLM(A9:A11). Because the whole conversation is sent each time, long conversations cost more.

The other parameters, described below, are optional. They let you pick the model, limit the length of the answer, and more.

The output of this formula is an LLM response object, which shows the start of the LLM's response. To get the answer as plain text that other formulas can use, add .Content to the cell, for example =A5.Content. See the "Returns" box below for more details.

Keep the cell selected while it runs; this will allow XLKitLearn to stream the response (reveal it bit by bit) in a box at the bottom of the XLKitLearn pane.

Sample function call
=XKL.LLM(message, [model], [tools], [response_format], [reasoning], [temperature], [max_tokens], [auto_tool_run])
Parameters
message

Your prompt, either text in quotes, or a cell holding the text. To ask a follow-up question, include your entire conversation so far, as a vertical range such as A9:A11.

model optional

Which AI model to use, in quotes. You can use a short name, in lower case: "chatgpt", "claude-haiku", "claude-sonnet", "claude-opus", "gemini-pro", "gemini-flash", "grok", "deepseek", "kimi" or "glm". Each short name uses the latest version of that model. To pick a specific version, give its full name from the OpenRouter model list, for example "openai/gpt-5.4-mini". If you omit this argument, OpenRouter will look at your prompt and try to determine the cheapest model that will give you a good response.

tools optional

Lets the model do things it can't do on its own, such as search Google Maps or send an email. Each of these is called a tool. Create each tool in a cell of its own, using a function from the GenAI - tools section, then provide those cells here, for example C2:C4. You can't use tools and response_format in the same call. For a step-by-step explanation, see the GenAI - tools section.

response_format optional

Forces the model answer in a fixed format, so you can ensure the output is structured as you want it to be. There are two ways to do this:

  • To get a single response out of the LLM but to force the response to be a number, integer (whole number) or boolean (true or false), pass "number", "integer", or "boolean" respectively to this argument.
  • To get several specific pieces of information from one prompt (for example, whether a review is Positive or Negative, *and* a rating from 1 to 5), use the helper function XKL.GETRESPONSEFORMATFIELD. Select the resulting cells here.

You can't use response_format and tools in the same call.

reasoning optional

How much the model thinks before it answers, in quotes: "high", "medium", "low" or "none". More thinking can help with harder questions, but it's slower and costs more. Omit this to use the model's default setting. Some models don't support this setting and show an error if you use it, or ignore it completely.

temperature optional

How varied the answers are, as a number from 0 to 2. Lower numbers give more consistent answers, so the same prompt tends to get the same answer each time. Higher numbers give more varied, creative answers. Omit this to use the model's default setting. Some models don't support this setting and show an error if you use it, or ignore it completely.

max_tokens optional

The longest answer the model can write, measured in tokens. Omit this to allow up to 5,000 tokens. If the model reaches the limit, its answer stops part way through. To count the tokens in a piece of text, use XKL.TOKENIZE.

auto_tool_run optional

When the model wants to use one of your tools, it decides which tool to use and what to put in the request, for example the words to search Google Maps for, but it doesn't run the tool automatically unless this setting is set to TRUE:

  • Omit this argument, or pass FALSE, to have the LLM function return a list of tools it wants to use without running them automatically. To inspect those requests, run .[Tool calls] on the LLM result, and run the tools requested. In the next XKL.LLM formula, include this cell and all the tool results.
  • Pass TRUE to have XLKitLearn run the tools straight away and save the results in this cell, then include just this cell in your next XKL.LLM formula. Be careful with tools that send emails or texts, as they will be sent without asking you first.

For a step-by-step explanation, see the GenAI - tools section.

Returns

An LLM response object, which shows the start of the LLM's response. Click the small speech bubble at the start of the cell to see the full answer, its cost and more.

It also exposes the following elements through dot notation. For example, if the answer is in cell A5, type =A5.Content in an empty cell.

  • .Content: the answer as plain text, so you can use it in other formulas.
  • .Cost: what it cost, in cents.
  • .[Time taken]: how long it took, in seconds.
  • .field_ followed by a name, such as .field_mood: if you asked for separate answers with response_format, each answer will be returned in one such field. If you prefer to retrieve every answer at once, use .Content, to get a table of all fields.
  • .[Tool calls]: the model's requests to use a tool, as a table filling the cells below and to the right. See auto_tool_run above.
  • .[Reasoning summary]: a short summary of the model's thinking, for models that support reasoning.
  • .[Prompt tokens], .[Cached prompt tokens], .[Total completion tokens] and .[Reasoning tokens]: how many tokens were sent to the model, how many of those it had seen recently (these usually cost less), how many it responded with, and how many it used for reasoning.

(Advanced) XLKitLearn also exposes the raw JSON that is sent to the OpenRouter API, and the response received back. To access this, click on the cell containing the LLM response, click on the 'json' button at the bottom of the XLKitLearn pane, and paste the text in your favorite text editor.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Turns a piece of text into an embedding: a long list of numbers that captures the text's meaning. Texts with similar meanings get similar numbers, so you can measure how close two pieces of text are, for example to find which customer reviews talk about the same thing.

Like XKL.LLM, each use costs a little, so the cell shows Ready to run until you select it and click the run icon at the bottom of the XLKitLearn pane.

To compare two embeddings, for example in A5 and A6, you could write =SUMSQ(A5.Embedding-A6.Embedding), to find the Pythagorean distance between the two vectors. The smaller the result, the more similar the two texts. You could also use a more advanced measure of distance called the cosine distance.

To visualize these embeddings, you can use the XKL.MDS function.

Sample function call
=XKL.EMBED(text, [model])
Parameters
text

The text to turn into an embedding, either in quotes or a cell holding it. With a model that supports images, this can also be a cell containing an Excel IMAGE formula.

model optional

Which embedding model to use, in quotes. Omit this to use OpenAI's "openai/text-embedding-3-small" embedding. You can also use the short names "openai" for that model and "gemini" for Google's "google/gemini-embedding-2", or give any embedding model's full name from the OpenRouter model list. You can only compare embeddings made with the same model. OpenAI's model does not support images, Gemini's does.

Returns

An embedding object. Click the small icon at the start of the cell to see its cost and more.

It also exposes the following elements through dot notation. For example, if the embedding is in cell A5, type =A5.Cost in an empty cell.

  • .Embedding: the list of numbers itself, in one row. It is very long, so it fills many cells to the right. You will usually use it inside another formula instead, such as =SUMSQ(A5.Embedding-A6.Embedding).
  • .Cost: what it cost, in cents.
  • .[Time taken]: how long it took, in seconds.
  • .Tokens: how many tokens the text used.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

GenAI - helpers

Define structured responses, inspect tokenization, and analyze token probabilities.

This function produces response format fields for use in the XKL.LLM function. In particular, if you want the response from an LLM to include several specific, distinct components (eg: a review's mood, estimated star rating, and any product it might refer to), you would set up each of these components using this function, and pass the resulting three cells to the response_format argument of XKL.LLM.

Interestingly, some models have trouble following specific instructions - the example below uses gpt-6-luna, which works pretty well. Try it with deepseek and see how it performs.

Sample function call
=XKL.GETRESPONSEFORMATFIELD(short_name, parameter_type, [description], [is_list])
Parameters
short_name

This specific field's name, in quotes. For example "mood", or "star_rating". This name cannot contain spaces. In the response to XKL.LLM, you'll be able to retrieve this component of the response using .field_mood.

parameter_type

The kind of answer, in quotes: "string" for text, "integer" for a whole number, "number" for any number, or "boolean" for yes or no (which comes back as 1 or 0).

description optional

Instructions for the model about what this particular field should contain, in quotes, for example "This should contain the word 'positive' or 'negative', describing the mood of the review".

is_list optional

TRUE if the answer is a list, such as several toppings. It then fills the cells to the right. Omit this for a single answer.

Returns

A response format object, which should be passed to the response_format argument of XKL.LLM.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Splits a piece of text into tokens, the small pieces of text an AI model reads and writes. AI models charge by the token, and there is a limit to how many tokens they can read in every prompt, so this helps you check how long a prompt is before you send it. It runs inside Excel without calling an AI model, so it's free and gives its answer straight away. For example, if your prompt is in A9, you would write =XKL.TOKENIZE(A9). To count the tokens, write =COLUMNS(A5#), where A5 is the cell with the XKL.TOKENIZE formula. The count is exact for some OpenAI models, including the default model of XKL.EMBED, and close for most others, since each model tokenizes text a little differently.

Sample function call
=XKL.TOKENIZE(text)
Parameters
text

The text to split, either in quotes or a cell holding it.

Returns

The tokens, one per cell, filling the cells to the right of the formula.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Large language models produce answers one token at a time. In each step, the model considers a what token it might generate next, and assigns a probability to each of these potential tokens. It then randomly picks from those tokens according to those probabilities.

XKL.LLMPROBS sends your prompt to GPT-4.1 and shows, for each token of the answer, the 20 top candidate tokens it was considering and how likely each one was. It always uses GPT-4.1, because newer OpenAI models no longer make these probabilities available.

The table grows to the right with every token, so ask for a short answer, for example by adding "Reply in 5 words at most" to your prompt.

**Note that XLKitLearn will format this function's response to make it readable, so we advice using it on a blank Excel sheet.*

Sample function call
=XKL.LLMPROBS(message)
Parameters
message

Your prompt, either text in quotes, or a cell holding the text. Unlike XKL.LLM, it only takes a single prompt, not a conversation.

Returns

A table filling the cells below and to the right of the formula, 21 rows deep.

  • The first two columns give details such as the full answer (Completion), the number of tokens and the cost in cents.
  • After an empty column, each token of the answer gets its own block. The top row shows the token the model picked, and the rows below list the 20 tokens it was most likely to pick, each with its probability.

The answer stops after 100 tokens.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

GenAI - tools

Connect language models and worksheets to messaging, email, Python, SQL, maps, weather, market data, flights, and location services.

Sends a text message to a US phone number, for example to tell a customer their order is on its way. For example, you would write =XKL.SENDTEXT("+12125550100","Your pizza is on its way."). The text comes from XLKitLearn, not from your own phone, so replies come back to XLKitLearn too. There are two ways to see them:

  • Set wait_for_reply to TRUE, and the cell waits up to about 3 minutes and shows the first reply.
  • Check at any time with XKL.GETTEXTRESPONSES (see that function for details).
Sample function call
=XKL.SENDTEXT(phone_number, message, [wait_for_reply])
Parameters
phone_number

The number to text, in quotes, as +1 followed by the 10 digits with no spaces, for example "+12125550100". Only US numbers work. Put it in quotes, because Excel drops the + from a number typed on its own.

message

The text to send, in quotes, 159 characters at most. Use plain keyboard characters only, with no emoji or accented letters such as é. Curly quotes and long dashes are changed to plain ones for you.

wait_for_reply optional

TRUE to keep the cell waiting after the text is sent, for up to about 3 minutes, and show the first reply. Omit this, or give FALSE, to finish as soon as the text is sent. You can still check for replies later with XKL.GETTEXTRESPONSES.

Returns

The text you sent, shown in the cell as Text message.

It also exposes the following elements through dot notation. For example, if the text is in cell A5, type =A5.Reply in an empty cell.

  • .[Phone number] and .Message: the number and message you sent.
  • .[Text ID]: the text's ID, which XKL.GETTEXTRESPONSES, detailed below, uses to find replies.- .Reply: the first reply, if you set wait_for_reply to TRUE and a reply came within about 3 minutes.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets XKL.LLM send SMS text messages. Pass the returned LLM Tool entity into the tools argument of XKL.LLM.

Sample function call
=XKL.SENDTEXTTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that sendText call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity. The tool requires a US +1 phone number and a message, and supports an optional wait-for-reply flag.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Shows the replies to a text sent with XKL.SENDTEXT, detailed above. Give it the text's ID: if the text is in A5, you would write =XKL.GETTEXTRESPONSES(A5.[Text ID]). The cell shows how many replies have come in so far, for example "Text responses (2 responses)". It shows #VALUE until a reply arrives. To check again, select the cell, click in the formula bar and press Enter.

Sample function call
=XKL.GETTEXTRESPONSES(text_id)
Parameters
text_id

The text's ID, from the .[Text ID] of an XKL.SENDTEXT cell, for example A5.[Text ID].

Returns

The replies, shown in the cell as Text responses, with the number received so far.

It also exposes the following elements through dot notation. For example, if the replies are in cell A5, type =A5.Responses in an empty cell.

  • .Responses: the replies, one per cell, filling the cells below.
  • .[Text ID]: the ID you gave.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets XKL.LLM look up replies to a sent text message. Pass this LLM Tool entity into the tools argument of XKL.LLM.

Sample function call
=XKL.GETTEXTRESPONSESTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that getTextResponses call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for retrieving SMS replies by text ID.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Sends an email, for example to confirm a customer's catering order. For example, you would write =XKL.SENDEMAIL("[email protected]","Your catering order","Thanks for your order of 10 large pizzas for Friday."). The email comes from XLKitLearn, not from your own email account, so replies come back to XLKitLearn too. There are two ways to see them:

  • Set wait_for_reply to TRUE, and the cell waits up to about 3 minutes and shows the first reply.
  • Check at any time with XKL.GETEMAILTHREAD, detailed below, which shows the whole conversation.
Sample function call
=XKL.SENDEMAIL(send_to_address, [email_subject], [email_text], [wait_for_reply], [thread_token])
Parameters
send_to_address

The address to send to, in quotes, for example "[email protected]".

email_subject optional

The subject line, in quotes. Omit this to send the email with "(no subject)".

email_text optional

The body of the email, in quotes. Omit this to send the email with "(no message)".

wait_for_reply optional

TRUE to keep the cell waiting after the email is sent, for up to about 3 minutes, and show the first reply. Omit this, or give FALSE, to finish as soon as the email is sent. You can still check for replies later with XKL.GETEMAILTHREAD.

thread_token optional

To send this email as a follow-up in an earlier email's conversation, give that email's thread token. If the earlier email is in A5, give A5.[Thread token]. Omit this to start a new conversation.

Returns

The email you sent, shown in the cell as Email.

It also exposes the following elements through dot notation. For example, if the email is in cell A5, type =A5.Reply in an empty cell.

  • .Reply: the first reply, if you set wait_for_reply to TRUE and a reply came within about 3 minutes.
  • .To, .Subject and .Message: what you sent.
  • .[Thread token]: the conversation's ID. XKL.GETEMAILTHREAD, detailed below, uses it to find replies, and you give it as thread_token to send a follow-up.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets XKL.LLM send emails. Pass the returned LLM Tool entity into the tools argument of XKL.LLM.

Sample function call
=XKL.SENDEMAILTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that sendEmail call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for sending email. The tool requires a recipient address and can optionally set subject, body, wait-for-reply, and thread token.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Shows the whole conversation for an email sent with XKL.SENDEMAIL, detailed above. Give it the email's thread token: if the email is in A5, you would write =XKL.GETEMAILTHREAD(A5.[Thread token]). The cell shows how many messages the conversation has, for example "Email thread (2 messages)". It only reads messages, so it doesn't need Ready to run. It doesn't update by itself. To check for replies, select the cell, click in the formula bar and press Enter.

Sample function call
=XKL.GETEMAILTHREAD([thread_token])
Parameters
thread_token optional

The conversation's thread token, from the .[Thread token] of an XKL.SENDEMAIL cell, for example A5.[Thread token]. This is technically optional, so that if you leave it blank, XLKitLearn rather than Excel catches it and shows you a clear error message.

Returns

The conversation, shown in the cell as Email thread, with the number of messages so far.

It also exposes the following elements through dot notation. For example, if the thread is in cell A5, type =A5.Messages in an empty cell.

  • .Messages: a table with one row per message, giving its number, sender, subject, date and content, filling the cells below and to the right.
  • .[Thread token]: the thread token you gave.
Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets XKL.LLM fetch an email thread by thread token. Pass this LLM Tool entity into the tools argument of XKL.LLM when the model may need to inspect a conversation.

Sample function call
=XKL.GETEMAILTHREADTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that getEmailThread call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for retrieving email thread history by thread token.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Run Python code in the workbook's Python worker and return the value of the last expression as JSON. Use this for quick calculations, data reshaping, or analysis that is easier in Python than in formulas.

Sample function call
=XKL.RUNPYTHON(code)
Parameters
code

Python code to execute. The last statement should be an expression whose value can be serialized to JSON; convert NumPy and pandas values to plain Python lists, dicts, floats, ints, or strings before returning.

Returns

Returns the JSON-serialized value of the final Python expression, or a friendly Python error entity if execution fails. If the last statement is not an expression, the return value is JSON null.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm run Python code for calculations and data analysis. Pass the returned LLM Tool entity into the tools argument of llm when a model should be able to compute rather than only reason in text.

Sample function call
=XKL.RUNPYTHONTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that runPython call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for Python execution. The tool expects code whose final expression is JSON-serializable.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Package an Excel range as a named table that can be queried with DuckDB SQL. Use this once per source table, then pass the resulting SQL Data Table entities to sql or sqlTool.

Sample function call
=XKL.SQLDATATABLE(table, table_name, [description])
Parameters
table

Range containing the table. The first row must contain unique, nonblank column names, and column names cannot contain double quotes.

table_name

SQL table name to use in queries. It must start with a letter and contain only letters, numbers, and underscores.

description optional

Optional description of the table and any columns whose meaning is not obvious. This is especially helpful when the table is exposed to llm through sqlTool.

Returns

Returns a one-cell SQL Data Table entity. The entity stores the source range, table name, description, and inferred column types; pass these entities to sql for direct querying or to sqlTool so an LLM can query the data.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Run a DuckDB SQL query against one or more Excel ranges packaged by sqlDataTable. Use this when you want a normal spilled table result in Excel.

Sample function call
=XKL.SQL(sql_code, tables, [max_response_size])
Parameters
sql_code

DuckDB SQL statement to run. Refer to each source range by the table_name you gave to sqlDataTable.

tables

One or more SQL Data Table entities created by sqlDataTable.

max_response_size optional

Optional maximum serialized response size used when this query is exposed as an LLM tool. Defaults to 2000.

Returns

Returns a spilled table with column headers. Dates are converted to readable date strings and SQL NULL values appear as blanks when called from Excel.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm query selected Excel tables with DuckDB SQL. Use sqlDataTable to define each source table first, then pass those entities here, and pass the returned LLM Tool entity into llm as a tool.

Sample function call
=XKL.SQLTOOL([tables], [max_response_size], [tool_call])
Parameters
tables optional

One or more SQL Data Table entities created by sqlDataTable. Each table name must be unique. To run a pending SQL call manually, this argument may instead be its LLM Tool call entity.

max_response_size optional

Optional maximum serialized response size to tell the tool to allow. Defaults to 2000.

tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that sql call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity that includes the SQL schema, table descriptions, and fixed table references. Give the tool to llm so the model can write SQL and inspect workbook data without copying the full data into the prompt.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Search Google Maps Places with a plain-language query and return normalized place details. This function is staged because it calls an external service: after the formula shows Ready to run, select it and click Run staged cells in selection in the GenAI tab of the side bar.

Sample function call
=XKL.GOOGLEMAPSPLACESSEARCH(query, [restriction_latitude], [restriction_longitude], [restriction_radius_meters], [included_type], [open_now])
Parameters
query

Plain-language search text, for example Columbia University, pizza near Boston, or pharmacies near 10027.

restriction_latitude optional

Optional latitude for a circular location bias. Provide with restriction_longitude and restriction_radius_meters.

restriction_longitude optional

Optional longitude for a circular location bias. Provide with restriction_latitude and restriction_radius_meters.

restriction_radius_meters optional

Radius in meters for the location bias. Required if restriction_latitude and restriction_longitude are set; maximum 50000.

included_type optional

Optional place type filter. If set, only places with that exact Google place type are returned.

open_now optional

TRUE to return only places Google reports as currently open.

Returns

Returns a Google Maps places search entity with cost, result count, and a hidden results table. Results include place_id, display name, addresses, latitude, longitude, Google Maps URI, business status, phone, website, rating, and rating count.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm search Google Maps Places. Pass the returned LLM Tool entity into the tools argument of llm when the model may need to find businesses, addresses, or place IDs before taking another action.

Sample function call
=XKL.GOOGLEMAPSPLACESSEARCHTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that googleMapsPlacesSearch call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for Google Maps place search. The tool returns normalized place records and billed cost metadata.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Compute route duration and distance between two Google place IDs. This function is staged because it calls an external service: after the formula shows Ready to run, select it and click Run staged cells in selection in the GenAI tab of the side bar.

Sample function call
=XKL.GOOGLEMAPSTRAVELTIME(origin_place_id, destination_place_id, [travel_mode], [consider_traffic], [departure_time], [arrival_time], [units])
Parameters
origin_place_id

Raw Google origin place ID, such as the place_id returned by googleMapsPlacesSearch.

destination_place_id

Raw Google destination place ID, such as the place_id returned by googleMapsPlacesSearch.

travel_mode optional

Travel mode. Defaults to DRIVE.

consider_traffic optional

TRUE to request traffic-aware routing. Only supported for DRIVE.

departure_time optional

Optional RFC 3339 departure timestamp, for example 2026-05-12T15:01:23Z. Do not provide together with arrival_time.

arrival_time optional

Optional RFC 3339 arrival timestamp. Google only uses arrival time for TRANSIT routes. Do not provide together with departure_time.

units optional

Distance units. Defaults to IMPERIAL.

Returns

Returns a Google Maps route entity with duration, static_duration, distance, route description, warnings, traffic flag, and billed cost. Use place IDs from Places search rather than addresses for the most reliable routing.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm compute Google Maps route time and distance between place IDs. Pair it with the Places search tool when the model first needs to look up place IDs.

Sample function call
=XKL.GOOGLEMAPSTRAVELTIMETOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that googleMapsTravelTime call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for route duration and distance. The tool requires origin and destination place IDs and supports mode, traffic, time, and units options.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Get current weather or an hourly forecast for a latitude/longitude from Google Maps Weather. This function is staged because it calls an external service: after the formula shows Ready to run, select it and click Run staged cells in selection in the GenAI tab of the side bar.

Sample function call
=XKL.GOOGLEMAPSWEATHER(latitude, longitude, [units_system], [forecast_until])
Parameters
latitude

Latitude of the location, between -90 and 90.

longitude

Longitude of the location, between -180 and 180.

units_system optional

Units system. Defaults to IMPERIAL.

forecast_until optional

Optional New York date/time through which to return hourly forecast data, formatted YYYY-MM-DD,HH:MM. Leave blank for current conditions only.

Returns

Returns a Google Maps weather entity. Current weather exposes condition, temperature, feels_like, humidity, UV index, precipitation, wind, and cloud cover; forecasts expose a hidden forecast_hours table with those fields by hour.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm get current or forecast weather for a latitude/longitude. Pass the returned LLM Tool entity into llm when the model may need weather context.

Sample function call
=XKL.GOOGLEMAPSWEATHERTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that googleMapsWeather call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for Google Maps weather. The tool requires latitude and longitude and can optionally request an hourly forecast through a New York time cutoff.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Fetch daily OHLCV stock prices for one or more equity tickers. This function is staged because it calls an external service: after the formula shows Ready to run, select it and click Run staged cells in selection in the GenAI tab of the side bar.

Sample function call
=XKL.GETSTOCKPRICES(tickers, from, to)
Parameters
tickers

One or more stock ticker symbols. Select a row or column of tickers to request several at once; symbols are normalized to uppercase.

from

Start date as YYYY-MM-DD, or an Excel date cell.

to

End date as YYYY-MM-DD, or an Excel date cell. Must be after from and at least 24 hours ago.

Returns

Returns a spilled table with columns ticker, date, open, high, low, close, and volume. Multiple tickers are stacked in the same output table.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm fetch daily stock prices. Pass the returned LLM Tool entity into the tools argument of llm when the model may need historical OHLCV data.

Sample function call
=XKL.GETSTOCKPRICESTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that getStockPrices call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for daily stock prices. The tool requires tickers, from date, and to date.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Search Duffel flight availability for a one-way, round-trip, or multi-city itinerary. This function is staged because it calls an external service: after the formula shows Ready to run, select it and click Run staged cells in selection in the GenAI tab of the side bar.

Sample function call
=XKL.FLIGHTSEARCH(cabin_class, allow_connection, [from_iata], [to_iata], [outbound_date], [return_date], [legs])
Parameters
cabin_class

Cabin class for the search: economy, premium_economy, business, or first.

allow_connection

TRUE to allow one connection per leg; FALSE to search nonstop options only.

from_iata optional

Origin IATA airport code for a simple one-way or round-trip search. Use with to_iata and outbound_date instead of legs.

to_iata optional

Destination IATA airport code for a simple one-way or round-trip search. Use with from_iata and outbound_date instead of legs.

outbound_date optional

Outbound departure date formatted YYYY-MM-DD. Use with from_iata and to_iata instead of legs.

return_date optional

Optional return departure date formatted YYYY-MM-DD. Only used with from_iata, to_iata, and outbound_date.

legs optional

Detailed flight legs for multi-city or constrained searches. Use a table with columns origin, destination, departure_date, and optional departure_time_from, departure_time_to, arrival_time_from, arrival_time_to. Use 3-letter IATA codes and YYYY-MM-DD dates.

Returns

Returns a Duffel flight search entity with Search ID and a hidden Results table. For multi-leg searches, choose a result's leg_id and pass the Search ID plus selected leg path to flightSearchNextLeg to retrieve the next leg options.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm search Duffel flight availability. Pass the returned LLM Tool entity into llm when the model may need to find flights or compare itineraries.

Sample function call
=XKL.FLIGHTSEARCHTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that flightSearch call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for flight search. The tool supports either simple from/to/date fields or an ordered list of detailed legs with optional time windows.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Continue a Duffel multi-leg flight search after selecting a previous leg option. This function is staged because it calls an external service: after the formula shows Ready to run, select it and click Run staged cells in selection in the GenAI tab of the side bar.

Sample function call
=XKL.FLIGHTSEARCHNEXTLEG(search_id, previous_legs)
Parameters
search_id

Search ID returned by flightSearch.

previous_legs

Selected previous leg path from the result leg_id values, for example 1 or 1.2.5.

Returns

Returns a Duffel next-leg search entity with the same Search ID and a hidden Results table for the next leg. Continue passing the growing previous_legs path until the itinerary is complete.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm continue a Duffel flight search after selecting a previous leg. Use it together with the flight search tool for multi-leg itineraries.

Sample function call
=XKL.FLIGHTSEARCHNEXTLEGTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that flightSearchNextLeg call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for retrieving next-leg flight options by Search ID and previous leg path.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Get the workbook user's public IP address, approximate location, and time zone. Use this when you need coarse location context, not precise GPS coordinates.

Returns

Returns a two-column key/value table with fields from the IP lookup service, such as IP address, city, region or metro code, country, continent, and timezone when available.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Create an LLM tool that lets llm look up the workbook user's public IP address, approximate location, and time zone. Use this only for coarse context; it is not a precise geolocation tool.

Sample function call
=XKL.IPINFOTOOL([tool_call])
Parameters
tool_call optional

Optional LLM Tool call entity from an LLM Output .tool_calls table. When provided, this function runs that ipInfo call instead of returning a tool descriptor.

Returns

Returns an LLM Tool entity for IP-based location lookup. The tool takes no arguments and returns approximate location metadata.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Simulation

Generate random values from commonly used probability distributions for simulation models.

Draws a random number from a normal distribution: the bell-shaped curve where values near the average are most common and values far from it are rare. Use it for quantities such as the number of orders a pizza shop gets each night, daily sales, or the weight of a dough ball. You give it the mean and the standard deviation, which measures how far values typically are from the average. For example, =XKL.SIMNORMAL(40,6.3) gives a random number of orders that is normally distributed with a mean of 30 and a standard deviation of 50.

Running a simulation: each time Excel recalculates, for example when you press F9, you get a new random number. To run your model many times and see the range of outcomes, use the Simulate tab. To get the same numbers every time, turn on Seed in the Simulate tab.

Sample function call
=XKL.SIMNORMAL(mean, standard_deviation)
Parameters
mean

The average value, for example 40 orders a night.

standard_deviation

How spread out the numbers are: how far they typically are from the average. Must be greater than 0. For example, with an average of 40 orders and a standard deviation of 6.3, about two-thirds of nights get between 34 and 46 orders (40 ± 6.3), and about 95% get between 27 and 53 (40 ± 2 × 6.3). A bigger standard deviation means more nights far from the average.

Returns

One random number. A new one is drawn each time Excel recalculates. A small icon next to the number shows that the cell holds a simulated value.

Important note: if you use that number in any calculation (even if you just multiply the cell by 1) the resulting number will not have an icon next to it because it is not a "pure" simulated value.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Draws a random number from a binomial distribution, which counts the number of successes in a fixed number of independent yes-or-no trials. For example, a pizza shop makes 20 deliveries tonight. Each one is either late or on time, with a 10% chance of being late. =XKL.SIMBINOMIAL(20,0.1) simulates one night, and provides the number of deliveries that were late that night.

A single yes or no: with trials set to 1, XKL.SIMBINOMIAL returns 1 or 0, for example =XKL.SIMBINOMIAL(1,0.3) has a 30% chance of returning 1.

Running a simulation: each time Excel recalculates, for example when you press F9, you get a new random number. To run your model many times and see the range of outcomes, use the Simulate tab. To get the same numbers every time, turn on Seed in the Simulate tab.

Sample function call
=XKL.SIMBINOMIAL(trials, probability)
Parameters
trials

How many tries there are, for example 20 deliveries tonight. Must be a whole number, 0 or more.

probability

The chance that it happens on each try, as a number from 0 to 1. For example, 0.1 is a 10% chance that a delivery is late.

Returns

One random whole number between 0 and trials. A new one is drawn each time Excel recalculates. A small icon next to the number shows that the cell holds a simulated value.

Important note: if you use that number in any calculation (even if you just multiply the cell by 1) the resulting number will not have an icon next to it because it is not a "pure" simulated value.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Draws a random number from a Poisson distribution, which counts how many times something happens in a set period when events happen independently at a constant average rate. For example, a pizza shop gets 4 phone orders an hour on average, but some hours get 2 and others get 6. =XKL.SIMPOISSON(4) gives a random number of phone orders for one hour. Use it to count any independent arrivals in a fixed time period, such as how many customers walk in during lunch.

Running a simulation: each time Excel recalculates, for example when you press F9, you get a new random number. To run your model many times and see the range of outcomes, use the Simulate tab. To get the same numbers every time, turn on Seed in the Simulate tab.

Sample function call
=XKL.SIMPOISSON(mean)
Parameters
mean

The average number of times it happens in the period, for example 4 phone orders an hour. The period is whatever your average refers to: for orders per night, use the average per night. It doesn't need to be a whole number, so 2.5 works too. Must be 0 or more.

Returns

One random whole number, 0 or more. A new one is drawn each time Excel recalculates. A small icon next to the number shows that the cell holds a simulated value.

Important note: if you use that number in any calculation (even if you just multiply the cell by 1) the resulting number will not have an icon next to it because it is not a "pure" simulated value.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Draws a random number from an exponential distribution, which describes how long you have to wait until something happens, when it happens independently at a steady average rate. For example, if a pizza shop gets a phone order every 15 minutes on average - the time till the next phonecall is exponentially distributed with a rate of 1/15 events per minute. Thus, =XKL.SIMEXPONENTIAL(1/15) gives a random number of minutes until the next phone order.

Exponential and Poisson: they describe the same situation from two sides. If the shop gets 4 phone orders an hour on average, XKL.SIMPOISSON(4) simulates how many orders arrive in an hour, and XKL.SIMEXPONENTIAL(1/15) simulates how many minutes until the next one.

Running a simulation: each time Excel recalculates, for example when you press F9, you get a new random number. To run your model many times and see the range of outcomes, use the Simulate tab. To get the same numbers every time, turn on Seed in the Simulate tab.

Sample function call
=XKL.SIMEXPONENTIAL(rate)
Parameters
rate

How many times it happens per unit of time, which is 1 divided by the average wait. For example, use 1/15 if orders come every 15 minutes on average. Must be greater than 0.

Returns

One random number, 0 or more, in the same time unit as rate. A new one is drawn each time Excel recalculates. A small icon next to the number shows that the cell holds a simulated value.

Important note: if you use that number in any calculation (even if you just multiply the cell by 1) the resulting number will not have an icon next to it because it is not a "pure" simulated value.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Draws a random number from a uniform distribution, where every value between a minimum and a maximum is equally likely. For example, if you randomly cut a slice out of a pizza, the angle fo the slice to the horizontal could be anywhere from 0 to 360. =XKL.SIMUNIFORM(0,360) gives a random angle in that range: 53 is just as likely as 75 or 363.

Running a simulation: each time Excel recalculates, for example when you press F9, you get a new random number. To run your model many times and see the range of outcomes, use the Simulate tab. To get the same numbers every time, turn on Seed in the Simulate tab.

(Advanced) Equally likely whole numbers: sometimes you need a whole number where each one is equally likely, for example if a customer orders 1, 2, 3 or 4 pizzas with the same chance each. Round down with INT and add 1 to the maximum: =INT(XKL.SIMUNIFORM(1,5)) gives 1, 2, 3 or 4, each with a 25% chance. Don't use ROUND instead: it makes the smallest and largest numbers half as likely as the others.

Sample function call
=XKL.SIMUNIFORM(minimum, maximum)
Parameters
minimum

The smallest possible value.

maximum

The largest possible value. Must be greater than minimum.

Returns

One random number between minimum and maximum. A new one is drawn each time Excel recalculates. A small icon next to the number shows that the cell holds a simulated value.

Important note: if you use that number in any calculation (even if you just multiply the cell by 1) the resulting number will not have an icon next to it because it is not a "pure" simulated value.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Draws a random number from a triangular distribution: values between a minimum and a maximum, with one most likely value in between. The chances rise steadily from the minimum up to the most likely value, then fall steadily to the maximum, like a triangle. Use it when you can give a rough estimate but have little data, such as "a delivery takes 20 to 50 minutes, most often about 30". For example, =XKL.SIMTRIANGLE(20,30,50) gives a random delivery time: usually between about 24 and 45 minutes, most often close to 30, and never below 20 or above 50.

Most likely is not the average: when the most likely value isn't in the middle of the range, the average shifts toward the longer side. Here the average is about 33 minutes, not 30, because some deliveries take much longer. The average is (minimum + most likely + maximum) / 3.

Running a simulation: each time Excel recalculates, for example when you press F9, you get a new random number. To run your model many times and see the range of outcomes, use the Simulate tab. To get the same numbers every time, turn on Seed in the Simulate tab.

Sample function call
=XKL.SIMTRIANGLE(minimum, most_likely, maximum)
Parameters
minimum

The smallest possible value, for example 20 minutes for the fastest delivery.

most_likely

The value that comes up most often, for example 30 minutes for a typical delivery. This is the most common value, not the average. Must be between minimum and maximum.

maximum

The largest possible value, for example 50 minutes for the slowest delivery. Must be greater than minimum.

Returns

One random number between minimum and maximum. A new one is drawn each time Excel recalculates. A small icon next to the number shows that the cell holds a simulated value.

Important note: if you use that number in any calculation (even if you just multiply the cell by 1) the resulting number will not have an icon next to it because it is not a "pure" simulated value.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Utilities

Perform common worksheet transformations, set operations, counts, and positional lookups.

Counts how many times each value appears in a list, for example how many orders there were for each type of pizza. It lists every distinct value once with its count, sorted from most to least common. It works like a quick pivot table, in one formula. Use it to get a feel for a column of data before you analyze it:

  • See what's most common: which pizzas sell best, or which complaint comes up most in reviews.
  • Spot messy data: typos and inconsistent spellings, such as "Pepperoni" and "pepperoni", show up as separate rows.
  • Check the balance of outcomes: before fitting a classification model, see what share of deliveries were late (1) and on time (0).

Blank cells: blank cells in the range are counted too, as an empty value. Select only the cells with data, and leave out the header.

Sample function call
=XKL.GETCOUNTS(values, [return_proportions], [case_sensitive])
Parameters
values

The values to count, in a single row or column, for example the pizza type of each order. They can be text or numbers. Don't include the header, or it will be counted as a value.

return_proportions optional

Leave blank or use FALSE to return the number of times each value appears. Use TRUE to get the proportion of each value in the list. Format the column as a percentage to show 0.4 as 40%.

case_sensitive optional

TRUE, the default, counts "Cheese" and "cheese" separately. FALSE counts them together, shown with whichever spelling comes first in the list.

Returns

A table with a header row and two columns: Value, and Counts (or Proportion, with "PERCENTAGES"). There is one row per distinct value, sorted from most to least common, with ties in alphabetical order. It fills the cells below and to the right of the formula.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Lists the values in one range that don't appear in another. Each value appears once in the result, in the order it first appears in the first range. Use it to compare two lists:

  • Find who's gone: customers who ordered last month but not this month.
  • Find what's new: swap the two ranges to get customers who ordered this month but not last month.
  • Find what's missing: menu items that got no orders this week, by starting from the full menu and removing the items that were ordered.

Exact matches only: values must match exactly. "Ana" and "ana" count as different, and so do the number 2 and the text "2". An extra space also makes two values different.

Sample function call
=XKL.SUBTRACTSETS(first_range, second_range)
Parameters
first_range

The list to start from, for example last month's customers. Any value that also appears in second_range is removed.

second_range

The values to take out, for example this month's customers. Values that appear here but not in first_range, such as new customers, are ignored.

Returns

A single column listing each value from first_range that isn't in second_range, once each, in the order they first appear. There is no header row. It fills the cells below the formula.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Looks at a column or row of numbers and returns the matching label for the largest one, such as the pizza that sold the most slices. You can also ask for the second largest, third largest, and so on. Give it:

  • the numbers, such as slices sold
  • the matching labels in the same order, such as pizza names (pictures work too)
  • which rank you want: 1 for the largest, 2 for the second largest, and so on

Excel's built-in MAX and LARGE functions return the number itself (185 slices). XKL.ARGMAX returns which item it belongs to (Pepperoni). If you leave out the labels, it returns the item's position in the list instead.

Use it to:

  • Find the top performer: which pizza sold the most this week.
  • List the top few: put n = 1, 2 and 3 in three cells to get a top-three list.
  • Pick a model's predicted group: for a row of predicted probabilities from XKL.PREDICT, with the group names as labels, it returns the group with the highest probability.

Ties: if two values are equal, the one that comes first in the list wins.

Sample function call
=XKL.ARGMAX(vector, [labels], [n])
Parameters
vector

The numbers to compare, in a single row or column, for example each pizza's sales this week.

labels optional

A row or column of names, one for each value in vector and in the same order, for example the pizza names. When you give labels, the function returns the name instead of the position. It must have the same number of cells as vector.

n optional

Which value to find: 1 for the largest (the default), 2 for the second largest, and so on. It must be between 1 and the number of values.

Returns

The label of the requested value if you give labels. Otherwise, its position in the list: 1 for the first cell, 2 for the second, and so on.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Looks at a column or row of numbers and returns the matching label for the smallest one, such as the pizza that sold the fewest slices. You can also ask for the second smallest, third smallest, and so on. Give it:

  • the numbers, such as slices sold
  • the matching labels in the same order, such as pizza names (pictures work too)
  • which place you want: 1 for the smallest, 2 for the second smallest, and so on

Excel's built-in MIN and SMALL functions return the number itself (60 slices). XKL.ARGMIN returns which item it belongs to (Tomato Pie). If you leave out the labels, it returns the item's position in the list instead.

Use it to:

  • Find the weakest performer: which pizza sold the least this week.
  • List the bottom few: put n = 1, 2 and 3 in three cells to get a bottom-three list.
  • Find the cheapest or fastest option: for example, the supplier with the lowest price, or the driver with the shortest delivery time.

Ties: if two values are equal, the one that comes first in the list wins.

Sample function call
=XKL.ARGMIN(vector, [labels], [n])
Parameters
vector

The numbers to compare, in a single row or column, for example each pizza's sales this week.

labels optional

A row or column of names, one for each value in vector and in the same order, for example the pizza names. When you give labels, the function returns the name instead of the position. It must have the same number of cells as vector.

n optional

Which value to find: 1 for the smallest (the default), 2 for the second smallest, and so on. It must be between 1 and the number of values.

Returns

The label of the requested value if you give labels. Otherwise, its position in the list: 1 for the first cell, 2 for the second, and so on.

Working example

Open the downloaded workbook, or paste the copied example into cell A1.

Results