iOfficeAI/OfficeCLI · error · ArgumentException

Invalid defined-name '{nrName}': single letter 'R' / 'C' is

Error message

Invalid defined-name '{nrName}': single letter 'R' / 'C' is reserved by Excel for R1C1 reference notation; choose a different name.

What it means

Thrown when the defined name is the single letter R or C (case-insensitive). Excel reserves these because they collide with R1C1 reference notation; using either as a workbook defined name makes Excel reject the file with 0x800A03EC. This is a targeted check that runs after the cell-reference check (554), so it specifically catches the R/C reservation that LooksLikeCellReference does not.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs:66

        // reference. Otherwise Excel rejects the file with 0x800A03EC.
        // "Letter" is any Unicode letter (\p{L}) — Excel accepts CJK/
        // Cyrillic/etc. names; the previous ASCII-only class falsely
        // rejected them. Emoji/symbols stay rejected (not \p{L}).
        if (!System.Text.RegularExpressions.Regex.IsMatch(nrName, @"^[\p{L}_\\][\p{L}\p{N}_\\.]*$"))
            throw new ArgumentException($"Invalid defined-name '{nrName}': must start with a letter/underscore and contain only letters, digits, underscores, or periods (no spaces).");
        // Excel caps defined-name identifier length at 255 characters; longer
        // names are silently truncated on open (or the file is rejected with
        // 0x800A03EC depending on host). Refuse up front instead of letting
        // a 256+ char name land on disk and round-trip-differ on re-open.
        if (nrName.Length > 255)
            throw new ArgumentException($"Invalid defined-name '{nrName}': length {nrName.Length} exceeds the Excel 255-character limit.");
        if (LooksLikeCellReference(nrName))
            throw new ArgumentException($"Invalid defined-name '{nrName}': name parses as a cell reference; choose a different name.");
        // R39-5: Excel reserves the single letters R and C (case-insensitive)
        // because they collide with R1C1 reference notation. Excel rejects
        // the file with 0x800A03EC if either is used as a defined name.
        if (nrName.Length == 1 && (nrName[0] == 'R' || nrName[0] == 'r' || nrName[0] == 'C' || nrName[0] == 'c'))
            throw new ArgumentException($"Invalid defined-name '{nrName}': single letter 'R' / 'C' is reserved by Excel for R1C1 reference notation; choose a different name.");
        // `refersTo` is the common Excel-documented alias for `ref`;
        // silently map it so users don't end up with an empty
        // <x:definedName/> that corrupts the file.
        var refVal = properties.GetValueOrDefault("ref",
            properties.GetValueOrDefault("refersTo",
                properties.GetValueOrDefault("formula", "")));
        // R15/bt-2: reject up-front when the required ref/refersTo/formula
        // value is missing so an empty <x:definedName/> never gets written
        // (the resulting zombie polluted the workbook and broke later Set
        // calls). Unsupported aliases like `range=` previously silently
        // landed here as empty and produced the zombie.
        if (string.IsNullOrEmpty(refVal))
            throw new ArgumentException("'ref' (or 'refersTo' / 'formula') property is required for namedrange");
        // R7-2: per ECMA-376 §18.2.5, <x:definedName> content must NOT
        // have a leading '=' (unlike the formula-bar form in Excel UI).
        // Excel rejects the file with 0x800A03EC if '=' is present.
        if (refVal.StartsWith('='))
            refVal = refVal.TrimStart('=');

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a longer name like `RowRange`, `ColRange`, `R_Range`, or any name with more than one character.
  2. Avoid the single letters R and C entirely for defined names.

Example fix

// before
add ./book.xlsx /namedrange --type namedrange --prop name=C --prop ref=Sheet1!C:C
// after
add ./book.xlsx /namedrange --type namedrange --prop name=ColRange --prop ref=Sheet1!C:C
Defensive patterns

Strategy: validation

Validate before calling

if (name.Length == 1 && (name[0] is 'R' or 'r' or 'C' or 'c'))
    throw new InvalidOperationException("Defined name 'R'/'C' is reserved for R1C1 notation");

Type guard

static bool IsNotReservedRc(string? s)
    => s is null || s.Length != 1 || (s[0] is not 'R' and not 'r' and not 'C' and not 'c');

Try / catch

try { handler.AddNamedRange(...); }
catch (ArgumentException ex) when (ex.Message.Contains("reserved by Excel for R1C1"))
{ /* rename to something longer */ }

Prevention

When it happens

Trigger: Passing `name=R`, `name=r`, `name=C`, or `name=c`. These single letters pass the identifier regex and the cell-reference check but are independently reserved.

Common situations: Using `R` for a 'Row' range or `C` for a 'Column' range as a mnemonic; auto-generated single-letter names.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/ee7c8bdb81afd511. Report an issue: GitHub.