Logical functions

SWITCH

Known larger differences on 4 of 1,395 recorded answers

Of 1,395 recorded answers (1,227 in the answer bank and 168 workbook cells), 4 do not match: 2 differ by more than 16 ULP, 2 are refused. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
ArabicSWITCH
BulgarianSWITCH
CzechSWITCH
DanishSKIFT
GermanSWITCH
GreekSWITCH
English (Australia)SWITCH
English (United Kingdom)SWITCH
English (United States)SWITCH
SpanishCAMBIAR
EstonianSWITCH
FinnishMUUTA
FrenchSI.MULTIPLE
HebrewSWITCH
CroatianSWITCH
HungarianÁTVÁLT
IndonesianSWITCH
ItalianSWITCH
JapaneseSWITCH
KoreanSWITCH
LithuanianSWITCH
LatvianSWITCH
NorwegianSWITCH
DutchSCHAKELEN
PolishPRZEŁĄCZ
Portuguese (Brazil)SWITCH
Portuguese (Portugal)PARÂMETRO
RomanianSWITCH
RussianПЕРЕКЛЮЧ
SlovakSWITCH
SlovenianSWITCH
Serbian (Latin)SWITCH
SwedishVÄXLA
ThaiSWITCH
TurkishİLKEŞLEŞEN
UkrainianSWITCH
VietnameseSWITCH
Chinese (Simplified)SWITCH
Chinese (Hong Kong)SWITCH
Chinese (Traditional)SWITCH

Names from Microsoft's support site.

What it does

SWITCH(expression, value1, result1, ...)

SWITCH evaluates one expression once and compares it, in order, against a list of candidate values, returning the result paired with the first candidate that matches. If nothing matches, it returns an optional trailing default — and if there is no default, #N/A.

The rule:

  1. Evaluate expression once.
  2. Walk the (valueN, resultN) pairs left to right. For each, test expression = valueN under the function's equality predicate.
  3. On the first match, return resultN and stop.
  4. If no candidate matched, return default if one was supplied, otherwise #N/A.

Two things make SWITCH more interesting than "IFS with an implicit =".

Parity decides the default. There is no keyword marking the default argument. SWITCH counts: the expression takes one slot, and candidate/result pairs take two each, so an even total argument count means the last argument is unpaired and is therefore the default. An odd total means every candidate has a result and there is no default. Nothing in the formula text says "default" — the argument count says it. Miscount the pairs and a value you meant as a candidate becomes the default, silently.

If you take one thing from this page: SWITCH is a comparison function wearing dispatch clothing, and its comparison is the same tolerant-looking one the = operator and COUNTIF use, not the exact one lookup functions use.

Arguments

SWITCH(expression, value1, result1, [value2, result2], ..., [default])

  • expression — required. Evaluated once. Any value kind.
  • default — optional, and identified only by argument parity as described above.

The commonly misunderstood positions are the last two: readers assume a named default and assume that a numeric candidate matches a numeric-looking text expression. It does not — the reference engine matches text against text and numbers against numbers, and does not cross the kind boundary.

Try it

Input cells (optional)

Example: {"B2": 3, "B3": 4}. A1 holds the formula. Other cells need values before a formula can read them.

Enter a formula, then calculate.

Runs locally in your browser with OneCalc. Its answer may differ from Excel. Use English function names and commas between arguments.

Quirks

Result and edge cases

Returns whatever kind the selected result carries.

  • No match, no default. #N/A.
  • No match, default present. The default, verbatim.
  • Numeric matching. Through the 15-significant-digit truncation predicate described above, not raw IEEE equality.
  • Kind mismatch. A number and numeric text do not match each other.
  • Error as the expression. Propagates.
  • Selected result is an error. Returned verbatim; SWITCH selects, it does not inspect.
  • Arrays. The call model records SWITCH under ByIndexScalarArrayLift over positions 0, 1 and 3 — the expression, the first candidate, and the first result (chapter 03). As with IFS, that list is irreducible structure rather than a derivable rule. Once a scalar comparison has selected a result, later arrays do not lift the call: SWITCH(2,2,1,{1,2},3) returns one 1 (FN-IFS-001).

IFS and SWITCH pass on the selected value whole, and later arrays do not lift the call

Once a scalar test selects a result, array arguments after it have no effect on the shape: IFS(TRUE,1,{FALSE,TRUE},{2,3}) and SWITCH(2,2,1,{1,2},3) each return one 1, not an array, and SWITCH("A","a",1,{"A","A"},2) returns 1 because the match ignores case. The selected value itself is passed on as it is. A selected reference stays a reference: ISBLANK(IFS(TRUE,Data!Z1)) is TRUE over an empty cell. A selected LAMBDA shows as #CALC! in the cell, IFS(TRUE,LAMBDA(xx,xx)), and a selected array of LAMBDAs as #CALC! in each cell. A test that is not TRUE or FALSE gives #VALUE! in the shape of its result: IFS("2",{"hit","hit"}) is {#VALUE!,#VALUE!}. A direct error as the SWITCH expression stays one error: SWITCH(#VALUE!,1,{1,2},0) is #VALUE!.

FormulaExcelMathematical value
=IFS(TRUE,1,{FALSE,TRUE},{2,3})
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

1
0x3ff0000000000000
—
=SWITCH(2,2,1,{1,2},3)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

1
0x3ff0000000000000
—
=SWITCH("A","a",1,{"A","A"},2)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

1
0x3ff0000000000000
—
=ISBLANK(IFS(TRUE,Data!Z1))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Number supplied through a cell.

Data!Z1: (empty cell)

TRUE—
=ISBLANK(SWITCH(1,1,Data!Z1))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Number supplied through a cell.

