{
  "category": "Text functions",
  "display_name": "TEXTAFTER",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.TEXTAFTER",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20527"
      ],
      "larger_numeric": 0,
      "last_bit": 0,
      "matched": 11,
      "other_mismatch": 0,
      "refused": 0,
      "rows": 11,
      "unread": 0,
      "worst_ulp": 0
    },
    "detail": "Recorded: 11 in the answer bank and 11 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 22 recorded answers",
    "workbook_corpus": {
      "cells": 11,
      "matched": 11
    }
  },
  "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/text_format.rs#L933-L933"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/text_format::read_value",
        "catalogue/text_format::value",
        "catalogue/text_format::profile",
        "catalogue/text_format::rendered",
        "catalogue/text_format::text",
        "catalogue/text_format::given",
        "catalogue/text_format::binary_flag",
        "catalogue/text_format::delimiters",
        "catalogue/text_format::text_delim",
        "decimal::low32",
        "decimal::Natural::zero",
        "decimal::Natural::from_u64",
        "decimal::Natural::pow10",
        "decimal::Natural::normalize",
        "decimal::Natural::is_zero",
        "decimal::Natural::mul_add_small",
        "decimal::Natural::times_pow10",
        "decimal::Natural::times_pow5",
        "decimal::Natural::times_pow2",
        "decimal::ExactDecimal::read",
        "decimal::ExactDecimal::binary",
        "format/datetime::has_invalid_exponent",
        "format/datetime::looks_like_datetime_format",
        "format/datetime::without_subseconds",
        "format/datetime::render_with_datetime_tokens",
        "format/datetime::tokenize_datetime_format",
        "format/datetime::elapsed_token_at",
        "format/datetime::classify_minute_tokens",
        "format/datetime::token_kind",
        "format/datetime::is_time_neighbor",
        "format/datetime::push_literal",
        "format/datetime::render_datetime_literal",
        "format/datetime::format_elapsed",
        "format/datetime::TimeParts::from_serial",
        "format::measured_host",
        "format::currency_literal",
        "format::digits",
        "format::fifteen",
        "format::split",
        "format::grouped",
        "format::general",
        "format::significant",
        "format::sections",
        "format::bracket",
        "format::is_condition",
        "format::is_elapsed",
        "format::condition_holds",
        "format::condition_of",
        "format::strip_tokens",
        "format::choose",
        "format::items",
        "format::numeric",
        "format::literal_text",
        "format::integer_part",
        "format::fraction_part",
        "format::scientific",
        "format::fraction_code",
        "format::FractionCode::render",
        "format::mixed_fraction_under_space_grouping",
        "format::convergent",
        "format::text_declared_date_locale",
        "format::text",
        "format::text_of_text",
        "format/names::month_name",
        "format/names::weekday_name",
        "format/names::locale_names",
        "locale::LocaleId::from_bcp47_language_tag",
        "locale::LocaleId::from_excel_lcid",
        "locale::short_date_order",
        "locale::short_date_pattern",
        "locale::currency_placement",
        "locale::currency_spacing",
        "locale::currency_negative_pattern",
        "locale::format_profile",
        "locale::days_from_civil",
        "locale::civil_from_days",
        "locale::ymd_from_excel_serial",
        "number_text::decimal",
        "number_text::first_precision",
        "number_text::near_tie",
        "number_text::first_rounding",
        "number_text::rounded",
        "number_text::increment",
        "number_text::ascii",
        "ported/date_kernels::days_from_civil",
        "ported/date_kernels::civil_from_days",
        "ported/date_kernels::serial_unbounded_1900",
        "ported/date_kernels::ymd_1900",
        "ported/date_kernels::is_leap",
        "ported/date_kernels::days_in_month",
        "ported/date_kernels::whole_serial",
        "ported/date_kernels::whole",
        "ported/date_kernels::weekday_sunday_one_based",
        "ported/date_kernels::remap_weekday",
        "ported/date_kernels::weekday_of",
        "ported/date_kernels::weekday",
        "ported/text_kernels::text",
        "ported/text_kernels::text_from_str",
        "ported/text_kernels::date_integer_floor",
        "ported/text_kernels::push_singleton_or_original",
        "ported/text_kernels::push_upper",
        "ported/text_kernels::upper",
        "ported/text_more::fold_ascii_case",
        "ported/text_more::units_match",
        "ported/text_more::delimited",
        "value_text::measured_host_reader",
        "value_text::measured_space",
        "value_text::read",
        "value_text::number",
        "value_text::decimal",
        "value_text::fraction",
        "value_text::tokens",
        "value_text::month_named",
        "value_text::time_at",
        "value_text::full_year",
        "value_text::valid_day",
        "value_text::this_year",
        "value_text::serial_1900",
        "value_text::date_of",
        "value_text::date_time"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/text_format.rs#L933-L933",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 22 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.TEXTAFTER.json",
  "name": "TEXTAFTER",
  "notes": [
    {
      "basis": "Three recorded readings, with blank-cell and logical companions in the same run.",
      "documentation": null,
      "evidence": [
        {
          "commit": "080a6f2f7b65e750400837841f9db3d3822d8ec3",
          "locator": "empty_text_delimiter_errors_match_the_recorded_excel_values",
          "note": "recorded readings pinned",
          "path": "crates/calc-func/tests/f2_text.rs",
          "repository": "DnaCalc"
        }
      ],
      "functions": [
        "FUNC.TEXTAFTER",
        "FUNC.TEXTBEFORE",
        "FUNC.TEXTSPLIT"
      ],
      "inferred": null,
      "kind": "quirk",
      "note_id": "FN-TEXTSPLIT-001",
      "open": [],
      "recorded_on": "2026-11-04",
      "repros": [
        {
          "call": "=TEXTBEFORE(\"\",\"-\")",
          "correct": null,
          "excel": {
            "bits": null,
            "display": "#N/A",
            "kind": "error"
          },
          "input_route": "formula-literal",
          "inputs": [],
          "recorded_in": "Excel build not recorded in this run; bulk captures of the same date (2026-09-29) record Excel 16.0 build 20430, Windows 64-bit, workbook compatibility 2",
          "source": {
            "commit": "4d5320dfdc385354469b4d506153357bb932ab08",
            "locator": "w111typed-00274-textbefore-arg1-empty-text",
            "note": null,
            "path": "runs/w111-broad-typed-20260929-002/outcomes/excel.jsonl.gz",
            "repository": "CalcFunc-Evidence"
          }
        },
        {
          "call": "=TEXTAFTER(\"\",\"-\")",
          "correct": null,
          "excel": {
            "bits": null,
            "display": "#N/A",
            "kind": "error"
          },
          "input_route": "formula-literal",
          "inputs": [],
          "recorded_in": "Excel build not recorded in this run; bulk captures of the same date (2026-09-29) record Excel 16.0 build 20430, Windows 64-bit, workbook compatibility 2",
          "source": {
            "commit": "4d5320dfdc385354469b4d506153357bb932ab08",
            "locator": "w111typed-00266-textafter-arg1-empty-text",
            "note": null,
            "path": "runs/w111-broad-typed-20260929-002/outcomes/excel.jsonl.gz",
            "repository": "CalcFunc-Evidence"
          }
        },
        {
          "call": "=TEXTSPLIT(\"\",\",\")",
          "correct": null,
          "excel": {
            "bits": null,
            "display": "#VALUE!",
            "kind": "error"
          },
          "input_route": "formula-literal",
          "inputs": [],
          "recorded_in": "Excel build not recorded in this run; bulk captures of the same date (2026-09-29) record Excel 16.0 build 20430, Windows 64-bit, workbook compatibility 2",
          "source": {
            "commit": "4d5320dfdc385354469b4d506153357bb932ab08",
            "locator": "w111typed-00282-textsplit-arg1-empty-text",
            "note": null,
            "path": "runs/w111-broad-typed-20260929-002/outcomes/excel.jsonl.gz",
            "repository": "CalcFunc-Evidence"
          }
        }
      ],
      "schema": "efh.function-note/v1",
      "statement": "An empty string as text gives #N/A (delimiter not found) from TEXTBEFORE and TEXTAFTER, but #VALUE! from TEXTSPLIT.",
      "status": "measured",
      "title": "Empty text gives #N/A from TEXTBEFORE and TEXTAFTER, #VALUE! from TEXTSPLIT"
    }
  ],
  "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- [`TEXTBEFORE`](FUNC.TEXTBEFORE.md) — the mirror function, same arguments, opposite side of the\n  cut. The two share one implementation module upstream, which is why their behavioural questions\n  are usually settled together.\n- [`TEXTSPLIT`](FUNC.TEXTSPLIT.md) — the same delimiter idea taken to its conclusion: instead of\n  selecting one occurrence, split at all of them and return the pieces as an array.\n- `MID`, `LEFT`, `RIGHT` — positional slicing. Reach for these when you know the character index;\n  reach for `TEXTAFTER` when you know the marker.\n- `FIND` / `SEARCH` combined with `MID` is the pre-2022 idiom this function replaces. `FIND` is\n  case-sensitive and `SEARCH` is not, which is the same distinction `match_mode` now expresses in\n  one argument.\n- Nothing is superseded by `TEXTAFTER`; the older idiom remains fully supported.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n\n- **Occurrence enumeration for multi-character delimiters needs an overlap policy.** Scanning\n  `\"aaa\"` for `\"aa\"` yields two occurrences if you advance by one character and one occurrence if\n  you advance past the match. The documentation does not state which Excel does. Pick one, write\n  it down, and treat it as a probe target rather than an assumption.\n- **Negative `instance_num` should be resolved against the same occurrence list**, not by\n  re-scanning right-to-left. A right-to-left scan can disagree with a left-to-right scan for\n  overlapping delimiters, and the difference is exactly the overlap policy above.\n- **Case-insensitive matching is not one rule.** The upstream slice contract records only ASCII\n  case folding as observed; Unicode case folding, and locale-sensitive folding in particular, are\n  outside what that evidence covers. An implementation that folds with a full Unicode table may\n  find more occurrences than Excel does.\n- **Indices are UTF-16 code units** in the model this Handbook uses. Delimiters and text\n  containing astral characters make the distinction between code units and Unicode scalars\n  observable; see [the value universe](../model/01-value-universe.md).\n- **Lift only the positions you have evidence for.** Lifting the delimiter position because it\n  seems symmetric is precisely the kind of invented behaviour this Handbook is trying not to ship.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nThe return kind is `Text` — a scalar string, including possibly the empty string. This function\nis not itself array-producing; it is a scalar kernel that the engine lifts. The lifting rules,\nincluding how a per-element failure stays element-local rather than collapsing the whole result,\nare in [coercion and lifting](../model/02-coercion-and-lifting.md); the spill mechanics are the\nhost-side adaptation step described in [the call pipeline](../model/03-call-pipeline.md).\n\nOther boundaries worth naming explicitly:\n\n- **Numbers and logicals as `text` or `delimiter`.** They convert to text by the ordinary rules in\n  [coercion and lifting](../model/02-coercion-and-lifting.md); `TRUE` becomes the string `TRUE`.\n  Nothing here is special-cased.\n- **An empty referenced cell** delivers `Empty`, which is distinct from an omitted argument. See\n  [the value universe](../model/01-value-universe.md) for why the two are kept apart.\n- **Error inputs propagate.** Coercion never discards a worksheet error.\n- **Empty result versus no result.** These are different outcomes and should not be conflated by a\n  caller: an empty string means the cut succeeded and nothing followed it; `#N/A` (or\n  `if_not_found`) means no such occurrence existed.\n\n\n\n### Errors\n\n\nMicrosoft's page documents the following (see Sources):\n\n| Error | Documented condition |\n|---|---|\n| `#N/A` | The delimiter is not found, or `instance_num` exceeds the number of occurrences. |\n| `#VALUE!` | `instance_num` is `0`, or its magnitude exceeds the length of the text. |\n\n`#N/A` is suppressible by supplying `if_not_found`; `#VALUE!` is not. Errors arriving in any\nargument propagate ahead of all of this. Empty `text` gives `#N/A`, not `#VALUE!`, even though the\ndefault `instance_num` of 1 exceeds its length of 0 (FN-TEXTSPLIT-001).\n\n\n",
    "sources": "- Microsoft Support, TEXTAFTER function —\n  <https://support.microsoft.com/en-us/office/textafter-function-c8db2546-5b51-416a-9690-c7e6722e90b4>\n  (retrieved for this page; source of the signature, argument meanings, and the documented error\n  table).\n- Handbook `content/model/01-value-universe.md`, `02-coercion-and-lifting.md`,\n  `03-call-pipeline.md` — the shared value, coercion, lifting, and publication model this page\n  refers to rather than restating.\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`TEXTAFTER` slices a string at one chosen occurrence of a delimiter and returns everything to the\nright of it.\n\nState it as an indexing problem, because that is what it is. Let `t` be the text and `d` the\ndelimiter. Under the chosen match mode, enumerate the occurrences of `d` inside `t` in\nleft-to-right order as index pairs `(start_1, end_1), (start_2, end_2), …, (start_k, end_k)`, where\n`end_i = start_i + len(d)`. The `instance_num` argument selects one of them: a positive `n` selects\nthe `n`-th pair counted from the left, a negative `n` selects the `|n|`-th counted from the right.\nThe result is the substring of `t` from the selected `end_i` to the end of `t`.\n\nThree consequences follow directly and are worth stating rather than discovering:\n\n1. **The delimiter itself is not in the result.** The cut is at `end_i`, not `start_i`. That is the\n   entire difference between this function and [`TEXTBEFORE`](FUNC.TEXTBEFORE.md), which cuts at\n   `start_i` and keeps the left side.\n2. **A delimiter at the very end of `t` yields the empty string**, not a missing value. `end_k`\n   equals `len(t)` and the substring is empty. Empty text is a perfectly good result here.\n3. **Selection is by occurrence, not by position.** There is no \"find the delimiter nearest\n   character 12\" mode. If you want positional slicing, you want `MID`/`LEFT`/`RIGHT`, not this\n   family.\n\n\n### Arguments\n\n\n`TEXTAFTER(text, delimiter, [instance_num], [match_mode], [match_end], [if_not_found])`\n\n| Argument | Required | Meaning (as documented by Microsoft) |\n|---|---|---|\n| `text` | yes | The string being searched. Wildcards are not accepted; the delimiter is matched literally. |\n| `delimiter` | yes | The string that marks the cut point. May be more than one character. |\n| `instance_num` | no | Which occurrence to cut at. Defaults to `1`. Negative counts from the end. `0` is documented as an error. |\n| `match_mode` | no | `0` (default) case-sensitive, `1` case-insensitive. |\n| `match_end` | no | `0` (default) plain matching; `1` treats the end of the text as a delimiter. |\n| `if_not_found` | no | The value returned instead of `#N/A` when the requested occurrence does not exist. |\n\nThe argument position readers misjudge most often is the third. `instance_num` is an *occurrence\nindex*, and it is signed; it is not a character position and not a count of characters to skip.\n`TEXTAFTER(\"a-b-c\", \"-\", 2)` is `\"c\"`, and `TEXTAFTER(\"a-b-c\", \"-\", -1)` is also `\"c\"` — the same\nanswer arrived at from opposite ends, which is why writing `-1` is the robust way to say \"after the\nlast one\".\n\nThe sixth argument is the one people forget exists. `if_not_found` removes the need to wrap the\ncall in `IFERROR`, and unlike `IFERROR` it only catches the no-match case: an argument-domain error\nstill surfaces.\n\n\n"
  },
  "signature": {
    "display": "TEXTAFTER(text, delimiter, [instance_num], [match_mode], [match_end], [if_not_found])",
    "parameters": [
      {
        "description": null,
        "name": "text",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "delimiter",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "instance_num",
        "optional": true,
        "repeats": false
      },
      {
        "description": null,
        "name": "match_mode",
        "optional": true,
        "repeats": false
      },
      {
        "description": null,
        "name": "match_end",
        "optional": true,
        "repeats": false
      },
      {
        "description": null,
        "name": "if_not_found",
        "optional": true,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 6,
        "min": 2
      },
      "category": "Text functions",
      "classification": {
        "arg_preparation_profile": "ValuesOnlyPreAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "TextToText",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "The part of a text after a delimiter",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns text that occurs after given character or string",
        "microsoft_url": "https://support.microsoft.com/en-us/office/textafter-function-c8db2546-5b51-416a-9690-c7e6722e90b4"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "TEXTAFTER"
        },
        {
          "locale": "bg-BG",
          "name": "TEXTAFTER"
        },
        {
          "locale": "cs-CZ",
          "name": "TEXTZA"
        },
        {
          "locale": "da-DK",
          "name": "TEKSTEFTER"
        },
        {
          "locale": "de-DE",
          "name": "TEXTAFTER"
        },
        {
          "locale": "el-GR",
          "name": "TEXTAFTER"
        },
        {
          "locale": "en-AU",
          "name": "TEXTAFTER"
        },
        {
          "locale": "en-GB",
          "name": "TEXTAFTER"
        },
        {
          "locale": "en-US",
          "name": "TEXTAFTER"
        },
        {
          "locale": "es-ES",
          "name": "TEXTODESPUES"
        },
        {
          "locale": "et-EE",
          "name": "TEXTAFTER"
        },
        {
          "locale": "fi-FI",
          "name": "TEKSTI.JÄLKEEN"
        },
        {
          "locale": "fr-FR",
          "name": "TEXTE.APRES*"
        },
        {
          "locale": "he-IL",
          "name": "TEXTAFTER"
        },
        {
          "locale": "hr-HR",
          "name": "TEXTAFTER"
        },
        {
          "locale": "hu-HU",
          "name": "SZÖVEGUTÁNA"
        },
        {
          "locale": "id-ID",
          "name": "TEXTAFTER"
        },
        {
          "locale": "it-IT",
          "name": "TEXTAFTER"
        },
        {
          "locale": "ja-JP",
          "name": "TEXTAFTER"
        },
        {
          "locale": "ko-KR",
          "name": "TEXTAFTER"
        },
        {
          "locale": "lt-LT",
          "name": "TEXTAFTER"
        },
        {
          "locale": "lv-LV",
          "name": "TEXTAFTER"
        },
        {
          "locale": "nb-NO",
          "name": "TEXTAFTER"
        },
        {
          "locale": "nl-NL",
          "name": "TEKST.NA"
        },
        {
          "locale": "pl-PL",
          "name": "TEKST.PO"
        },
        {
          "locale": "pt-BR",
          "name": "TEXTAFTER"
        },
        {
          "locale": "pt-PT",
          "name": "TEXTODEPOIS"
        },
        {
          "locale": "ro-RO",
          "name": "TEXTAFTER"
        },
        {
          "locale": "ru-RU",
          "name": "ТЕКСТПОСЛЕ"
        },
        {
          "locale": "sk-SK",
          "name": "TEXTAFTER"
        },
        {
          "locale": "sl-SI",
          "name": "TEXTAFTER"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "TEXTAFTER"
        },
        {
          "locale": "sv-SE",
          "name": "TEXTEFTER"
        },
        {
          "locale": "th-TH",
          "name": "TEXTAFTER"
        },
        {
          "locale": "tr-TR",
          "name": "SONRAKİMETİN"
        },
        {
          "locale": "uk-UA",
          "name": "TEXTAFTER"
        },
        {
          "locale": "vi-VN",
          "name": "TEXTAFTER"
        },
        {
          "locale": "zh-CN",
          "name": "TEXTAFTER"
        },
        {
          "locale": "zh-HK",
          "name": "TEXTAFTER"
        },
        {
          "locale": "zh-TW",
          "name": "TEXTAFTER"
        }
      ],
      "signature": {
        "display": "TEXTAFTER(text, delimiter, [instance_num], [match_mode], [match_end], [if_not_found])",
        "parameters": [
          {
            "description": null,
            "name": "text",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "delimiter",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "instance_num",
            "optional": true,
            "repeats": false
          },
          {
            "description": null,
            "name": "match_mode",
            "optional": true,
            "repeats": false
          },
          {
            "description": null,
            "name": "match_end",
            "optional": true,
            "repeats": false
          },
          {
            "description": null,
            "name": "if_not_found",
            "optional": true,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "TEXTAFTER",
      "version_marker": null,
      "xlcall": null
    },
    "microsoft": "https://support.microsoft.com/en-us/office/textafter-function-c8db2546-5b51-416a-9690-c7e6722e90b4"
  },
  "try_it": {
    "formula": "=TEXTAFTER(\"name@example.com\",\"@\")"
  },
  "url": "https://handbook.dnacalc.com/functions/TEXTAFTER.html",
  "variants": [],
  "versions": []
}