Anomaly Detection in Excel — Find Outliers and Revenue Spikes with Rolling Z-Scores
A single revenue spike or unexpected drop can mean a tracking error, a broken integration, or a genuine business event — and the difference matters enormously before a month-end report goes out. This tutorial shows you how to build a rolling z-score anomaly detector in pure Excel formulas. No add-ins, no macros. By the end you’ll have a column that flags every statistically unusual data point and a conditional formatting heatmap that makes outliers impossible to miss.
TL;DR
Add a rolling mean (OFFSET + AVERAGE over a 28-day window), a rolling standard deviation (OFFSET + STDEV), and a z-score column =(value - rolling_mean) / rolling_stdev. Flag rows where ABS(z) > 2 as anomalies. Apply conditional formatting to highlight them in red. The entire setup takes about 35 minutes and works on any time series with 30+ data points.
Contents
- Step 1 — Organise the time series
- Step 2 — Calculate rolling mean
- Step 3 — Calculate rolling standard deviation
- Step 4 — Calculate z-score
- Step 5 — Flag anomalies with IF formula
- Step 6 — Highlight with conditional formatting
- Anomaly detection methods compared
- Seasonal data — the one gotcha
- When to move beyond Excel
- FAQ
1.Step 1 — Organise the time series
Put dates in column A and your metric values in column B. This works for any numeric time series: daily revenue, weekly order count, hourly sessions, monthly churn rate. Sort the data ascending by date — the rolling window formulas rely on rows being in chronological order.
| A (Date) | B (Revenue) |
|---|---|
| 2024-01-01 | 4,820 |
| 2024-01-02 | 5,110 |
| 2024-01-03 | 4,950 |
| … | … |
You need at least 30 data points for a rolling 28-day window to produce meaningful statistics. With fewer than 30 rows, the early rows will have very small windows and the z-scores will be unstable — likely flagging too many or too few anomalies.
Add headers in row 1: Date, Value, RollingMean, RollingStdev, ZScore, Flag. Data starts in row 2.
2.Step 2 — Calculate rolling mean (28-day window)
In column C (RollingMean), enter this formula in C2 and drag down:
This looks complex but does something simple: it takes an average over the last 28 rows, or fewer rows if we are near the top of the data. Breaking it down:
ROW(B2)-ROW($B$2) is the zero-indexed row position (0 for the first data row, 1 for the second, etc.). MIN(..., 27) limits the offset to at most 27 rows back, so we never try to read before the start of the data. MIN(...+1, 28) gives the height of the window — up to 28 rows, but fewer at the start.
For the first row of data (row 2), the window is just 1 row, so the rolling mean equals the value itself. By row 29, the full 28-day window is in use. This is called a causal rolling window — it only uses past data, which is what you want for anomaly detection in a live series.
3.Step 3 — Calculate rolling standard deviation
In column D (RollingStdev), the formula is identical in structure but uses STDEV instead of AVERAGE:
Use STDEV (sample standard deviation, divides by n−1) rather than STDEVP (population, divides by n). Since the rolling window is a sample of the series, the sample version is statistically correct.
Important: for the first row, STDEV of a single value returns an error (you cannot compute standard deviation from one point). Wrap the formula in IFERROR(..., 0) or start flagging anomalies only from row 3 onwards where there are at least 2 points in the window.
=IFERROR(STDEV(OFFSET(B2,-MIN(ROW(B2)-ROW($B$2),27),0,MIN(ROW(B2)-ROW($B$2)+1,28),1)), 0)
4.Step 4 — Calculate z-score
In column E (ZScore), the formula is straightforward:
This tells you how many standard deviations the current value is from the rolling mean. Wrap in IFERROR to handle the early rows where the stdev is zero:
=IFERROR((B2-C2)/D2, 0)
Interpreting the result:
Z > +2 or Z < −2: statistically unusual — only about 5% of points in a normal distribution fall outside this range. Worth a second look.
Z > +3 or Z < −3: strong anomaly — roughly 0.3% of points. These are almost always genuine events or data errors.
Z between −2 and +2: within normal variation for this window. Not an anomaly by this method.
5.Step 5 — Flag anomalies with IF formula
In column F (Flag), add a plain-language flag:
You can refine this to distinguish direction and severity:
=IF(E2>3,"HIGH SPIKE",IF(E2>2,"SPIKE",IF(E2<-3,"DEEP DROP",IF(E2<-2,"DROP",""))))
Adjust the threshold to match your use case. For a daily revenue series where you want to investigate anything unusual: use 2.0. For a weekly series where you only want to escalate genuine crises: use 2.5 or 3.0. The threshold does not change the underlying statistics — only the number of rows that get flagged.
6.Step 6 — Highlight with conditional formatting
Select the range of values in column B (e.g. B2:B366 for a year of daily data). Go to Home → Conditional Formatting → New Rule → Use a formula to determine which cells to format.
Enter this formula (adjust to match your actual column references):
Set the fill to red. This uses an expanding window (all data from the start up to the current row) rather than a rolling window — it is less precise than the rolling approach above, but requires only a single conditional formatting rule with no helper columns and renders a visible heatmap instantly.
For a more precise highlight, add a second conditional formatting rule that checks the Flag column: formula =$F2="ANOMALY" applied to column B, fill red. This will highlight exactly the rows your rolling z-score formula flagged.
Anomaly detection methods compared
Z-score is not the only approach. Here is how the common methods compare for business time series data in Excel:
| Method | Best for | Robustness to skew | Excel complexity |
|---|---|---|---|
| Rolling z-score | Smooth, roughly normal series (sessions, revenue) | Moderate | Low (3 columns) |
| IQR fence | Skewed or heavy-tailed distributions (order values) | High | Low (2 columns) |
| Percentile threshold | When you want to flag the top/bottom N% | High | Very low (1 formula) |
| Manual inspection | When domain knowledge overrides statistics | N/A | None |
For an IQR fence in Excel: =IF(B2<QUARTILE($B$2:$B$365,1)-1.5*(QUARTILE($B$2:$B$365,3)-QUARTILE($B$2:$B$365,1)),"LOW",IF(B2>QUARTILE($B$2:$B$365,3)+1.5*(QUARTILE($B$2:$B$365,3)-QUARTILE($B$2:$B$365,1)),"HIGH","")). Note this uses the entire series as the reference range — adapt to a rolling window if your series has a strong trend.
Seasonal data — the one gotcha
Rolling z-scores work well on stationary or slowly trending data. They break down on seasonal data. If your revenue spikes every December, a 28-day rolling window will flag December as an anomaly every year — because November and January surround it, pulling the rolling mean down.
Two solutions:
Year-over-year z-score: instead of comparing against the trailing 28 days, compare against the same day or week in the prior year. Calculate (this week’s value) − (same week last year’s value) and compute the z-score of those differences. Seasonal spikes that repeat on schedule will cancel out; genuine deviations from the seasonal pattern will still be flagged.
De-seasonalise first: use Holt-Winters or a seasonal decomposition to extract the residuals (the part of the series not explained by trend or seasonality), then apply z-scores to the residuals. See our Holt-Winters in Excel tutorial for the decomposition step. The residuals are by definition free of seasonal effects, so z-scores on them are far more reliable.
When to move beyond Excel
The Excel rolling z-score approach works well for a single series up to a few thousand rows. The formula refresh time is fast, and the visual output is clear. The limitations appear when you need to:
Monitor many columns at once. If you have 20 metrics (revenue, orders, sessions, refunds, conversion rate, etc.), rebuilding the 4-column setup for each one becomes tedious and error-prone. At that point a live KPI dashboard in Excel — or one of the best dashboard software tools — surfaces every flagged anomaly in one view.
Get real-time alerts. Excel does not send you a notification when a new anomaly appears. You have to open the file to see it.
Auto-tune the window and threshold. The right window size and z-score threshold vary by series. Manually calibrating each one takes significant time.
Want anomaly detection without the formulas?
DataHub Pro runs automated anomaly detection across every column in your CSV or Excel file on upload. Rolling z-scores with automatic window selection, anomaly highlights in the dashboard, and no formula work required.
Try DataHub Pro free →Frequently asked questions
What’s the difference between a z-score and an IQR fence?
What window size should I use for the rolling mean?
My data is seasonal — will z-scores give false positives every Christmas?
What threshold should I use?
Can I do this automatically without Excel formulas?
How do I distinguish a data error from a real business anomaly?
Related guides
- DataHub Pro — Holt-Winters forecasting in Excel (de-seasonalise before applying z-scores).
- DataHub Pro — Moving average in Excel (the smoothed baseline anomalies deviate from).
- DataHub Pro — Variance analysis in Excel (explain the spikes you have flagged).
- DataHub Pro — KPI dashboard in Excel (surface anomalies on a live dashboard).
- DataHub Pro — Regression analysis in Excel (model the trend the residuals are measured against).
- DataHub Pro — All Excel analytics tutorials.
- NIST Engineering Statistics Handbook — Outlier detection methods.