Data!Z1: (empty cell)

TRUE—
=IFS(TRUE,LAMBDA(xx,xx))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#CALC!—
=SWITCH(1,1,LAMBDA(xx,xx))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#CALC!—
=IFS(TRUE,HSTACK(LAMBDA(xx,xx),LAMBDA(xx,xx)))
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

{#CALC!,#CALC!}—
=IFS("2",{"hit","hit"})
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

{#VALUE!,#VALUE!}—
=SWITCH(#VALUE!,1,{1,2},0)
Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
Inputs and reference value

Typed formula.

#VALUE!—

Inputs, build details and evidence

How to implement

Notes for implementers

  1. Compute the default by parity before scanning, and treat "is there a default" as a structural fact of the call, not something discovered mid-loop.
  2. Do not evaluate candidates or results past the first match. Lazy evaluation is observable whenever a later argument would error.
  3. Choose the equality predicate deliberately and document it. If you share a comparison helper with =, COUNTIF, and SUMIF, SWITCH inherits their truncation semantics. If you share one with MATCH, it inherits raw IEEE equality. Both are defensible; silently inheriting whichever helper was nearest is not.

Rust code

Show the CalcFunc source of this function

Quoted from the public repository DnaCalc/DnaCalc, crates calc-func and calc-fml, at commit 9e1884369a67. Comments are the source's own. A kernel shared with other functions appears once, on its module page.

SWITCH · 13 lines · calc-func/src/catalogue/logical_more.rs on GitHub
CatalogueEntry {
    id: SWITCH,
    spelling: "SWITCH",
    notation: Notation::Call,
    arity: CallableArityShape::range(3, 254),
    parameters: &[
        Parameter::value("expression"),
        Parameter::value("value1"),
        Parameter::value("result1"),
    ],
    demand: ArgumentDemand::Eager,
    kernel: Kernel::Eager(switch),
}
switch · 11 lines · calc-func/src/catalogue/logical_more.rs on GitHub
fn switch(
    arguments: &[CalcValue],
    services: &mut EvalServices<'_>,
) -> Result<CalcValue, FunctionFault> {
    selection(SWITCH, arguments, services, |s, a| {
        match switch_index(s, a)? {
            Some(index) => Ok(selected(&a[index])),
            None => fail(WorksheetErrorCode::NA),
        }
    })
}
switch_index · 18 lines · calc-func/src/catalogue/logical_more.rs on GitHub
/// The selected SWITCH argument, or no match without a default. Both shape admission
/// and the kernel use this one selector; comparisons read no host or random services.
fn switch_index(site: &Site<'_>, arguments: &[CalcValue]) -> Step<Option<usize>> {
    if let CoreRef::Error(code) = arguments[0].core_ref() {
        return fail(code);
    }
    let has_default = arguments.len().is_multiple_of(2);
    let cases = arguments.len() - usize::from(has_default);
    let mut at = 1;
    while at + 1 < cases {
        let pair = [arguments[0].clone(), arguments[at].clone()];
        if order(site, &pair, Want::Equality)? == Ordering::Equal {
            return Ok(Some(at + 1));
        }
        at += 2;
    }
    Ok(has_default.then_some(arguments.len() - 1))
}

Kernels shared with other functions

Argument and result plumbing

No implementation has been published with a Handbook test suite for this function.

Version differences

The recorded environments below distinguish a reading from a same-input comparison. Counts describe captured inputs in each environment; overlapping captures and comparisons are not totals of unique worksheet calls.

Excel 16.0 buildPlatform and CPUCaptured inputs
20430Windows, 64-bit, CPU not recorded4,151

The record contains no same-input comparison between these environments. Reading different inputs on different builds does not establish either a version change or cross-build agreement.

Recorded environments and comparison details.

Excel 16.0.20527.20088

Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA

=SWITCH(2,2,1,{1,2},3) returned 1 (0x3ff0000000000000). =SWITCH("A","a",1,{"A","A"},2) returned 1 (0x3ff0000000000000). 3 further recorded controls are attached. Inputs were supplied through cells using Value2, formula literals. These are controls from this environment, not a same-input comparison with another build.

Observed formulas and results
  • =SWITCH(2,2,1,{1,2},3) → 1
    0x3ff0000000000000 (formula-literal)
  • =SWITCH("A","a",1,{"A","A"},2) → 1
    0x3ff0000000000000 (formula-literal)
  • =ISBLANK(SWITCH(1,1,Data!Z1)) → TRUE (cell-value2)
  • =SWITCH(1,1,LAMBDA(xx,xx)) → #CALC! (formula-literal)
  • =SWITCH(#VALUE!,1,{1,2},0) → #VALUE! (formula-literal)

Excel 16.0 build 20430

Windows, 64-bit, CPU not recorded

4,151 captured inputs are indexed for this environment. Capture dates: 2026-09-29 to 2026-09-29. This is a reading count, not a comparison with another build.

Alternatives

Relationships

  • IFS is the sibling for independent conditions. Use IFS when the tests differ in kind; use SWITCH when they are all equality against one expression. Both return #N/A on no match, but only SWITCH has a real default slot.
  • IF nested is what both replace.
  • CHOOSE dispatches on a 1-based index rather than on a value match.
  • LOOKUP / XLOOKUP / MATCH are the table-driven alternatives, and they are on the other side of the equality split recorded in EV-STRUCT-0001: MATCH and XMATCH compare with raw IEEE equality. Replacing a SWITCH with an XLOOKUP over a two-column table therefore changes the comparison semantics, not just the notation. That is a genuinely surprising migration hazard and the most practical consequence of this page.
  • SWITCH arrived in Excel 2016. It supersedes nothing and is not a Compatibility-category entry.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents