?? ?? ?? ???? PPTX ??? ? ?? ??
?? ?? ??? PPTX/DOCX/XLSX/HTML ???? ? ?????, PPTX? ???? ??? ? ???? ?? ???? ? ??? ?? ?? ???? ????. ?? ????: - ExcelSkill? conditional_formats? ??? ?? ???? ??? ? ?????? OpenXML? ?? ???? workbook quality review? ?? - DocxSkill? style_map? ??? ???? ??/??/?? ???? ?? ?? ParagraphStyleId? ?? - HtmlSkill? print_header/print_footer ?? ?? ???? ???? ArtifactQualityReviewService? ?? ?? ?? ???? ?? - PptxTemplatePackRegistry? PptxSkill template_pack ????? ??? strategy/board/pmo/finance/sales/operating_model ??? ??? ?? ?? ?? ??? ?? - ?????, ????, ?? ???, ??? ?? ?? ?? ???? ???? ?? ?? ?? ???? ???? ???? ?? ?? ??: - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_next_doc_ppt\\ -p:IntermediateOutputPath=obj\\verify_next_doc_ppt\\ => ?? 0 / ?? 0 - dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ArtifactQualityReviewServiceTests|ExcelSkillDataValidationTests|ExcelSkillConditionalFormattingTests|ExcelSkillExecutiveSummaryLinkTests|ExcelSkillSummarySheetTests|DocxSkillTemplateFeaturesTests|DocxSkillStyleMapTests|HtmlSkillConsultingSectionsTests|HtmlSkillPrintFrameTests|DocumentAssemblerDocxFeaturesTests|PptxSkillConsultingDeckTests|PptxSkillAutoRepairTests|PptxSkillTemplatePackTests" -p:OutputPath=bin\\verify_next_doc_ppt_tests\\ -p:IntermediateOutputPath=obj\\verify_next_doc_ppt_tests\\ => ?? 15
This commit is contained in:
@@ -43,8 +43,9 @@ public class ExcelSkill : IAgentTool
|
||||
},
|
||||
["number_formats"] = new() { Type = "array", Description = "Number format per column index. Supported: 'currency' (#,##0\"원\"), 'percent' (0.00%), 'decimal' (#,##0.00), 'integer' (#,##0), 'date' (yyyy-mm-dd), or any custom Excel format string. e.g. [\"text\",\"integer\",\"currency\",\"percent\"]", Items = new() { Type = "string" } },
|
||||
["data_validations"] = new() { Type = "array", Description = "Validation rules such as [{\"range\":\"E2:E100\",\"type\":\"list\",\"formula1\":\"\\\"Open,In Progress,Done\\\"\",\"allow_blank\":true,\"prompt\":\"Select status\"}].", Items = new() { Type = "object" } },
|
||||
["conditional_formats"] = new() { Type = "array", Description = "Conditional formatting rules such as [{\"range\":\"C2:C20\",\"type\":\"color_scale\",\"low\":\"FEE2E2\",\"mid\":\"FEF3C7\",\"high\":\"DCFCE7\"},{\"range\":\"D2:D20\",\"type\":\"data_bar\",\"color\":\"2563EB\"}].", Items = new() { Type = "object" } },
|
||||
["col_alignments"] = new() { Type = "array", Description = "Horizontal alignment per column: 'left', 'center', 'right'. Headers always center-aligned.", Items = new() { Type = "string" } },
|
||||
["sheets"] = new() { Type = "array", Description = "Multi-sheet mode: array of sheet objects [{name, headers, rows, style?, theme?, col_widths?, freeze_header?, number_formats?, col_alignments?, merges?, summary_row?, data_validations?}]. When present, overrides top-level headers/rows/sheet_name.", Items = new() { Type = "object" } },
|
||||
["sheets"] = new() { Type = "array", Description = "Multi-sheet mode: array of sheet objects [{name, headers, rows, style?, theme?, col_widths?, freeze_header?, number_formats?, col_alignments?, merges?, summary_row?, data_validations?, conditional_formats?}]. When present, overrides top-level headers/rows/sheet_name.", Items = new() { Type = "object" } },
|
||||
},
|
||||
Required = []
|
||||
};
|
||||
@@ -185,10 +186,11 @@ public class ExcelSkill : IAgentTool
|
||||
var summaryArg = args.SafeTryGetProperty("summary_row", out var sumEl) ? sumEl : default;
|
||||
var mergesArg = args.SafeTryGetProperty("merges", out var mergeEl) ? mergeEl : default;
|
||||
var validationsArg = args.SafeTryGetProperty("data_validations", out var validationsEl) ? validationsEl : default;
|
||||
var conditionalFormatsArg = args.SafeTryGetProperty("conditional_formats", out var conditionalFormatsEl) ? conditionalFormatsEl : default;
|
||||
|
||||
var (rowCount, validationCount) = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
var (rowCount, validationCount, conditionalFormattingCount) = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
isStyled, freezeHeader, theme, numFmts, alignments, customFmts,
|
||||
summaryArg, mergesArg, validationsArg, colCount);
|
||||
summaryArg, mergesArg, validationsArg, conditionalFormatsArg, colCount);
|
||||
|
||||
var wbSheets = workbookPart.Workbook.AppendChild(new Sheets());
|
||||
wbSheets.Append(new Sheet
|
||||
@@ -212,6 +214,7 @@ public class ExcelSkill : IAgentTool
|
||||
CountFormulaCells(rows),
|
||||
0,
|
||||
validationCount,
|
||||
conditionalFormattingCount,
|
||||
false,
|
||||
false,
|
||||
summaryArg.ValueKind == JsonValueKind.Object));
|
||||
@@ -273,9 +276,10 @@ public class ExcelSkill : IAgentTool
|
||||
var summaryArg = args.SafeTryGetProperty("summary_row", out var sumEl) ? sumEl : default;
|
||||
var mergesArg = args.SafeTryGetProperty("merges", out var mergeEl) ? mergeEl : default;
|
||||
var validationsArg = args.SafeTryGetProperty("data_validations", out var validationsEl) ? validationsEl : default;
|
||||
var (rowCount, validationCount) = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
var conditionalFormatsArg = args.SafeTryGetProperty("conditional_formats", out var conditionalFormatsEl) ? conditionalFormatsEl : default;
|
||||
var (rowCount, validationCount, conditionalFormattingCount) = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
isStyled, freezeHeader, theme, numFmts, alignments, customFmts,
|
||||
summaryArg, mergesArg, validationsArg, colCount);
|
||||
summaryArg, mergesArg, validationsArg, conditionalFormatsArg, colCount);
|
||||
|
||||
wbSheets.Append(new Sheet
|
||||
{
|
||||
@@ -298,6 +302,7 @@ public class ExcelSkill : IAgentTool
|
||||
CountFormulaCells(rows),
|
||||
1,
|
||||
validationCount,
|
||||
conditionalFormattingCount,
|
||||
true,
|
||||
HasSummaryItems(summarySheet, "highlights"),
|
||||
HasSummaryItems(summarySheet, "actions")));
|
||||
@@ -343,6 +348,7 @@ public class ExcelSkill : IAgentTool
|
||||
var totalRows = 0;
|
||||
var totalFormulaCount = 0;
|
||||
var totalValidationCount = 0;
|
||||
var totalConditionalFormattingCount = 0;
|
||||
var detailSheetNames = new List<string>();
|
||||
|
||||
foreach (var sheetDef in sheetsArr.EnumerateArray())
|
||||
@@ -386,13 +392,14 @@ public class ExcelSkill : IAgentTool
|
||||
var summaryArg = sheetDef.SafeTryGetProperty("summary_row", out var sumEl) ? sumEl : default;
|
||||
var mergesArg = sheetDef.SafeTryGetProperty("merges", out var mergeEl) ? mergeEl : default;
|
||||
var validationsArg = sheetDef.SafeTryGetProperty("data_validations", out var validationsEl) ? validationsEl : default;
|
||||
var conditionalFormatsArg = sheetDef.SafeTryGetProperty("conditional_formats", out var conditionalFormatsEl) ? conditionalFormatsEl : default;
|
||||
|
||||
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
|
||||
worksheetPart.Worksheet = new Worksheet();
|
||||
|
||||
var (rowCount, validationCount) = WriteSheetContent(worksheetPart, sheetDef, sheetName, headers, rows,
|
||||
var (rowCount, validationCount, conditionalFormattingCount) = WriteSheetContent(worksheetPart, sheetDef, sheetName, headers, rows,
|
||||
isStyled, freezeHeader, theme, numFmts, alignments, combinedCustomFmts,
|
||||
summaryArg, mergesArg, validationsArg, colCount);
|
||||
summaryArg, mergesArg, validationsArg, conditionalFormatsArg, colCount);
|
||||
|
||||
wbSheets.Append(new Sheet
|
||||
{
|
||||
@@ -406,6 +413,7 @@ public class ExcelSkill : IAgentTool
|
||||
totalRows += rowCount;
|
||||
totalFormulaCount += CountFormulaCells(rows);
|
||||
totalValidationCount += validationCount;
|
||||
totalConditionalFormattingCount += conditionalFormattingCount;
|
||||
}
|
||||
|
||||
workbookPart.Workbook.Save();
|
||||
@@ -417,6 +425,7 @@ public class ExcelSkill : IAgentTool
|
||||
totalFormulaCount,
|
||||
summarySheet.ValueKind == JsonValueKind.Object ? detailSheetNames.Count : 0,
|
||||
totalValidationCount,
|
||||
totalConditionalFormattingCount,
|
||||
summarySheet.ValueKind == JsonValueKind.Object,
|
||||
HasSummaryItems(summarySheet, "highlights"),
|
||||
HasSummaryItems(summarySheet, "actions")));
|
||||
@@ -551,7 +560,7 @@ public class ExcelSkill : IAgentTool
|
||||
};
|
||||
}
|
||||
|
||||
private static (int RowCount, int ValidationCount) WriteSheetContent(
|
||||
private static (int RowCount, int ValidationCount, int ConditionalFormattingCount) WriteSheetContent(
|
||||
WorksheetPart worksheetPart,
|
||||
JsonElement args,
|
||||
string sheetName,
|
||||
@@ -566,6 +575,7 @@ public class ExcelSkill : IAgentTool
|
||||
JsonElement summaryArg,
|
||||
JsonElement mergesArg,
|
||||
JsonElement validationsArg,
|
||||
JsonElement conditionalFormatsArg,
|
||||
int colCount)
|
||||
{
|
||||
// Column widths
|
||||
@@ -659,6 +669,7 @@ public class ExcelSkill : IAgentTool
|
||||
}
|
||||
|
||||
var validationCount = AddDataValidations(worksheetPart, sheetData, mergeCellsSection, validationsArg);
|
||||
var conditionalFormattingCount = AddConditionalFormats(worksheetPart, mergeCellsSection, conditionalFormatsArg);
|
||||
|
||||
// Freeze header
|
||||
if (freezeHeader)
|
||||
@@ -684,7 +695,7 @@ public class ExcelSkill : IAgentTool
|
||||
worksheetPart.Worksheet.InsertBefore(sheetViews, insertBefore);
|
||||
}
|
||||
|
||||
return (rowCount, validationCount);
|
||||
return (rowCount, validationCount, conditionalFormattingCount);
|
||||
}
|
||||
|
||||
private static int AddDataValidations(WorksheetPart worksheetPart, SheetData sheetData, MergeCells? mergeCells, JsonElement validationsArg)
|
||||
@@ -731,6 +742,97 @@ public class ExcelSkill : IAgentTool
|
||||
return count;
|
||||
}
|
||||
|
||||
private static int AddConditionalFormats(WorksheetPart worksheetPart, MergeCells? mergeCells, JsonElement conditionalFormatsArg)
|
||||
{
|
||||
if (conditionalFormatsArg.ValueKind != JsonValueKind.Array || conditionalFormatsArg.GetArrayLength() == 0)
|
||||
return 0;
|
||||
|
||||
var insertedCount = 0;
|
||||
OpenXmlElement anchor = mergeCells is not null
|
||||
? mergeCells
|
||||
: worksheetPart.Worksheet.Elements<SheetData>().First();
|
||||
|
||||
foreach (var rule in conditionalFormatsArg.EnumerateArray())
|
||||
{
|
||||
var range = rule.SafeTryGetProperty("range", out var rangeEl) ? rangeEl.SafeGetString() : null;
|
||||
var type = rule.SafeTryGetProperty("type", out var typeEl) ? typeEl.SafeGetString()?.Trim().ToLowerInvariant() : null;
|
||||
if (string.IsNullOrWhiteSpace(range) || string.IsNullOrWhiteSpace(type))
|
||||
continue;
|
||||
|
||||
ConditionalFormatting? conditionalFormatting = type switch
|
||||
{
|
||||
"color_scale" => BuildColorScaleConditionalFormatting(range, rule, (uint)(insertedCount + 1)),
|
||||
"data_bar" => BuildDataBarConditionalFormatting(range, rule, (uint)(insertedCount + 1)),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
if (conditionalFormatting == null)
|
||||
continue;
|
||||
|
||||
worksheetPart.Worksheet.InsertAfter(conditionalFormatting, anchor);
|
||||
anchor = conditionalFormatting;
|
||||
insertedCount++;
|
||||
}
|
||||
|
||||
return insertedCount;
|
||||
}
|
||||
|
||||
private static ConditionalFormatting? BuildColorScaleConditionalFormatting(string range, JsonElement rule, uint priority)
|
||||
{
|
||||
var low = rule.SafeTryGetProperty("low", out var lowEl) ? NormalizeHex(lowEl.SafeGetString(), "FEE2E2") : "FEE2E2";
|
||||
var mid = rule.SafeTryGetProperty("mid", out var midEl) ? NormalizeHex(midEl.SafeGetString(), "FEF3C7") : "FEF3C7";
|
||||
var high = rule.SafeTryGetProperty("high", out var highEl) ? NormalizeHex(highEl.SafeGetString(), "DCFCE7") : "DCFCE7";
|
||||
|
||||
var ruleElement = new ConditionalFormattingRule
|
||||
{
|
||||
Type = ConditionalFormatValues.ColorScale,
|
||||
Priority = (int)priority,
|
||||
};
|
||||
ruleElement.Append(new ColorScale(
|
||||
new ConditionalFormatValueObject { Type = ConditionalFormatValueObjectValues.Min },
|
||||
new ConditionalFormatValueObject { Type = ConditionalFormatValueObjectValues.Percentile, Val = "50" },
|
||||
new ConditionalFormatValueObject { Type = ConditionalFormatValueObjectValues.Max },
|
||||
new Color { Rgb = low },
|
||||
new Color { Rgb = mid },
|
||||
new Color { Rgb = high }));
|
||||
|
||||
return new ConditionalFormatting(ruleElement)
|
||||
{
|
||||
SequenceOfReferences = new ListValue<StringValue> { InnerText = range }
|
||||
};
|
||||
}
|
||||
|
||||
private static ConditionalFormatting? BuildDataBarConditionalFormatting(string range, JsonElement rule, uint priority)
|
||||
{
|
||||
var color = rule.SafeTryGetProperty("color", out var colorEl) ? NormalizeHex(colorEl.SafeGetString(), "2563EB") : "2563EB";
|
||||
|
||||
var ruleElement = new ConditionalFormattingRule
|
||||
{
|
||||
Type = ConditionalFormatValues.DataBar,
|
||||
Priority = (int)priority,
|
||||
};
|
||||
ruleElement.Append(new DataBar(
|
||||
new ConditionalFormatValueObject { Type = ConditionalFormatValueObjectValues.Min },
|
||||
new ConditionalFormatValueObject { Type = ConditionalFormatValueObjectValues.Max },
|
||||
new Color { Rgb = color }));
|
||||
|
||||
return new ConditionalFormatting(ruleElement)
|
||||
{
|
||||
SequenceOfReferences = new ListValue<StringValue> { InnerText = range }
|
||||
};
|
||||
}
|
||||
|
||||
private static string NormalizeHex(string? color, string fallback)
|
||||
{
|
||||
var value = string.IsNullOrWhiteSpace(color) ? fallback : color.Trim().TrimStart('#');
|
||||
return value.Length switch
|
||||
{
|
||||
6 => "FF" + value.ToUpperInvariant(),
|
||||
8 => value.ToUpperInvariant(),
|
||||
_ => fallback,
|
||||
};
|
||||
}
|
||||
|
||||
private static DataValidationValues ResolveValidationType(string? type)
|
||||
{
|
||||
return (type ?? "list").Trim().ToLowerInvariant() switch
|
||||
|
||||
Reference in New Issue
Block a user