iOfficeAI/OfficeCLI · error · ArgumentException

DefinedName '{trimmedInput}' not found

Error message

DefinedName '{trimmedInput}' not found

What it means

In chart data-range parsing (ParseDataRangeForChart), if dataRange has no '!' and no ':' and matches an identifier pattern, the parser tries to resolve it as a workbook DefinedName. If no DefinedName matches case-insensitively, or the match's text is empty, it throws. This is the 'use a named range as the chart source' convenience path; a literal range bypasses it.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Helpers.Chart.cs:419

        string? ExplicitCategoriesRef);

    private (List<(string name, double[] values)> seriesData, string[]? categories, ChartRangeGeometry geometry) ParseDataRangeForChart(
        string dataRange, string defaultSheetName, Dictionary<string, string> properties)
    {
        // CONSISTENCY(defined-name-range): if dataRange has no '!' and no ':' and
        // looks like a workbook-defined name, resolve it to its referent range
        // (e.g. "MyData" -> "Sheet1!$A$1:$B$3"). Excel charts accept defined-name
        // references as a data source, so do the same here.
        var trimmedInput = dataRange.Trim();
        if (!trimmedInput.Contains('!') && !trimmedInput.Contains(':') &&
            System.Text.RegularExpressions.Regex.IsMatch(trimmedInput, @"^[A-Za-z_][A-Za-z0-9_\.]*$"))
        {
            var workbook = _doc.WorkbookPart?.Workbook;
            var defNames = workbook?.GetFirstChild<DefinedNames>();
            var match = defNames?.Elements<DefinedName>()
                .FirstOrDefault(dn => string.Equals(dn.Name?.Value, trimmedInput, StringComparison.OrdinalIgnoreCase));
            if (match == null || string.IsNullOrEmpty(match.Text))
                throw new ArgumentException($"DefinedName '{trimmedInput}' not found");
            dataRange = match.Text!;
        }

        // Parse sheet name and range
        string rangeSheetName = defaultSheetName;
        string rangePart = dataRange.Trim();
        var bangIdx = rangePart.IndexOf('!');
        if (bangIdx >= 0)
        {
            rangeSheetName = rangePart[..bangIdx].Trim('\'');
            rangePart = rangePart[(bangIdx + 1)..];
        }

        // Strip any $ signs for parsing
        var cleanRange = rangePart.Replace("$", "");
        var rangeParts = cleanRange.Split(':');
        if (rangeParts.Length != 2)
            throw new ArgumentException($"Invalid dataRange: '{dataRange}'. Expected format: 'Sheet1!A1:D5', 'A1:B3', or a defined-name");

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Provide a literal range 'Sheet1!A1:D5' instead of a name.
  2. Create or fix the defined name in the workbook before referencing it.
  3. Verify the name's spelling and scope (workbook vs worksheet).
  4. Read DefinedNames first to confirm the name resolves to non-empty text.

Example fix

// before
props["dataRange"] = "MyData";  // no such defined name -> throw

// after
props["dataRange"] = "Sheet1!A1:D5";
// or create the name in the workbook first, then keep "MyData"
Defensive patterns

Strategy: validation

Validate before calling

// If dataRange looks like a name, confirm it resolves before charting.
if (!dataRange.Contains('!') && !dataRange.Contains(':')
    && Regex.IsMatch(dataRange, @"^[A-Za-z_][A-Za-z0-9_\.]*$"))
{
    if (!handler.DefinedNameExists(dataRange)) // your helper
        throw new ArgumentException($"No defined name '{dataRange}'; pass a literal range instead.");
}

Prevention

When it happens

Trigger: chart dataRange=MyData where no defined name 'MyData' exists in the workbook; dataRange=Sales2024 after the name was deleted.

Common situations: Name typo; scope mismatch (the name lives at worksheet scope on a different sheet); the defined name was deleted or never created; the name's referent text is empty.

Related errors


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