Functions: BAHTTEXT (#291)

Thai number words with บาท / สตางค์ / ถ้วน, rounded to satang, ล้าน
repeating per six digits, ลบ for negatives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
vangel76 2026-10-11 12:07:41 +02:00
parent 9f896c1249
commit 35d6c23fd1
6 changed files with 130 additions and 18 deletions

View File

@ -197,7 +197,7 @@ egui frontend is a separate crate, so the UI can be swapped without touching the
GridCraft is in **alpha**: the core workflow works end to end, but depth, fidelity and file
compatibility are still rough. It covers 89% of the Excel ribbon commands in our catalog
([`docs/parity-checklist.md`](docs/parity-checklist.md)) and 501 of Excel's 523 worksheet functions
([`docs/parity-checklist.md`](docs/parity-checklist.md)) and 502 of Excel's 523 worksheet functions
([`docs/function-parity.md`](docs/function-parity.md)); weighted by what Excel users rely on, we
estimate it is about 50% ready for real work. Next up: XLSX fidelity on real-world files, very large
workbooks and multi-threaded recalc, chart depth, text in every script, and `.xls` import. Stage,

View File

@ -2,7 +2,7 @@
**Stage: alpha** · next: beta, ~25 points of "ready for real work" and ~160–240 h away
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (full re-measure against Excel for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Excel (Microsoft 365)
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (worksheet functions 502 / 523) · **Target:** Microsoft Excel (Microsoft 365)
GridCraft aims at full Microsoft Excel parity, and at being better in places: faster, open (XLSX
is the native format), fully scriptable by agents (MCP, control channel, CLI), and on the web.
@ -21,7 +21,7 @@ This page is the summary. The detail is in:
| Number | Value | Kind |
|---|---|---|
| **Feature breadth** (weighted) | **~75%** | estimated, anchored on two measurements: ribbon catalog 258 / 290 (89.0%), worksheet functions 501 / 523 (95.8%; 492 working, 94.1%) |
| **Feature breadth** (weighted) | **~75%** | estimated, anchored on two measurements: ribbon catalog 258 / 290 (89.0%), worksheet functions 502 / 523 (96.0%; 493 working, 94.3%) |
| **Ready for real work** | **~50%** | estimated from written weights (51.6); [target-app-parity.md](docs/target-app-parity.md) |
| **Mainstream practitioner** | **~50%** | estimated: typical analyst/finance user, weekly features, × 0.90 interaction × 0.92 stability × 0.88 file exchange; [method](docs/target-app-parity.md#mainstream-practitioner) |
| **Essentials user** | **~63%** | estimated: core features only, × 0.92 launch/stability × 0.95 clarity × 0.90 opening sent files; [method](docs/target-app-parity.md#essentials-user) |
@ -74,7 +74,7 @@ collaboration, mobile, AI).
| Area | Breadth | Ready | Hours | Doc |
|---|---|---|---|---|
| Formula language and calculation | ~92% | ~72% | 20–30 | [target-app-parity.md](docs/target-app-parity.md#feature-areas) |
| Worksheet functions | 95.8% measured | ~82% | 18–30 | [function-parity.md](docs/function-parity.md) |
| Worksheet functions | 96.0% measured | ~82% | 18–30 | [function-parity.md](docs/function-parity.md) |
| Editing, navigation, clipboard, fill | ~90% | ~70% | 15–25 | [ui-parity.md](docs/ui-parity.md) |
| Cell formatting, styles, conditional formatting | ~95% | ~80% | 8–14 | [target-app-parity.md](docs/target-app-parity.md#feature-areas) |
| Sort, filter, tables, validation, outline | ~82% | ~70% | 10–16 | [target-app-parity.md](docs/target-app-parity.md#feature-areas) |
@ -131,6 +131,7 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in
| Date | What landed |
|---|---|
| 2026-10-11 | BAHTTEXT: amounts in Thai words with Baht and Satang (#291) |
| 2026-10-10 | Ribbon translated into Japanese, Chinese, Korean, Brazilian Portuguese and Russian with system-language default (#31, #104, #82); CJK/Thai/Hebrew font fallback (#38); clear messages for encrypted and `.xls` files (#17); smooth line charts (#62). Progress docs restructured to the craftrules standard; full re-measure (this page). Initial ribbon key tips (#43), in-place text box editing (#84), copy as HTML table (#36). ODS and XLSB data import (#100, #101); recalc linear in the number of range formulas (#66); RISC-V Linux build; Flatpak repository on Pages; web cell-commit trap fixed |
| 2026-10-09 | Community fixes: spill range operator `A1#`, sheet-scoped names, protection refuses locked-cell edits, Insert/Delete Cells adjust references, `DATE(1900,2,29)`, SUMIF sizing, `ROUND` at 15 digits, `_xlpm.` LAMBDA parameters in XLSX, vertical scrollbar, system appearance, border previews; v0.4.0 |
| 2026-10-08 | v0.2.0 and v0.3.0 releases; Flatpak, AppImage zsync, branded DMG; desktop log file; DirectX 12 default on Windows |
@ -142,6 +143,7 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in
| Date | Change | Summary |
|---|---|---|
| 2026-10-11 | minor | Worksheet functions 502 / 523 (BAHTTEXT); progress log row |
| 2026-10-10 | minor | Readiness-by-audience table with hours to ~95% per audience; full number unchanged (additive weighted sum) |
| 2026-10-10 | minor | Added Mainstream practitioner (~50%) and Essentials user (~63%); languages updated for the 10-10 merges (ribbon in ja, zh, ko, pt-BR, ru); localization 5%→10%; full number re-checked (51.6, unchanged) |
| 2026-10-10 | minor | Checked against the alpha gate (six core workflows pass): stays alpha |

View File

@ -403,6 +403,88 @@ fn dollar(a: &[Arg], _c: &mut dyn Ctx) -> R<Value> {
text_val(if r < 0.0 { format!("(${body})") } else { format!("${body}") })
}
// ---------------------------------------------------------------------------------------------
// BAHTTEXT
const THAI_DIGITS: [&str; 10] = ["ศูนย์", "หนึ่ง", "สอง", "สาม", "สี่", "ห้า", "หก", "เจ็ด", "แปด", "เก้า"];
/// Units, tens, hundreds, thousands, ten thousands, hundred thousands.
const THAI_PLACES: [&str; 6] = ["", "สิบ", "ร้อย", "พัน", "หมื่น", "แสน"];
/// Thai words for a group of up to six decimal digits (most significant first); empty for zero.
/// One in the tens is สิบ, two is ยี่สิบ, and a final one after higher digits is เอ็ด.
fn thai_group(digits: &[u8]) -> String {
let n = digits.len();
let higher = digits.iter().take(n.saturating_sub(1)).any(|d| *d != 0);
let mut out = String::new();
for (i, &d) in digits.iter().enumerate() {
let place = n - 1 - i;
match (place, d) {
(_, 0) => {}
(0, 1) if higher => out.push_str("เอ็ด"),
(1, 1) => out.push_str("สิบ"),
(1, 2) => out.push_str("ยี่สิบ"),
_ => {
out.push_str(THAI_DIGITS.get(d as usize).copied().unwrap_or_default());
out.push_str(THAI_PLACES.get(place).copied().unwrap_or_default());
}
}
}
out
}
/// Thai words for a whole number written in decimal digits: groups of six digits, each but the
/// last followed by ล้าน (so 10^12 is หนึ่งล้านล้าน).
fn thai_number(digits: &str) -> String {
let d: Vec<u8> = digits.bytes().filter(u8::is_ascii_digit).map(|b| b - b'0').skip_while(|x| *x == 0).collect();
if d.is_empty() {
return "ศูนย์".to_string();
}
let first = match d.len() % 6 {
0 => 6,
r => r,
};
let mut out = String::new();
let mut start = 0;
let mut len = first;
while let Some(group) = d.get(start..start + len) {
out.push_str(&thai_group(group));
start += len;
len = 6;
if start < d.len() {
out.push_str("ล้าน");
}
}
out
}
/// BAHTTEXT(number): the amount in Thai words with บาท, rounded to satang (สตางค์); a whole
/// number of baht ends in ถ้วน and a negative amount starts with ลบ.
fn bahttext(a: &[Arg], _c: &mut dyn Ctx) -> R<Value> {
let x = round_half_away(num(a, 0)?, 2);
if !x.is_finite() {
return Err(CellError::Num);
}
let fixed = format!("{:.2}", x.abs());
let (whole, frac) = fixed.split_once('.').unwrap_or((fixed.as_str(), "00"));
let baht = whole.bytes().any(|b| b != b'0');
let satang = frac.bytes().any(|b| b != b'0');
let mut out = String::new();
if x < 0.0 && (baht || satang) {
out.push_str("ลบ");
}
if baht || !satang {
out.push_str(&thai_number(whole));
out.push_str("บาท");
}
if satang {
out.push_str(&thai_number(frac));
out.push_str("สตางค์");
} else {
out.push_str("ถ้วน");
}
text_val(out)
}
fn t_fn(a: &[Arg], _c: &mut dyn Ctx) -> R<Value> {
match scalar(arg(a, 0)?) {
Value::Text(t) => Ok(Value::Text(t)),
@ -762,6 +844,7 @@ pub(crate) fn specs() -> Vec<FnSpec> {
fixed
),
f!("DOLLAR", 1, 2, Text, S, "DOLLAR(number, [decimals])", "Formats a number as currency text.", dollar),
f!("BAHTTEXT", 1, 1, Text, S, "BAHTTEXT(number)", "Spells out a number in Thai words with Baht.", bahttext),
f!("T", 1, 1, Text, S, "T(value)", "Returns the value if it is text, otherwise empty text.", t_fn),
f!(
"TEXTBEFORE",
@ -856,6 +939,30 @@ mod tests {
use crate::util::testutil::*;
#[test]
fn bahttext() {
let bt = |x: f64| ev("BAHTTEXT", vec![n(x)]);
// Microsoft's example.
is_text(bt(1234.0), "หนึ่งพันสองร้อยสามสิบสี่บาทถ้วน");
// Tens, เอ็ด, satang, millions and beyond, sign and rounding to satang.
is_text(bt(0.0), "ศูนย์บาทถ้วน");
is_text(bt(21.25), "ยี่สิบเอ็ดบาทยี่สิบห้าสตางค์");
is_text(bt(0.5), "ห้าสิบสตางค์");
is_text(bt(101.0), "หนึ่งร้อยเอ็ดบาทถ้วน");
is_text(bt(1_000_000.0), "หนึ่งล้านบาทถ้วน");
is_text(bt(11_000_000.0), "สิบเอ็ดล้านบาทถ้วน");
is_text(bt(2_000_005_000_000.0), "สองล้านห้าล้านบาทถ้วน");
is_text(bt(1e12), "หนึ่งล้านล้านบาทถ้วน");
is_text(bt(-15.5), "ลบสิบห้าบาทห้าสิบสตางค์");
is_text(bt(1.999), "สองบาทถ้วน");
is_text(bt(0.005), "หนึ่งสตางค์");
is_text(bt(-0.001), "ศูนย์บาทถ้วน");
is_err(ev("BAHTTEXT", vec![t("abc")]), CellError::Value);
// Huge numbers give text (or #NUM! where rounding overflows), never a panic.
assert!(matches!(bt(-1e300), Value::Text(_)));
assert!(matches!(bt(f64::MAX), Value::Text(_) | Value::Error(CellError::Num)));
}
#[test]
fn concat_family() {
is_text(ev("CONCATENATE", vec![t("a"), n(1.5), b(true)]), "a1.5TRUE");

View File

@ -1,6 +1,6 @@
# Function parity: worksheet functions and formulas
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created; measured against Microsoft's published Excel function list) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (BAHTTEXT added) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4
Excel's worksheet functions, category by category, against GridCraft's function library. Part of
[target-app-parity.md](target-app-parity.md); gaps feed [gaps.md](gaps.md).
@ -12,7 +12,7 @@ Excel's worksheet functions, category by category, against GridCraft's function
them), plus 14 text functions the page lists under combined entries (FIND/FINDB, LEFT/LEFTB,
LEN/LENB, MID/MIDB, REPLACE/REPLACEB, RIGHT/RIGHTB, SEARCH/SEARCHB), BETA.INV, and COPILOT and
PY (Microsoft 365 functions not on that page when fetched).
- **Ours (501):** every function spec in `crates/functions/src/*.rs` (`f!("NAME", …)`) plus the
- **Ours (502):** every function spec in `crates/functions/src/*.rs` (`f!("NAME", …)`) plus the
evaluator's special forms in `crates/calc/src/eval.rs` (`SPECIAL_FUNCTIONS`: IF, IFS, CHOOSE,
OFFSET, INDIRECT, INDEX, SUBTOTAL, AGGREGATE, TEXT, LET, LAMBDA, MAP, REDUCE, SCAN, BYROW, BYCOL,
MAKEARRAY…), excluding the test-only `ADD2`. Every one is an Excel name.
@ -23,7 +23,7 @@ Excel's worksheet functions, category by category, against GridCraft's function
## Coverage
**Measured: 501 / 523 by name (95.8%); 492 / 523 working (94.1%).**
**Measured: 502 / 523 by name (96.0%); 493 / 523 working (94.3%).**
| Category | Excel | Ours | Working | % working | Missing |
|---|---|---|---|---|---|
@ -31,7 +31,7 @@ Excel's worksheet functions, category by category, against GridCraft's function
| Math and trigonometry | 80 | 79 | 79 | 99% | PERCENTOF |
| Financial | 55 | 51 | 51 | 93% | ODDFPRICE, ODDFYIELD, ODDLPRICE, ODDLYIELD |
| Engineering | 54 | 54 | 54 | 100% | — |
| Text | 50 | 47 | 47 | 94% | BAHTTEXT, DETECTLANGUAGE, TRANSLATE |
| Text | 50 | 48 | 48 | 96% | DETECTLANGUAGE, TRANSLATE |
| Lookup and reference | 40 | 36 | 36 | 90% | GETPIVOTDATA, IMAGE, RTD, TRIMRANGE |
| Compatibility | 40 | 40 | 40 | 100% | — |
| Date and time | 25 | 25 | 25 | 100% | — |
@ -42,9 +42,9 @@ Excel's worksheet functions, category by category, against GridCraft's function
| Web | 3 | 3 | 1 | 33% | (WEBSERVICE, FILTERXML are stubs; ENCODEURL works) |
| Add-in and Automation | 3 | 0 | 0 | 0% | CALL, EUROCONVERT, REGISTER.ID |
| AI and Python | 2 | 0 | 0 | 0% | COPILOT, PY |
| **Total** | **523** | **501** | **492** | **94.1%** | 22 missing, 9 stubs |
| **Total** | **523** | **502** | **493** | **94.3%** | 21 missing, 9 stubs |
By the Excel version that introduced them (working / total): before 2010 342 / 360, 2010
By the Excel version that introduced them (working / total): before 2010 343 / 360, 2010
56 / 56, 2013 49 / 51, 2016 1 / 5, 2019 6 / 6, 2021 11 / 11, 2024 22 / 23, Microsoft 365 5 / 11.
Dynamic-array and LAMBDA-era functions (FILTER, SORT, UNIQUE, XLOOKUP, VSTACK, TAKE, GROUPBY,
PIVOTBY, REGEXTEST…) are all present.
@ -56,7 +56,7 @@ PIVOTBY, REGEXTEST…) are all present.
| FORECAST.ETS family (4) | yes | 4–6 h | AAA exponential smoothing with seasonality detection; needed for Forecast Sheet too |
| ODDFPRICE, ODDFYIELD, ODDLPRICE, ODDLYIELD | yes | 2–4 h | Odd first/last period bond maths |
| GETPIVOTDATA | yes | 2–3 h | Needs the pivot engine's result cache; also the "Generate GetPivotData" option |
| TRIMRANGE, PERCENTOF, BAHTTEXT | yes | 1–2 h | TRIMRANGE also implies the `.:` trim-ref operators |
| TRIMRANGE, PERCENTOF | yes | 1–2 h | TRIMRANGE also implies the `.:` trim-ref operators |
| IMAGE | yes | 3–5 h | Pictures in cells (see PR #105); fetching URLs needs a privacy decision |
| EUROCONVERT | yes | 0.5 h | Fixed conversion table |
| CUBE* (7), WEBSERVICE, FILTERXML | partly | 4–8 h | FILTERXML can work offline; CUBE needs an OLAP/data-model source |
@ -97,4 +97,5 @@ workbooks; results checked in as data, not Excel files) and fixing what it finds
| Date | Change | Summary |
|---|---|---|
| 2026-10-11 | minor | BAHTTEXT added: 502 / 523 by name, 493 working |
| 2026-10-10 | major | Created: 501 / 523 by name, 492 working, per category, against Microsoft's published list |

View File

@ -1,6 +1,6 @@
# Gaps
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created from the full re-measure against Excel for Mac 16.113.4 and the issue tracker) · **Target:** Microsoft Excel (Microsoft 365)
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (§15: BAHTTEXT landed) · **Target:** Microsoft Excel (Microsoft 365)
Every known shortfall against Excel, one entry each, ranked by user impact (what blocks someone
using GridCraft for real work first). This is the work list: pick from the top, check the open
@ -106,7 +106,7 @@ No alpha blockers: every core workflow passes the [alpha gate](roadmap.md#alpha-
#143). **Estimate:** 12–20 h.
### 15. Remaining functions and an oracle suite (F)
- 22 missing, 9 stubs; no Excel-computed oracle corpus; #137, #138. **Estimate:** 18–30 h.
- 21 missing, 9 stubs; no Excel-computed oracle corpus; #137, #138. **Estimate:** 18–30 h.
[function-parity.md](function-parity.md)
### 16. Collaboration and review (F)
@ -149,6 +149,7 @@ No alpha blockers: every core workflow passes the [alpha gate](roadmap.md#alpha-
| Date | Change | Summary |
|---|---|---|
| 2026-10-11 | minor | §15: BAHTTEXT added (21 functions missing) |
| 2026-10-10 | minor | Updated for the 10-10 merges (#17, #31, #38, #62, #82, #104, #116) and the new chart resize bug (#190) |
| 2026-10-10 | minor | Noted that no gap blocks the alpha gate |
| 2026-10-10 | major | Created: 24 ranked gaps with evidence, from the full re-measure and the 60 open issues |

View File

@ -1,6 +1,6 @@
# Target-app parity: GridCraft vs Microsoft Excel
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (first full assessment; re-measure against Excel for Mac 16.113.4, replacing the estimates that lived in ROADMAP.md) · **Target:** Microsoft Excel (Microsoft 365)
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (worksheet functions 502 / 523: BAHTTEXT) · **Target:** Microsoft Excel (Microsoft 365)
This is the authoritative parity assessment. [`ROADMAP.md`](../ROADMAP.md) summarizes it,
[`gaps.md`](gaps.md) lists every shortfall, and the area checklists hold the detail:
@ -14,7 +14,7 @@ generated ribbon checklist is [`parity-checklist.md`](parity-checklist.md).
|---|---|---|
| Feature breadth (weighted by use) | **~75%** | estimated from the area table below; anchored on two measurements |
| Ribbon and menu catalog | **258 / 290 (89.0%)** | measured: `cargo xtask parity` (`crates/engine/src/catalog.rs` ∩ registered command ids) |
| Worksheet functions, by name | **501 / 523 (95.8%)** | measured: registered functions vs Microsoft's published function list (method below) |
| Worksheet functions, by name | **502 / 523 (96.0%)** | measured: registered functions vs Microsoft's published function list (method below) |
| Worksheet functions that do real work | **492 / 523 (94.1%)** | measured: excludes 9 stubs (7 CUBE functions, WEBSERVICE, FILTERXML) |
| **Ready for real work** | **~50%** | estimated; written weights below (51.6 computed) |
| **Mainstream practitioner** | **~50%** | estimated; [method](#mainstream-practitioner) (69.5 depth × 0.90 × 0.92 × 0.88 = 50.6) |
@ -53,7 +53,7 @@ long `.xls` track, so about half parallelizes (≈30–50 wall-clock hours with
LEFT/LEFTB, LEN/LENB, MID/MIDB, REPLACE/REPLACEB, RIGHT/RIGHTB, SEARCH/SEARCHB, BETA.INV) and
COPILOT and PY: **523 functions**. Ours: every `f!(…)` spec in `crates/functions/src/*.rs` plus
`SPECIAL_FUNCTIONS` in `crates/calc/src/eval.rs` (evaluator special forms), minus the test-only
`ADD2`: **501**, all of them Excel names.
`ADD2`: **502**, all of them Excel names.
- **Ribbon catalog:** `crates/engine/src/catalog.rs` (290 unique ids across 15 tabs) against the
313 command ids registered in `crates/engine/src/cmd/*.rs`, recomputed from source by script and
identical to the committed `parity-checklist.md`. The catalog is our own transcription of
@ -80,7 +80,7 @@ performance 8, stability 8, localization 4, hardware 2, platforms 2, ecosystem 2
| Area | Weight | Breadth | Ready | Hours | Evidence |
|---|---|---|---|---|---|
| Formula language and calculation | 18 | ~92% | ~72% | 20–30 | A1/R1C1 parser, reference adjustment, dependency-graph recalc, dynamic arrays and `#SPILL!`, `A1#`, LET/LAMBDA and helpers, structured references, names, 3-D references. Open correctness bugs: 15-digit equality (#57), stale spills after structural edits and cleared blockers (#133, #139), 3-D span endpoint deletion (#140), sheet rename and qualified names (#134). Single-threaded |
| Worksheet functions | 12 | 95.8% (measured) | ~82% | 18–30 | 501 / 523 names, 492 working. Missing: FORECAST.ETS family, ODDF*/ODDL*, GETPIVOTDATA, TRIMRANGE, PERCENTOF, BAHTTEXT, IMAGE plus cloud functions. No conformance suite against Excel-computed oracles; edge-case bugs keep surfacing (#137, #138). [function-parity.md](function-parity.md) |
| Worksheet functions | 12 | 96.0% (measured) | ~82% | 18–30 | 502 / 523 names, 493 working. Missing: FORECAST.ETS family, ODDF*/ODDL*, GETPIVOTDATA, TRIMRANGE, PERCENTOF, IMAGE plus cloud functions. No conformance suite against Excel-computed oracles; edge-case bugs keep surfacing (#137, #138). [function-parity.md](function-parity.md) |
| Editing, navigation, clipboard, fill | 12 | ~90% | ~70% | 15–25 | Point mode, F4, AutoComplete, Paste Special, AutoFill, Flash Fill, Find/Replace, Go To Special. Bugs: rectangular drag-select (#28), monthly fill (#132), cut across sheets (#128), Insert Copied Cells missing (#21), key tips only on part of the Home tab (#43; #33, #49). [ui-parity.md](ui-parity.md) |
| Cell formatting, styles, conditional formatting | 10 | ~95% | ~80% | 8–14 | Full number-format language, borders, 47 cell styles, 60 table styles, all CF rule kinds including data bars, colour scales and icon sets. Gaps: font weights beyond regular/bold (#168), system fonts list (#4), themes |
| Sort, filter, tables, validation, outline | 8 | ~82% | ~70% | 10–16 | Multi-level sort, AutoFilter, Advanced Filter, tables with totals, validation, outline, subtotals, consolidate. Bugs: subtotal header (#131), validation edits (#129), table style panic caught (#130); no slicers on tables |
@ -277,7 +277,7 @@ The inventory carried over from the 2026-10-07 ROADMAP.md, updated for what land
- Engine: A1/R1C1 formula parser with reference adjustment, dependency-graph recalculation with
dynamic arrays (spill + `#SPILL!`), cycle detection, LET/LAMBDA/MAP/REDUCE/SCAN/BYROW/BYCOL/
MAKEARRAY, structured table references, defined names, INDIRECT/OFFSET/INDEX references,
501 worksheet functions (478 at M0) (math, statistics and distributions, text and regex, lookup incl.
502 worksheet functions (478 at M0) (math, statistics and distributions, text and regex, lookup incl.
XLOOKUP/FILTER/SORT/UNIQUE/VSTACK, dates, financial incl. bonds, engineering incl. complex
numbers and Bessel, database, information).
- Number formats: Excel's full format-code language (sections, conditions, colours, dates and
@ -332,6 +332,7 @@ The inventory carried over from the 2026-10-07 ROADMAP.md, updated for what land
| Date | Change | Summary |
|---|---|---|
| 2026-10-11 | minor | Worksheet functions 502 / 523 (96.0%; 493 working): BAHTTEXT |
| 2026-10-10 | minor | Readiness-by-audience table: hours to ~95% for each of the three numbers (full 650–1,050, mainstream 200–310, essentials 60–100). Full number confirmed as the additive weighted sum over the written dimension weights (no change) |
| 2026-10-10 | minor | Added Mainstream practitioner (~50%) and Essentials user (~63%) with written weights and discounts, and user-evidence counts; re-checked the full number after the 10-10 merges (charts 38→30, localization 5→10; still 51.6, ~50%) |
| 2026-10-10 | minor | Stage checked against the new alpha gate (six core workflows, all pass): stays alpha |