iOfficeAI/OfficeCLI · error · System.ArgumentException

Sheet not found: {cfSheetName}

Error message

Sheet not found: {cfSheetName}

What it means

Thrown by AddDataBar when FindWorksheet(cfSheetName) returns null. The sheet name is the first segment of parentPath after trimming the leading slash. This fires after the type-allowlist check (498) passes, so the type was valid (or defaulted to databar) but the sheet segment does not resolve to a worksheet.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cf.cs:126

                return Add(parentPath, "cfextended", position, properties);
            // R10: Reject unknown CF types instead of silently falling through to
            // dataBar. The `cf` alias (AddCf) already throws on unknowns; mirror
            // the behavior here so both `--type cf` and `--type conditionalformatting`
            // share the same allowlist (CONSISTENCY(cf-type-allowlist)). `databar`
            // is the documented default for this alias, so allow it explicitly.
            if (cfTypeLower is not "databar")
            {
                throw new ArgumentException(
                    $"Unknown CF type '{cfTypeProp}'. Valid: databar, iconset, colorscale, formula, cellIs, "
                    + "top10, topPercent, bottom, bottomPercent, aboveAverage, belowAverage, "
                    + "uniqueValues, duplicateValues, containsText, notContains, beginsWith, endsWith, "
                    + "containsBlanks, notContainsBlanks, containsErrors, notContainsErrors, dateOccurring.");
            }
        }
        var cfSegments = parentPath.TrimStart('/').Split('/', 2);
        var cfSheetName = cfSegments[0];
        var cfWorksheet = FindWorksheet(cfSheetName)
            ?? throw new ArgumentException($"Sheet not found: {cfSheetName}");

        // R22-2: a path-tail range (/Sheet1/A1:A3) is the sqref fallback before
        // the hardcoded "A1:A10" — previously csSegments[1] was silently ignored.
        var cfPathRange = cfSegments.Length > 1 && !string.IsNullOrEmpty(cfSegments[1]) ? cfSegments[1] : "A1:A10";
        var sqref = ValidateSqref(properties.GetValueOrDefault("sqref") ?? properties.GetValueOrDefault("range") ?? properties.GetValueOrDefault("ref", cfPathRange), "ref");
        var minVal = properties.ContainsKey("min") ? properties["min"] : (string?)null;
        var maxVal = properties.ContainsKey("max") ? properties["max"] : (string?)null;
        // The schema documents min/max as "numeric or 'auto'". 'auto' is the
        // automatic-bound sentinel, NOT a literal value: emitting it as a
        // numeric cfvo (<cfvo type="num" val="auto"/>) is malformed and Excel
        // silently drops the whole data bar. Map it back to null so the cfvo
        // builders below pick the type="min"/type="max" (and x14 AutoMin/AutoMax)
        // branches — identical to the user omitting the bound entirely.
        if (string.Equals(minVal, "auto", StringComparison.OrdinalIgnoreCase)) minVal = null;
        if (string.Equals(maxVal, "auto", StringComparison.OrdinalIgnoreCase)) maxVal = null;
        var cfColor = properties.GetValueOrDefault("color", "638EC6");
        var normalizedColor = ParseHelpers.NormalizeArgbColor(cfColor);

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Confirm the sheet exists via a Get on / and use the exact name.
  2. Create the sheet first if it is missing.
  3. Ensure the path begins with /<exactSheetName> (a trailing /A1:A10 range is optional but allowed).

Example fix

// before
handler.Add("/SheetZ", "cf", null, props); // SheetZ missing

// after
handler.Add("/Sheet1", "cf", null, props);
Defensive patterns

Strategy: validation

Validate before calling

string sheet = parentPath.TrimStart('/').Split('/', 2)[0];
var sheets = handler.Query("/");
if (!sheets.Any(s => string.Equals(s.Name, sheet, StringComparison.OrdinalIgnoreCase)))
    throw new InvalidOperationException($"Sheet not found: {sheet}");
handler.Add(parentPath, "cf", null, props);

Type guard

static bool SheetExists(IExcelHandler h, string sheet)
    => h.Query("/").Any(s => string.Equals(s.Name, sheet, StringComparison.OrdinalIgnoreCase));

Try / catch

try { handler.Add(parentPath, "cf", null, props); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Sheet not found"))
{ /* create the sheet or report the missing name */ }

Prevention

When it happens

Trigger: Add type=cf or type=conditionalformatting with parentPath="/BadSheet" or a path whose sheet segment is not a worksheet. A path-tail range (e.g. /Sheet1/A1:A3) is fine because only the first segment is used for the sheet lookup; the range is consumed later as the sqref fallback.

Common situations: Sheet renamed or deleted after the path was captured. Script reuses a sheet name from a different workbook. Typo or trailing whitespace in the sheet segment.

Related errors


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