{
  "category": "Text functions",
  "display_name": "REPLACE",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.REPLACE",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 8 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 8 recorded answers",
    "workbook_corpus": {
      "cells": 8,
      "matched": 8
    }
  },
  "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_functions.rs#L305-L307"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/text_functions::count_surrogate_pairs",
        "catalogue/text_functions::start",
        "catalogue/text_functions::replace",
        "catalogue/text_functions::capped",
        "ported/text_kernels::text",
        "ported/text_kernels::unit_width",
        "ported/text_kernels::character_boundary",
        "ported/text_kernels::truncated",
        "ported/text_kernels::positive",
        "ported/text_kernels::nonnegative",
        "ported/text_kernels::replace"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/text_functions.rs#L305-L307",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 8 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.REPLACE.json",
  "name": "REPLACE",
  "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- **[SUBSTITUTE](FUNC.SUBSTITUTE.md)** — the by-content counterpart. See the section above.\n- **[MID](FUNC.MID.md)** — the same `(start_num, num_chars)` addressing, reading instead of\n  writing. `MID` extracts the window `REPLACE` overwrites.\n- **[REPLACEB](FUNC.REPLACEB.md)** — the byte-addressed sibling, documented by Microsoft on the\n  same page and published by the Handbook as a separate entry.\n- **`FIND` and `SEARCH`** are what supplies `start_num` when the window is not known in\n  advance. `SEARCH` is case-insensitive and takes wildcards; `FIND` is neither. Choosing\n  between them changes what `REPLACE` overwrites.\n- **`TEXTBEFORE` / `TEXTAFTER`** cover many `REPLACE`-with-a-computed-position formulas more\n  directly.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n\nThe three-piece concatenation identity above is the implementation, and the only subtleties\nare at its edges: what `LEFT(t, s-1)` does when `s-1` exceeds `LEN(t)`, and what `MID(t, s+k,\nLEN(t))` does when `s+k` exceeds it. Both must be defined so that a window entirely past the\nend degrades gracefully rather than producing a `#VALUE!` from an intermediate step.\n\nBecause `REPLACE` can grow its input, it is one of the functions that can manufacture a string\nover the 32,767 code-unit cap from inputs that are each individually legal. Whatever the\npublication behaviour turns out to be, it has to be applied at the function's own boundary and\nnot left to the cell.\n\nCounting is in UTF-16 code units, consistent with `LEN` and `MID`. A `REPLACE` window can\ntherefore split a surrogate pair, and the implementation has to survive producing ill-formed\nUTF-16 — the Handbook's value-universe chapter records that state as reachable in practice.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Text`.\n\nMicrosoft's `REPLACE` page states the signature and the meaning of each argument but does not\nenumerate boundary behaviours the way the `MID` page does. The following are therefore\n*expected* rather than documented, and the Handbook has not checked any of them:\n\n- `start_num` past the end of `old_text` — plausibly an append; unverified.\n- `num_chars` running past the end of `old_text` — plausibly a clamp to the end; unverified.\n- `num_chars` of 0 — insertion, as above; this follows from the definition but is not stated\n  on the page.\n- `start_num` less than 1 — the sibling functions document `#VALUE!` for this; `REPLACE`'s\n  page does not.\n\n\n### REPLACE versus SUBSTITUTE\n\n\nThese two are the most-confused pair in the text category, and the distinction is clean once\nstated. Microsoft states it on the `SUBSTITUTE` page itself:\n\n> Use `SUBSTITUTE` when you want to replace specific text in a text string; use `REPLACE` when\n> you want to replace any text that occurs in a specific location in a text string.\n\n| | `REPLACE` | `SUBSTITUTE` |\n|---|---|---|\n| Addresses the target by | **position** (`start_num`, `num_chars`) | **content** (`old_text` matched literally) |\n| Number of edits | exactly one window | every occurrence, or one chosen occurrence |\n| If the target is not there | meaningless — there is no target to find | returns the input unchanged |\n| Case sensitivity | not applicable | case-**sensitive** |\n| Wildcards | not applicable | none |\n| Length preserved | no | no |\n\nThe one-line test: if your formula computes `start_num` with `FIND` or `SEARCH`, you probably\nwanted `SUBSTITUTE`. If your positions come from a fixed-width record layout, you wanted\n`REPLACE`.\n\nSee [SUBSTITUTE](FUNC.SUBSTITUTE.md) for the other side of this pair.\n\n\n\n### Errors\n\n\nMicrosoft's `REPLACE, REPLACEB` page does not carry an error table. The errors reachable here\nare the shared ones: an error value in any argument propagates, and non-numeric text in\n`start_num` or `num_chars` surfaces `#VALUE!` under the shared coercion rules. A result\nexceeding the 32,767 code-unit text cap is the other candidate — the Handbook's value-universe\nchapter records `#VALUE!` for the over-cap formula path observed with `REPT`, but whether\n`REPLACE` publishes the same way is unverified.\n\n\n",
    "sources": "- Microsoft, \"REPLACE, REPLACEB functions\" —\n  <https://support.microsoft.com/en-us/office/replace-function-8d799074-2425-4a8a-84bc-82472868878a>\n  (signature and argument meanings).\n- Microsoft, \"SUBSTITUTE function\" —\n  <https://support.microsoft.com/en-us/office/substitute-function-6434944e-a904-4336-a9b0-1e58df3bc332>\n  (the quoted by-content versus by-location guidance).\n- Handbook, [The value universe](../model/01-value-universe.md) — the 32,767 code-unit text\n  cap, the observed `#VALUE!` on the over-cap formula path, and surrogate splitting.\n- Handbook, [Coercion and lifting](../model/02-coercion-and-lifting.md) — numeric-argument\n  coercion and error propagation.\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`REPLACE(old_text, start_num, num_chars, new_text)` returns `old_text` with the window of\n`num_chars` characters beginning at position `start_num` removed and `new_text` put in its\nplace. Positions are 1-based.\n\nEquivalently, in terms of the slicing functions:\n\n```\nREPLACE(t, s, k, new)  =  LEFT(t, s - 1) & new & MID(t, s + k, LEN(t))\n```\n\nTwo consequences of that identity are worth reading off it directly, because they are the two\nthings people get wrong about this function:\n\n1. **`REPLACE` does not look at what it is replacing.** It never inspects the characters in\n   the window. It cannot fail to find anything, because it does not search.\n2. **The result length is not the input length.** `new_text` need not be `num_chars` long. With\n   `num_chars` of 0, `REPLACE` inserts without deleting; with `new_text` empty, it deletes\n   without inserting. These are not tricks — they fall straight out of the definition, and\n   they are the idiomatic way to do both operations.\n\n`REPLACEB` is the byte-addressed sibling; see [REPLACEB](FUNC.REPLACEB.md).\n\n\n\n### Arguments\n\n\n| Argument | Meaning |\n|---|---|\n| `old_text` | The string to modify. Required. |\n| `start_num` | 1-based position of the first character to replace. Required. |\n| `num_chars` | How many characters to remove. Required. |\n| `new_text` | What to put in their place. Required. |\n\nAll four are required — there is no \"replace to the end\" default and no optional argument.\n\n`start_num` and `num_chars` are numeric slots subject to ordinary to-number coercion; see\n[Coercion and lifting](../model/02-coercion-and-lifting.md).\n\nThe commonly misread position is `num_chars`. It is a **count of characters to remove from\n`old_text`**, not an end position and not the length of `new_text`. `REPLACE(\"abcdef\", 2, 3,\n\"XY\")` removes `bcd` and yields `aXYef`.\n\n\n"
  },
  "signature": {
    "display": "REPLACE(old_text, start_num, num_chars, new_text)",
    "parameters": [
      {
        "description": null,
        "name": "old_text",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "start_num",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "num_chars",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "new_text",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 4,
        "min": 4
      },
      "category": "Text functions",
      "classification": {
        "arg_preparation_profile": "ValuesOnlyPreAdapter",
        "coercion_lift_profile": "None",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Text with a span of characters replaced by other text",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Replaces characters within text",
        "microsoft_url": "https://support.microsoft.com/en-us/office/replace-function-8d799074-2425-4a8a-84bc-82472868878a"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "REPLACE"
        },
        {
          "locale": "bg-BG",
          "name": "REPLACE"
        },
        {
          "locale": "da-DK",
          "name": "ERSTAT"
        },
        {
          "locale": "de-DE",
          "name": "REPLACE"
        },
        {
          "locale": "el-GR",
          "name": "REPLACE"
        },
        {
          "locale": "en-AU",
          "name": "REPLACE"
        },
        {
          "locale": "en-GB",
          "name": "REPLACE"
        },
        {
          "locale": "en-US",
          "name": "REPLACE"
        },
        {
          "locale": "es-ES",
          "name": "REEMPLAZAR"
        },
        {
          "locale": "et-EE",
          "name": "REPLACE"
        },
        {
          "locale": "fi-FI",
          "name": "KORVAA"
        },
        {
          "locale": "fr-FR",
          "name": "REMPLACER"
        },
        {
          "locale": "he-IL",
          "name": "REPLACE"
        },
        {
          "locale": "hr-HR",
          "name": "REPLACE"
        },
        {
          "locale": "hu-HU",
          "name": "CSERE"
        },
        {
          "locale": "id-ID",
          "name": "REPLACE"
        },
        {
          "locale": "it-IT",
          "name": "REPLACE"
        },
        {
          "locale": "ja-JP",
          "name": "REPLACE"
        },
        {
          "locale": "ko-KR",
          "name": "REPLACE"
        },
        {
          "locale": "lt-LT",
          "name": "REPLACE"
        },
        {
          "locale": "lv-LV",
          "name": "REPLACE"
        },
        {
          "locale": "nb-NO",
          "name": "REPLACE"
        },
        {
          "locale": "nl-NL",
          "name": "VERVANGEN"
        },
        {
          "locale": "pl-PL",
          "name": "ZASTĄP"
        },
        {
          "locale": "pt-BR",
          "name": "REPLACE"
        },
        {
          "locale": "pt-PT",
          "name": "SUBSTITUIR"
        },
        {
          "locale": "ro-RO",
          "name": "REPLACE"
        },
        {
          "locale": "ru-RU",
          "name": "ЗАМЕНИТЬ"
        },
        {
          "locale": "sk-SK",
          "name": "REPLACE"
        },
        {
          "locale": "sl-SI",
          "name": "REPLACE"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "REPLACE"
        },
        {
          "locale": "sv-SE",
          "name": "ERSÄTT"
        },
        {
          "locale": "th-TH",
          "name": "REPLACE"
        },
        {
          "locale": "tr-TR",
          "name": "DEĞİŞTİR"
        },
        {
          "locale": "uk-UA",
          "name": "REPLACE"
        },
        {
          "locale": "vi-VN",
          "name": "REPLACE"
        },
        {
          "locale": "zh-CN",
          "name": "REPLACE"
        },
        {
          "locale": "zh-HK",
          "name": "REPLACE"
        },
        {
          "locale": "zh-TW",
          "name": "REPLACE"
        }
      ],
      "signature": {
        "display": "REPLACE(old_text, start_num, num_chars, new_text)",
        "parameters": [
          {
            "description": null,
            "name": "old_text",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "start_num",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "num_chars",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "new_text",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "REPLACE",
      "version_marker": null,
      "xlcall": null
    },
    "microsoft": "https://support.microsoft.com/en-us/office/replace-function-8d799074-2425-4a8a-84bc-82472868878a"
  },
  "try_it": {
    "formula": "=REPLACE(\"handbook\",1,4,\"note\")"
  },
  "url": "https://handbook.dnacalc.com/functions/REPLACE.html",
  "variants": [
    {
      "code": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/text_functions.rs#L305-L307",
      "difference": "A surrogate pair counts as two characters.",
      "error_bound": null,
      "evidence": [
        {
          "commit": "",
          "locator": "",
          "note": "",
          "path": "https://support.microsoft.com/en-gb/excel/compatibility-versions",
          "repository": ""
        }
      ],
      "key": {
        "cpu": "Any",
        "excel_build_range": "Compatibility Version 1, all Excel versions"
      },
      "kind": "environment",
      "name": "REPLACE at Compatibility Version 1",
      "onecalc_udf": null,
      "state": "selected",
      "state_summary": "Implemented; selected by the workbook's Compatibility Version."
    },
    {
      "code": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/text_functions.rs#L305-L307",
      "difference": "A surrogate pair counts as one character. Characters combined from several code points still count separately.",
      "error_bound": null,
      "evidence": [
        {
          "commit": "",
          "locator": "",
          "note": "",
          "path": "https://support.microsoft.com/en-gb/excel/compatibility-versions",
          "repository": ""
        }
      ],
      "key": {
        "cpu": "Any",
        "excel_build_range": "Compatibility Version 2, Excel for Microsoft 365"
      },
      "kind": "environment",
      "name": "REPLACE at Compatibility Version 2",
      "onecalc_udf": null,
      "state": "selected",
      "state_summary": "Implemented; selected by the workbook's Compatibility Version."
    }
  ],
  "versions": []
}