{"record":{"id":"a33e55be3f4ffdef","repo":"iOfficeAI/OfficeCLI","slug":"defined-name-nrname-already-exists-in-workbook","errorCode":null,"errorMessage":"Defined name '{nrName}' already exists in workbook scope; remove it before adding a new one or pick a different name.","messagePattern":"Defined name '(.+?)' already exists in workbook scope; remove it before adding a new one or pick a different name\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs","lineNumber":191,"sourceCode":"        // recalc engine treats function-flagged defined names as volatile,\n        // forcing recalc on every workbook change.\n        if (properties.TryGetValue(\"volatile\", out var nrVolatile) && IsTruthy(nrVolatile))\n            dn.Function = true;\n\n        // CONSISTENCY(definedname-unique): Excel rejects two\n        // <definedName> entries that share both name AND scope\n        // (LocalSheetId) with a \"found a problem\" repair dialog.\n        // Same name across different scopes (workbook-global vs\n        // per-sheet, or two distinct sheets) is legal — only the\n        // (name, localSheetId) pair must be unique.\n        var dnLocalId = dn.LocalSheetId?.Value;\n        foreach (var existingDn in definedNames.Elements<DefinedName>())\n        {\n            var existingName = existingDn.Name?.Value;\n            if (existingName == null) continue;\n            if (!string.Equals(existingName, nrName, StringComparison.OrdinalIgnoreCase)) continue;\n            if (existingDn.LocalSheetId?.Value == dnLocalId)\n                throw new ArgumentException(\n                    $\"Defined name '{nrName}' already exists\" +\n                    (dnLocalId.HasValue ? $\" in sheet scope (localSheetId={dnLocalId})\" : \" in workbook scope\") +\n                    \"; remove it before adding a new one or pick a different name.\");\n        }\n\n        // Mirror of the table-side check: Excel's name namespace spans\n        // defined names AND ListObject table names; a collision passes\n        // schema validation but real Excel refuses the file (0x800A03EC).\n        foreach (var existingTable in _doc.WorkbookPart!.WorksheetParts\n            .SelectMany(wp => wp.TableDefinitionParts)\n            .Select(tdp => tdp.Table)\n            .Where(t => t != null)!)\n        {\n            if (string.Equals(existingTable!.Name?.Value, nrName, StringComparison.OrdinalIgnoreCase)\n                || string.Equals(existingTable.DisplayName?.Value, nrName, StringComparison.OrdinalIgnoreCase))\n                throw new ArgumentException(\n                    $\"Defined name '{nrName}' collides with the table name '{existingTable.Name?.Value ?? existingTable.DisplayName?.Value}'. Excel requires table and defined names to be unique in one namespace; pick a different name.\");\n        }","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs#L173-L209","documentation":"Thrown when a defined name with the same identifier AND the same scope (LocalSheetId) already exists in the workbook. OOXML permits the same name across different scopes (workbook-global vs a specific sheet, or two distinct sheets), but a duplicate (name, localSheetId) pair triggers Excel's 'found a problem' repair dialog. The check iterates existing <definedName> entries comparing name (case-insensitive) and LocalSheetId, and additionally checks for collisions with ListObject table names. The message states whether the conflict is sheet-scoped or workbook-scoped.","triggerScenarios":"Calling add namedrange with a `name=` that already exists at the same scope (e.g. re-running a script that adds `SalesTotal` at workbook scope twice); or a name that collides with an existing table name. A same-named name on a DIFFERENT sheet scope does NOT trigger this.","commonSituations":"Re-running an import script without first removing the previously added name; merging workbooks that each defined the same global name; choosing a name that matches an existing table.","solutions":["Remove the existing defined name first (via the tool's remove/delete command) then re-add.","Pick a different name for the new defined range.","If you want a per-sheet name with the same spelling as a workbook-global one, add it scoped to a specific sheet (different LocalSheetId) — that is legal."],"exampleFix":"// before\nadd ./book.xlsx /namedrange --type namedrange --prop name=SalesTotal --prop ref=Sheet1!A1  // when SalesTotal already exists\n// after\n// (option A) remove then re-add, or (option B) rename\nadd ./book.xlsx /namedrange --type namedrange --prop name=SalesTotal2024 --prop ref=Sheet1!A1","handlingStrategy":"validation","validationCode":"// Reject (name, scope) duplicates before add, mirroring the handler.\nforeach (var dn in definedNames.Elements<DefinedName>())\n{\n    if (string.Equals(dn.Name?.Value, name, StringComparison.OrdinalIgnoreCase)\n        && dn.LocalSheetId?.Value == targetLocalSheetId)\n        throw new InvalidOperationException($\"'{name}' already exists in that scope; remove or rename\");\n}\n// Also guard against ListObject table-name collisions.","typeGuard":"static bool DefinedNameIsUnique(IEnumerable<DefinedName> existing, string name, uint? scope)\n    => !existing.Any(d => string.Equals(d.Name?.Value, name, StringComparison.OrdinalIgnoreCase)\n        && d.LocalSheetId?.Value == scope);","tryCatchPattern":"try { handler.AddNamedRange(...); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"already exists\"))\n{ /* remove the old name first, or pick a new name — do NOT retry unchanged */ }","preventionTips":["Make add-namedrange scripts idempotent: remove-then-add, or check existence first.","Remember same name in a DIFFERENT scope is legal; only (name, scope) collisions fail.","Avoid name collisions with ListObject table names — they share Excel's name namespace."],"tags":["excel","named-range","defined-name","duplicate","conflict","input-validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}