{"record":{"id":"5499123788ae5621","repo":"iOfficeAI/OfficeCLI","slug":"calculatedfield-raw-must-be-name-formula-c","errorCode":null,"errorMessage":"calculatedField '{raw}' must be 'Name:=Formula' (colon-separated)","messagePattern":"calculatedField '(.+?)' must be 'Name:=Formula' \\(colon-separated\\)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/PivotTableHelper.Definition.cs","lineNumber":1749,"sourceCode":"            {\n                throw new ArgumentException($\"invalid JSON for calculatedFields: {ex.Message}\");\n            }\n        }\n\n        // Numbered + bare calculatedField props (ordinal sort so calculatedField1\n        // appears before calculatedField2 regardless of insertion order).\n        var cfKeys = properties.Keys\n            .Where(k => System.Text.RegularExpressions.Regex.IsMatch(\n                k, @\"^calculatedField\\d*$\", System.Text.RegularExpressions.RegexOptions.IgnoreCase))\n            .OrderBy(k => k, StringComparer.OrdinalIgnoreCase)\n            .ToList();\n        foreach (var key in cfKeys)\n        {\n            var raw = properties[key];\n            if (string.IsNullOrWhiteSpace(raw)) continue;\n            var colonIdx = raw.IndexOf(':');\n            if (colonIdx < 0)\n                throw new ArgumentException(\n                    $\"calculatedField '{raw}' must be 'Name:=Formula' (colon-separated)\");\n            var name = raw[..colonIdx].Trim();\n            var formula = raw[(colonIdx + 1)..].Trim();\n            result.Add((name, formula));\n        }\n\n        return result;\n    }\n\n}\n","sourceCodeStart":1731,"sourceCodeEnd":1760,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/PivotTableHelper.Definition.cs#L1731-L1760","documentation":"The bare or numbered 'calculatedField' / 'calculatedField1' / 'calculatedField2' props use a colon-separated 'Name:=Formula' syntax. If the value has no colon at all, the parser cannot split name from formula and rejects it with this message. Note: a literal colon inside the formula after the first one is fine, because only IndexOf(':') (the first colon) is used as the split point.","triggerScenarios":"calculatedField=SalesFormula (no colon); calculatedField=Sales=A1*2 (used '=' instead of ':' as separator); calculatedField1 with whitespace-only content that lost its colon; copy-paste from Excel's formula bar where ':' was dropped.","commonSituations":"User assumes '=' separates name and formula (it actually starts the formula half after the colon); a templating step stripped the colon; mismatch with the documented Name:=Formula contract.","solutions":["Use the colon form: calculatedField=Margin:=Sales-Cost","For multiple fields, use numbered props: calculatedField1=Margin:=Sales-Cost and calculatedField2=Tax:=Margin*0.2","Switch to JSON form (calculatedFields=[{...}]) if your names or formulas contain colons"],"exampleFix":"// before\ncalculatedField=\"SalesFormula=A1*2\"\n// after\ncalculatedField=\"SalesFormula:=A1*2\"","handlingStrategy":"validation","validationCode":"foreach (var (key, raw) in cfProps)\n    if (string.IsNullOrWhiteSpace(raw) || raw.IndexOf(':') < 0)\n        throw new InvalidOperationException($\"{key} must be 'Name:=Formula'\");","typeGuard":"static bool IsColonFormSpec(string raw) =>\n    !string.IsNullOrWhiteSpace(raw) && raw.IndexOf(':') >= 0;","tryCatchPattern":"try { AddCalculatedFields(props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"colon-separated\"))\n{ /* rewrite with the 'Name:=Formula' shape */ }","preventionTips":["Use ':' (not '=') to separate name and formula","Switch to JSON form if names or formulas contain colons","Validate the colon presence in your own input layer"],"tags":["pivottable","calculated-field","argument-validation","input-parsing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}