{
  "category": "Text functions",
  "display_name": "MIDB",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.MIDB",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 7 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 7 recorded answers",
    "workbook_corpus": {
      "cells": 7,
      "matched": 7
    }
  },
  "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#L279-L279"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/text_functions::count_surrogate_pairs",
        "catalogue/text_functions::single_byte",
        "catalogue/text_functions::mid",
        "catalogue/text_functions::start",
        "ported/text_kernels::text",
        "ported/text_kernels::text_from_str",
        "ported/text_kernels::date_integer_floor",
        "ported/text_kernels::nonnegative_count",
        "ported/text_kernels::mid_start",
        "ported/text_kernels::unit_width",
        "ported/text_kernels::character_boundary",
        "ported/text_kernels::take_mid",
        "ported/text_kernels::truncated",
        "ported/text_kernels::positive",
        "ported/text_kernels::push_singleton_or_original",
        "ported/text_kernels::push_upper",
        "ported/text_kernels::upper"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/text_functions.rs#L279-L279",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 7 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.MIDB.json",
  "name": "MIDB",
  "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- [MID](FUNC.MID.md) is the character-counting twin. Microsoft documents the two on a single\n  page, `MID, MIDB`; the Handbook publishes them as two entries because they are two functions\n  with two different addressing units.\n- `LENB` is the function you need to reason about `MIDB` offsets at all, because `MIDB`\n  positions are `LENB` positions, not `LEN` positions.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n\nThree things make this function harder than it looks.\n\n1. **It is host-state dependent.** The active default editing language is an input to the\n   function that does not appear in its argument list. Any implementation that wants to match\n   Excel needs that state threaded in, and any test vector for `MIDB` is meaningless without\n   recording it.\n2. **The code page is per-language.** Shift-JIS, GBK, Big5 and EUC-KR assign different byte\n   widths to different characters. \"Two bytes for CJK\" is a summary, not a specification.\n3. **Partial-character windows are reachable and undefined here.** Pick a behaviour, document\n   it, and mark it as unverified — do not present a guess as the rule.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Text`.\n\nThe boundary rules Microsoft documents for `MID` are stated on the same page for `MIDB` with\n\"characters\" replaced by \"bytes\": a `start_num` past the end of `text` yields the empty string,\nand a window running past the end yields the bytes to the end of `text`.\n\nThe genuinely `MIDB`-specific question — what happens when `start_num` or `start_num +\nnum_bytes` lands **inside** a double-byte character rather than on its boundary — is not\nanswered by Microsoft's page. There are several defensible behaviours (return the half byte as\na replacement character, drop the partial character, round the boundary outward, round it\ninward) and the Handbook does not know which one Excel implements. This is the single most\nimportant open question about this function and it is not a corner case: any offset arithmetic\nover mixed-width text hits it immediately.\n\nEmpty, missing and error arguments follow the shared call model; see\n[Coercion and lifting](../model/02-coercion-and-lifting.md).\n\n\n\n### Errors\n\n\nAs documented on Microsoft's `MID, MIDB` page:\n\n| Error | Condition |\n|---|---|\n| `#VALUE!` | `start_num` is less than 1. |\n| `#VALUE!` | `num_bytes` is negative. |\n\nNon-numeric text in a numeric argument slot and incoming error values behave as the shared\ncoercion rules describe. The Handbook has not verified any of this against Excel.\n\n\n",
    "sources": "- Microsoft, \"MID, MIDB functions\" —\n  <https://support.microsoft.com/en-us/office/mid-function-d5f9e25c-d7d6-472e-b568-4ecb12433028>\n  (the shared signature, the boundary rules, and the DBCS default-language condition).\n- Handbook, [The value universe](../model/01-value-universe.md) — worksheet text as UTF-16\n  code units, which is what the byte view has to be reconciled against.\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`MIDB(text, start_num, num_bytes)` returns the run of `text` that begins at **byte** position\n`start_num` and is `num_bytes` bytes long, where byte positions are counted from 1.\n\nThe whole content of this function is the word \"byte\", and Microsoft states precisely when it\nmeans anything:\n\n> The B functions count each double-byte character as 2 **only when a DBCS language has been\n> enabled for editing and set as the default language**. Otherwise they count each character\n> as 1.\n\nSo `MIDB` has two behaviours and which one you get is a property of the machine, not of the\nformula. On a default-English installation `MIDB(text, s, k)` and `MID(text, s, k)` are the\nsame function. On an installation whose default language is Japanese, Chinese (Simplified or\nTraditional), or Korean, every character in a double-byte range costs two positions.\n\nThe byte count is against the **DBCS code page for the active language**, not UTF-8 and not\nUTF-16. That distinction matters for anyone implementing this: a UTF-8 byte count would make a\nLatin-1 accented character cost two bytes and a CJK character cost three, and neither matches\nthe DBCS rule.\n\n\n\n### Arguments\n\n\n| Argument | Meaning |\n|---|---|\n| `text` | The string to slice. Required. |\n| `start_num` | 1-based **byte** position of the first byte to take. Required. |\n| `num_bytes` | How many bytes to take. Required, and must not be negative. |\n\nAll three are required. The argument name is the only signature difference from `MID`; the\narity and positions are identical.\n\n\n"
  },
  "signature": {
    "display": "MIDB(text, start_num, num_bytes)",
    "parameters": [
      {
        "description": null,
        "name": "text",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "start_num",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "num_bytes",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 3
      },
      "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": "Characters from the middle of a text, counted in bytes for double-byte languages",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns a specific number of characters from a text string starting at the position you specify",
        "microsoft_url": "https://support.microsoft.com/en-us/office/mid-function-d5f9e25c-d7d6-472e-b568-4ecb12433028"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "MIDB"
        },
        {
          "locale": "bg-BG",
          "name": "MIDB"
        },
        {
          "locale": "cs-CZ",
          "name": "MIDB"
        },
        {
          "locale": "da-DK",
          "name": "MIDTB"
        },
        {
          "locale": "de-DE",
          "name": "MIDB"
        },
        {
          "locale": "el-GR",
          "name": "MIDB"
        },
        {
          "locale": "en-AU",
          "name": "MIDB"
        },
        {
          "locale": "en-GB",
          "name": "MIDB"
        },
        {
          "locale": "en-US",
          "name": "MIDB"
        },
        {
          "locale": "es-ES",
          "name": "EXTRAEB"
        },
        {
          "locale": "et-EE",
          "name": "MIDB"
        },
        {
          "locale": "fi-FI",
          "name": "POIMI.TEKSTIB"
        },
        {
          "locale": "fr-FR",
          "name": "STXTB"
        },
        {
          "locale": "he-IL",
          "name": "MIDB"
        },
        {
          "locale": "hr-HR",
          "name": "MIDB"
        },
        {
          "locale": "hu-HU",
          "name": "KÖZÉP2"
        },
        {
          "locale": "id-ID",
          "name": "MIDB"
        },
        {
          "locale": "it-IT",
          "name": "MIDB"
        },
        {
          "locale": "ja-JP",
          "name": "MIDB"
        },
        {
          "locale": "ko-KR",
          "name": "MIDB"
        },
        {
          "locale": "lt-LT",
          "name": "MIDB"
        },
        {
          "locale": "lv-LV",
          "name": "MIDB"
        },
        {
          "locale": "nb-NO",
          "name": "MIDB"
        },
        {
          "locale": "nl-NL",
          "name": "DEELB"
        },
        {
          "locale": "pl-PL",
          "name": "FRAGMENT.TEKSTU.B"
        },
        {
          "locale": "pt-BR",
          "name": "MIDB"
        },
        {
          "locale": "pt-PT",
          "name": "SEG.TEXTOB"
        },
        {
          "locale": "ro-RO",
          "name": "MIDB"
        },
        {
          "locale": "ru-RU",
          "name": "ПСТРБ"
        },
        {
          "locale": "sk-SK",
          "name": "MIDB"
        },
        {
          "locale": "sl-SI",
          "name": "MIDB"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "MIDB"
        },
        {
          "locale": "sv-SE",
          "name": "EXTEXTB"
        },
        {
          "locale": "th-TH",
          "name": "MIDB"
        },
        {
          "locale": "tr-TR",
          "name": "ORTAB işlevleri"
        },
        {
          "locale": "uk-UA",
          "name": "MIDB"
        },
        {
          "locale": "vi-VN",
          "name": "MIDB"
        },
        {
          "locale": "zh-CN",
          "name": "MIDB"
        },
        {
          "locale": "zh-HK",
          "name": "MIDB"
        },
        {
          "locale": "zh-TW",
          "name": "MIDB"
        }
      ],
      "signature": {
        "display": "MIDB(text, start_num, num_bytes)",
        "parameters": [
          {
            "description": null,
            "name": "text",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "start_num",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "num_bytes",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "MIDB",
      "version_marker": null,
      "xlcall": null
    },
    "microsoft": "https://support.microsoft.com/en-us/office/mid-function-d5f9e25c-d7d6-472e-b568-4ecb12433028"
  },
  "try_it": {
    "formula": "=MIDB(\"handbook\",2,3)"
  },
  "url": "https://handbook.dnacalc.com/functions/MIDB.html",
  "variants": [],
  "versions": []
}