?? ??? 3?? DOCX ????XLSX ?? ???HTML ???? ?? ??
- DocumentAssemblerTool? template_path/page_numbers? ??? DOCX ??? ??, ??????????? ?? ??? ?? - ExcelSkill? data_validations? ???? ??/??/?? ?? ??? ?? ??? ?? ?? ?? ?? - HtmlSkill? ArtifactQualityReviewService? decision_summary/evidence_cards ??? ?? ?? ?? ??? ?? - DocumentAssemblerDocxFeaturesTests, HtmlSkillConsultingSectionsTests, ExcelSkillDataValidationTests? ?? ??? ?? - README.md? docs/DEVELOPMENT.md? 2026-04-14 22:28 (KST) ???? ?? ??: - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_doc_phase_next\\ -p:IntermediateOutputPath=obj\\verify_doc_phase_next\\ (?? 0 / ?? 0) - dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "DocumentAssemblerDocxFeaturesTests|DocumentAssemblerSemanticTests|DocumentPlannerWorkbookScaffoldTests|ExcelSkillExecutiveSummaryLinkTests|ExcelSkillSummarySheetTests|ExcelSkillDataValidationTests|HtmlSkillConsultingSectionsTests|DocxSkillTemplateFeaturesTests|DocumentPlannerBusinessDocumentTests" -p:OutputPath=bin\\verify_doc_phase_next_tests\\ -p:IntermediateOutputPath=obj\\verify_doc_phase_next_tests\\ (?? 9)
This commit is contained in:
@@ -42,8 +42,9 @@ public class ExcelSkill : IAgentTool
|
||||
"Example: {\"name\":\"Summary\",\"title\":\"2026 운영 리뷰\",\"subtitle\":\"핵심 KPI와 후속 과제\",\"kpis\":[{\"label\":\"Revenue\",\"value\":\"12%\",\"trend\":\"YoY\",\"note\":\"Strong\"}],\"highlights\":[\"핵심 인사이트 1\",\"핵심 인사이트 2\"],\"actions\":[\"즉시 과제 1\",\"즉시 과제 2\"]}"
|
||||
},
|
||||
["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" } },
|
||||
["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?}]. 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?}]. When present, overrides top-level headers/rows/sheet_name.", Items = new() { Type = "object" } },
|
||||
},
|
||||
Required = []
|
||||
};
|
||||
@@ -183,10 +184,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 rowCount = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
var (rowCount, validationCount) = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
isStyled, freezeHeader, theme, numFmts, alignments, customFmts,
|
||||
summaryArg, mergesArg, colCount);
|
||||
summaryArg, mergesArg, validationsArg, colCount);
|
||||
|
||||
var wbSheets = workbookPart.Workbook.AppendChild(new Sheets());
|
||||
wbSheets.Append(new Sheet
|
||||
@@ -209,7 +211,7 @@ public class ExcelSkill : IAgentTool
|
||||
rowCount,
|
||||
CountFormulaCells(rows),
|
||||
0,
|
||||
0,
|
||||
validationCount,
|
||||
false,
|
||||
false,
|
||||
summaryArg.ValueKind == JsonValueKind.Object));
|
||||
@@ -270,9 +272,10 @@ public class ExcelSkill : IAgentTool
|
||||
var colCount = headers.GetArrayLength();
|
||||
var summaryArg = args.SafeTryGetProperty("summary_row", out var sumEl) ? sumEl : default;
|
||||
var mergesArg = args.SafeTryGetProperty("merges", out var mergeEl) ? mergeEl : default;
|
||||
var rowCount = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
var validationsArg = args.SafeTryGetProperty("data_validations", out var validationsEl) ? validationsEl : default;
|
||||
var (rowCount, validationCount) = WriteSheetContent(worksheetPart, args, sheetName, headers, rows,
|
||||
isStyled, freezeHeader, theme, numFmts, alignments, customFmts,
|
||||
summaryArg, mergesArg, colCount);
|
||||
summaryArg, mergesArg, validationsArg, colCount);
|
||||
|
||||
wbSheets.Append(new Sheet
|
||||
{
|
||||
@@ -294,7 +297,7 @@ public class ExcelSkill : IAgentTool
|
||||
rowCount,
|
||||
CountFormulaCells(rows),
|
||||
1,
|
||||
0,
|
||||
validationCount,
|
||||
true,
|
||||
HasSummaryItems(summarySheet, "highlights"),
|
||||
HasSummaryItems(summarySheet, "actions")));
|
||||
@@ -339,6 +342,7 @@ public class ExcelSkill : IAgentTool
|
||||
var totalSheets = 0;
|
||||
var totalRows = 0;
|
||||
var totalFormulaCount = 0;
|
||||
var totalValidationCount = 0;
|
||||
var detailSheetNames = new List<string>();
|
||||
|
||||
foreach (var sheetDef in sheetsArr.EnumerateArray())
|
||||
@@ -381,13 +385,14 @@ public class ExcelSkill : IAgentTool
|
||||
var colCount = headers.GetArrayLength();
|
||||
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 worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
|
||||
worksheetPart.Worksheet = new Worksheet();
|
||||
|
||||
var rowCount = WriteSheetContent(worksheetPart, sheetDef, sheetName, headers, rows,
|
||||
var (rowCount, validationCount) = WriteSheetContent(worksheetPart, sheetDef, sheetName, headers, rows,
|
||||
isStyled, freezeHeader, theme, numFmts, alignments, combinedCustomFmts,
|
||||
summaryArg, mergesArg, colCount);
|
||||
summaryArg, mergesArg, validationsArg, colCount);
|
||||
|
||||
wbSheets.Append(new Sheet
|
||||
{
|
||||
@@ -400,11 +405,23 @@ public class ExcelSkill : IAgentTool
|
||||
totalSheets++;
|
||||
totalRows += rowCount;
|
||||
totalFormulaCount += CountFormulaCells(rows);
|
||||
totalValidationCount += validationCount;
|
||||
}
|
||||
|
||||
workbookPart.Workbook.Save();
|
||||
var review = ArtifactQualityReviewService.ReviewWorkbook(new WorkbookReviewInput(
|
||||
fullPath,
|
||||
totalSheets + (summarySheet.ValueKind == JsonValueKind.Object ? 1 : 0),
|
||||
totalSheets,
|
||||
totalRows,
|
||||
totalFormulaCount,
|
||||
summarySheet.ValueKind == JsonValueKind.Object ? detailSheetNames.Count : 0,
|
||||
totalValidationCount,
|
||||
summarySheet.ValueKind == JsonValueKind.Object,
|
||||
HasSummaryItems(summarySheet, "highlights"),
|
||||
HasSummaryItems(summarySheet, "actions")));
|
||||
return ToolResult.Ok(
|
||||
$"Excel 파일 생성 완료: {fullPath}\n시트: {totalSheets}개, 총 데이터 행: {totalRows}",
|
||||
$"Excel 파일 생성 완료: {fullPath}\n시트: {totalSheets}개, 총 데이터 행: {totalRows}\n{review.ToToolSummary()}",
|
||||
fullPath);
|
||||
}
|
||||
|
||||
@@ -534,7 +551,7 @@ public class ExcelSkill : IAgentTool
|
||||
};
|
||||
}
|
||||
|
||||
private static int WriteSheetContent(
|
||||
private static (int RowCount, int ValidationCount) WriteSheetContent(
|
||||
WorksheetPart worksheetPart,
|
||||
JsonElement args,
|
||||
string sheetName,
|
||||
@@ -548,6 +565,7 @@ public class ExcelSkill : IAgentTool
|
||||
List<(string code, uint id)> customFmtRegistry,
|
||||
JsonElement summaryArg,
|
||||
JsonElement mergesArg,
|
||||
JsonElement validationsArg,
|
||||
int colCount)
|
||||
{
|
||||
// Column widths
|
||||
@@ -626,19 +644,22 @@ public class ExcelSkill : IAgentTool
|
||||
AddSummaryRow(sheetData, summaryArg, rowNum, colCount, rowCount, isStyled);
|
||||
|
||||
// Cell merges
|
||||
MergeCells? mergeCellsSection = null;
|
||||
if (mergesArg.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var mergeCells = new MergeCells();
|
||||
mergeCellsSection = new MergeCells();
|
||||
foreach (var merge in mergesArg.EnumerateArray())
|
||||
{
|
||||
var range = merge.SafeGetString();
|
||||
if (!string.IsNullOrEmpty(range))
|
||||
mergeCells.Append(new MergeCell { Reference = range });
|
||||
mergeCellsSection.Append(new MergeCell { Reference = range });
|
||||
}
|
||||
if (mergeCells.HasChildren)
|
||||
worksheetPart.Worksheet.InsertAfter(mergeCells, sheetData);
|
||||
if (mergeCellsSection.HasChildren)
|
||||
worksheetPart.Worksheet.InsertAfter(mergeCellsSection, sheetData);
|
||||
}
|
||||
|
||||
var validationCount = AddDataValidations(worksheetPart, sheetData, mergeCellsSection, validationsArg);
|
||||
|
||||
// Freeze header
|
||||
if (freezeHeader)
|
||||
{
|
||||
@@ -663,7 +684,64 @@ public class ExcelSkill : IAgentTool
|
||||
worksheetPart.Worksheet.InsertBefore(sheetViews, insertBefore);
|
||||
}
|
||||
|
||||
return rowCount;
|
||||
return (rowCount, validationCount);
|
||||
}
|
||||
|
||||
private static int AddDataValidations(WorksheetPart worksheetPart, SheetData sheetData, MergeCells? mergeCells, JsonElement validationsArg)
|
||||
{
|
||||
if (validationsArg.ValueKind != JsonValueKind.Array || validationsArg.GetArrayLength() == 0)
|
||||
return 0;
|
||||
|
||||
var dataValidations = new DataValidations();
|
||||
var count = 0;
|
||||
|
||||
foreach (var rule in validationsArg.EnumerateArray())
|
||||
{
|
||||
var range = rule.SafeTryGetProperty("range", out var rangeEl) ? rangeEl.SafeGetString() : null;
|
||||
var typeText = rule.SafeTryGetProperty("type", out var typeEl) ? typeEl.SafeGetString() : null;
|
||||
var formula1 = rule.SafeTryGetProperty("formula1", out var formulaEl) ? formulaEl.SafeGetString() : null;
|
||||
if (string.IsNullOrWhiteSpace(range) || string.IsNullOrWhiteSpace(typeText) || string.IsNullOrWhiteSpace(formula1))
|
||||
continue;
|
||||
|
||||
var validation = new DataValidation
|
||||
{
|
||||
Type = ResolveValidationType(typeText),
|
||||
AllowBlank = !(rule.SafeTryGetProperty("allow_blank", out var allowBlankEl) && allowBlankEl.ValueKind == JsonValueKind.False),
|
||||
ShowInputMessage = rule.SafeTryGetProperty("prompt", out _),
|
||||
SequenceOfReferences = new ListValue<StringValue> { InnerText = range }
|
||||
};
|
||||
|
||||
if (rule.SafeTryGetProperty("prompt", out var promptEl) && !string.IsNullOrWhiteSpace(promptEl.SafeGetString()))
|
||||
{
|
||||
validation.PromptTitle = "Input";
|
||||
validation.Prompt = promptEl.SafeGetString();
|
||||
}
|
||||
|
||||
validation.Append(new Formula1(formula1));
|
||||
dataValidations.Append(validation);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
dataValidations.Count = (uint)count;
|
||||
var anchor = (OpenXmlElement?)mergeCells ?? sheetData;
|
||||
worksheetPart.Worksheet.InsertAfter(dataValidations, anchor);
|
||||
return count;
|
||||
}
|
||||
|
||||
private static DataValidationValues ResolveValidationType(string? type)
|
||||
{
|
||||
return (type ?? "list").Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"whole" or "whole_number" => DataValidationValues.Whole,
|
||||
"decimal" => DataValidationValues.Decimal,
|
||||
"date" => DataValidationValues.Date,
|
||||
"text_length" => DataValidationValues.TextLength,
|
||||
"custom" => DataValidationValues.Custom,
|
||||
_ => DataValidationValues.List,
|
||||
};
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user