{
  "category": "Lookup and reference functions",
  "display_name": "INDIRECT",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.INDIRECT",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 174 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 174 recorded answers",
    "workbook_corpus": {
      "cells": 176,
      "matched": 174,
      "pending": 2
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/reference_text.rs#L25-L33",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/reference_text.rs#L36-L42",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/reference_text.rs#L44-L67"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/reference_text.rs#L25-L33",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 174 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.INDIRECT.json",
  "name": "INDIRECT",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n\n- **`ADDRESS`** is the natural producer of the text `INDIRECT` consumes. The pair\n  `INDIRECT(ADDRESS(r, c))` is the textbook computed-reference idiom — and, in almost every\n  case, `INDEX(range, r, c)` does the same job without volatility, without the text round trip,\n  and while remaining visible to the dependency graph. That comparison is the practical bottom\n  line of this page.\n- **`OFFSET`** computes a reference by displacement rather than by text. It is also volatile,\n  but it *is* visible to the dependency graph, so it sits between `INDEX` and `INDIRECT` on the\n  cost scale.\n- **`INDEX`'s reference form** is the non-volatile alternative for nearly every computed\n  reference that does not need a *name* to come from data. See the `INDEX` page.\n- **Defined names and `LET`** cover cases where the \"dynamic\" part is really parameterization\n  rather than genuinely data-driven addressing.\n- **`CHOOSE`** selects among ranges written in the formula. When the candidate ranges are known\n  at authoring time — the usual case for a drop-down-driven lookup — `CHOOSE` replaces\n  `INDIRECT` and keeps the references visible.\n- **`FORMULATEXT`** goes the other way, exposing formula text as data.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n\n- **Parsing is the function.** `INDIRECT` is a reference parser wearing a function's clothes,\n  and its accepted grammar is co-extensive with the host's reference syntax — including\n  quoting rules, sheet-span syntax, structured-reference syntax, and the R1C1 alternative.\n  Implementing it means either reusing the formula parser's reference production or accepting\n  that the two will drift.\n- **The A1/R1C1 flag changes the grammar, not the formatting.** Two parsers, or one\n  parameterized parser; not a post-processing step.\n- **Locale.** Reference syntax is locale-sensitive in places — the sheet separator, list\n  separators inside union expressions, and the spelling of R1C1 in localized builds. Text built\n  in one locale may not parse in another, which makes `INDIRECT` formulas a portability hazard\n  in a way that literal references are not.\n- **Caller context is required.** An unqualified address resolves against the calling sheet, so\n  the function cannot be evaluated without knowing where it was called from. This is why the\n  reference implementation classifies it `CallerContext` and why a host-free harness cannot\n  exercise it at all.\n- **Volatility must be declared, not inferred.** An engine that treats `INDIRECT` as pure will\n  cache a result that is correct only until the workbook changes shape.\n\n\n",
    "quirks": "\n### Volatility and the dependency graph\n\n\nThis section exists because these are the properties that decide whether you should use the\nfunction at all.\n\n**Invisibility to the dependency graph.** The engine builds its calculation order from\nreferences it can see in formulas. It cannot see through text. Two consequences:\n\n1. **Restructuring does not update the text.** Insert a row above `A10` and every literal\n   reference to `A10` becomes `A11`; `INDIRECT(\"A10\")` still says `A10` and now points at\n   different data. Nothing errors. This is the failure mode that makes `INDIRECT` genuinely\n   dangerous in maintained workbooks — it is silent, and it is discovered by reconciliation\n   rather than by a `#REF!`.\n2. **Calculation order cannot be derived.** Because the engine does not know in advance what an\n   `INDIRECT` call will read, it cannot order that call after its true precedents by inspection.\n   Volatility is, in part, how the engine copes: recalculating always is a blunt substitute for\n   knowing when to recalculate.\n\n**The upside, stated fairly.** `INDIRECT` does one thing nothing else does: it makes the\n*target* of a reference into data. Sheet names in a column, a lookup table chosen by a\ndrop-down, a range whose extent is a user setting — these are genuinely dynamic and `INDIRECT`\nexpresses them directly. It is also the only way to write a reference that survives row\ndeletion deliberately, which is occasionally exactly what you want. The advice is not \"never\";\nit is \"know what you are buying\".\n\n\n\n### Result and edge cases\n\n\nReturn kind: `Reference`. Because it is a reference and not a value, `INDIRECT` composes with\nrange-consuming functions — `SUM(INDIRECT(\"A1:A10\"))` scans a range — and with the range\noperator.\n\n- **Preparation.** Unlike most reference-producing functions, `INDIRECT` is prepared under\n  `ValuesOnlyPreAdapter`: it takes text and produces a reference, rather than receiving one. It\n  is a reference *source*, not a reference *inspector*.\n- **The text is trimmed and must be non-empty**, per the reference implementation's parse; an\n  empty or whitespace-only `ref_text` is an invalid reference.\n- **`a1` given as a blank or omitted slot.** Missing and Empty are distinct at the call boundary\n  ([value universe](../model/01-value-universe.md)), and the reference implementation treats\n  them differently here — omitted selects A1 style, an explicitly empty argument does not. That\n  is an implementation detail worth probing against Excel rather than assuming.\n- **Defined names, structured references, spill anchors** (`\"B1#\"`) — each is a distinct\n  reference shape and each is a separate question about what `INDIRECT`'s parser accepts.\n- **Three-dimensional references** (`\"Sheet1:Sheet3!A1\"`) — likewise.\n\n\n\n### Errors\n\n\nMicrosoft's page documents:\n\n- `#REF!` when `ref_text` is not a valid reference.\n- `#REF!` when `ref_text` refers to another workbook that is not open.\n\n`#REF!` is therefore the function's characteristic failure, and note what it does *not* cover:\ntext that parses fine but points at the wrong place because the sheet was restructured. That\ncase produces a number, not an error.\n\nAn error value supplied as `ref_text` propagates under the universal rule in\n[coercion and lifting](../model/02-coercion-and-lifting.md) — the reference implementation\nconverts it to a coercion failure carrying the incoming code, which is the same discipline.\n\nWhether a non-text `ref_text` (a number, a logical) is coerced to text and parsed, or rejected\noutright, is not established here.\n\n\n",
    "sources": "- Microsoft, INDIRECT function —\n  <https://support.microsoft.com/en-us/office/indirect-function-474b3a3a-8a26-4f44-b491-92b6306fa261>\n  (the `ref_text` and `a1` arguments, the A1/R1C1 selection, the `#REF!` conditions for invalid\n  references and closed external workbooks, and the note that external references are not\n  supported in Excel for the web).\n- Handbook `content/model/01-value-universe.md` (reference kind and shapes; Missing versus\n  Empty).\n- Handbook `content/model/02-coercion-and-lifting.md` (`eval_time_deref`; error propagation;\n  reference resolution as an explicit step).\n- Handbook `content/model/03-call-pipeline.md` (caller-aware functions; reference-producing\n  functions).\n- Handbook `data/functions/FUNC.INDIRECT.json` and `data/presence/FUNC.INDIRECT.json` (arity,\n  `VolatileContextual`, `CallerContext`, `HostSerialized`, implementing module).\n\n\n",
    "version-differences": "No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.",
    "what-it-does": "\n`INDIRECT(ref_text, [a1])` parses a string as a reference and returns that reference. It is the\ninverse of writing a reference literally: where `=A1` names a cell at authoring time,\n`=INDIRECT(\"A1\")` names it at evaluation time, from data.\n\nEverything interesting about this function follows from *when* the reference comes into\nexistence. A literal reference is part of the formula's structure: the engine can see it before\nevaluation, adjust it when rows are inserted, and use it to order the calculation chain. A\nreference built by `INDIRECT` exists only while the formula is being evaluated, and only as the\nvalue of an expression the engine cannot inspect in advance.\n\nThe text is resolved against the calling context: a bare `\"A1\"` means `A1` on the calling\nformula's sheet.\n\n\n\n### Arguments\n\n\n| Argument | Meaning |\n|---|---|\n| `ref_text` | Text naming a reference: a cell address, a range, a defined name, a structured reference, or a sheet- or workbook-qualified address. Required. |\n| `a1` | Logical selecting the notation of `ref_text`. Microsoft documents `TRUE` or omitted as A1 style, `FALSE` as R1C1 style. |\n\n`ref_text` is where every subtlety lives:\n\n- **It is a reference expression in text, not just an address.** A range (`\"A1:B10\"`), a defined\n  name (`\"SalesData\"`), and a sheet-qualified address (`\"Sheet2!A1\"`) are all admissible in\n  principle. Which grammar `INDIRECT` accepts in full is broader than the documentation\n  enumerates and is on the unchecked list below.\n- **Sheet names needing quotes need them in your text.** `\"'Q1 Sales'!A1\"` — the apostrophes are\n  part of the string you must build, not something `INDIRECT` adds.\n- **External workbook references require the other workbook to be open.** Microsoft documents\n  that if the source workbook is not open, `INDIRECT` returns `#REF!`. This is the single most\n  common production failure of the function: a formula that worked while the source was open\n  breaks silently once it is closed, and no amount of recalculation fixes it.\n- **Microsoft further documents that external references are not supported in Excel for the\n  web**, which makes `INDIRECT`-based cross-workbook formulas a platform-dependent construct.\n\nThe `a1` argument is the one people forget exists. `INDIRECT(\"R1C1\")` with `a1` omitted asks\nExcel to parse `R1C1` as an A1-style address — which is a *valid* A1-style address (column `R1C`\ndoes not exist, but the parse attempt is the point). Notation mismatches here produce `#REF!`\nrather than obviously wrong answers, which is at least loud.\n\n\n"
  },
  "signature": {
    "display": "INDIRECT(ref_text, [a1])",
    "parameters": [
      {
        "description": null,
        "name": "ref_text",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "a1",
        "optional": true,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 2,
        "min": 1
      },
      "category": "Lookup and reference functions",
      "classification": {
        "arg_preparation_profile": "ValuesOnlyPreAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "CallerContext",
        "host_interaction_class": "WorkbookState",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "CallerContext",
        "thread_safety_class": "HostSerialized",
        "volatility_class": "VolatileContextual"
      },
      "descriptions": {
        "long": null,
        "short": "The reference that a text names",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns a reference indicated by a text value",
        "microsoft_url": "https://support.microsoft.com/en-us/office/indirect-function-474b3a3a-8a26-4f44-b491-92b6306fa261"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "INDIRECT"
        },
        {
          "locale": "bg-BG",
          "name": "INDIRECT"
        },
        {
          "locale": "cs-CZ",
          "name": "NEPŘÍMÝ.ODKAZ"
        },
        {
          "locale": "da-DK",
          "name": "INDIREKTE"
        },
        {
          "locale": "de-DE",
          "name": "INDIREKT"
        },
        {
          "locale": "el-GR",
          "name": "INDIRECT"
        },
        {
          "locale": "en-AU",
          "name": "INDIRECT"
        },
        {
          "locale": "en-GB",
          "name": "INDIRECT"
        },
        {
          "locale": "en-US",
          "name": "INDIRECT"
        },
        {
          "locale": "es-ES",
          "name": "INDIRECT"
        },
        {
          "locale": "et-EE",
          "name": "INDIRECT"
        },
        {
          "locale": "fi-FI",
          "name": "EPÄSUORA"
        },
        {
          "locale": "fr-FR",
          "name": "INDIRECT"
        },
        {
          "locale": "he-IL",
          "name": "INDIRECT"
        },
        {
          "locale": "hr-HR",
          "name": "INDIRECT"
        },
        {
          "locale": "hu-HU",
          "name": "INDIREKT"
        },
        {
          "locale": "id-ID",
          "name": "INDIRECT"
        },
        {
          "locale": "it-IT",
          "name": "INDIRECT"
        },
        {
          "locale": "ja-JP",
          "name": "INDIRECT"
        },
        {
          "locale": "ko-KR",
          "name": "INDIRECT"
        },
        {
          "locale": "lt-LT",
          "name": "INDIRECT"
        },
        {
          "locale": "lv-LV",
          "name": "INDIRECT"
        },
        {
          "locale": "nb-NO",
          "name": "INDIREKTE"
        },
        {
          "locale": "nl-NL",
          "name": "INDIRECT"
        },
        {
          "locale": "pl-PL",
          "name": "ADR.POŚR"
        },
        {
          "locale": "pt-BR",
          "name": "INDIRETO"
        },
        {
          "locale": "pt-PT",
          "name": "INDIRETO"
        },
        {
          "locale": "ro-RO",
          "name": "INDIRECT"
        },
        {
          "locale": "ru-RU",
          "name": "ДВССЫЛ"
        },
        {
          "locale": "sk-SK",
          "name": "INDIRECT"
        },
        {
          "locale": "sl-SI",
          "name": "INDIRECT"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "INDIRECT"
        },
        {
          "locale": "sv-SE",
          "name": "INDIREKT"
        },
        {
          "locale": "th-TH",
          "name": "INDIRECT"
        },
        {
          "locale": "tr-TR",
          "name": "DOLAYLI işlevi"
        },
        {
          "locale": "uk-UA",
          "name": "INDIRECT"
        },
        {
          "locale": "vi-VN",
          "name": "INDIRECT"
        },
        {
          "locale": "zh-CN",
          "name": "INDIRECT"
        },
        {
          "locale": "zh-HK",
          "name": "INDIRECT"
        },
        {
          "locale": "zh-TW",
          "name": "INDIRECT"
        }
      ],
      "signature": {
        "display": "INDIRECT(ref_text, [a1])",
        "parameters": [
          {
            "description": null,
            "name": "ref_text",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "a1",
            "optional": true,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "INDIRECT",
      "version_marker": null,
      "xlcall": {
        "code": "148",
        "symbol": "xlfIndirect"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/indirect-function-474b3a3a-8a26-4f44-b491-92b6306fa261"
  },
  "try_it": {
    "formula": "=INDIRECT(\"B2\")",
    "inputs": {
      "B2": 1
    }
  },
  "url": "https://handbook.dnacalc.com/functions/INDIRECT.html",
  "variants": [],
  "versions": []
}