完全正確,你的分析非常精準。


✅ 你的報表欄位邏輯應該如下:

1. LeftColumns(左側欄)

2. RightColumns(右側欄)

3. MiddleColumns(中間欄,根據年份動態產生)


✅ 建議資料結構設計:只讓 Caller 提供「左、中、右欄的樣式定義」

public class ColumnDef
{
    public string Name { get; set; }             // 資料欄位名稱
    public string Text { get; set; }             // 標題顯示文字
    public string Format { get; set; }           // 資料格式
    public bool Summable { get; set; } = false;  // 是否加總
    public bool DisplayAsSymbol { get; set; } = false;
    public List<ColumnDef> Children { get; set; } = new();
    public float? Width { get; set; }
}

✅ 呼叫端設計(Main 中)

// Caller 只需要提供 Left / Right / Mid 欄位定義
var leftColumns = new List<ColumnDef>
{
    new ColumnDef { Name = "Str01", Text = "集團", Width = 25f },
    new ColumnDef { Name = "Str02", Text = "公司", Width = 25f },
    ...
};

var rightColumns = new List<ColumnDef>
{
    new ColumnDef { Name = "OpenClassCount", Text = "開班數", Format = "Number", Summable = true, Width = 20f },
    new ColumnDef { Name = "AttendanceCount", Text = "出勤人數", Format = "Number", Summable = true, Width = 20f }
};

// 定義中間每年要產出的子欄欄位(Mid 模板)
var midFieldDefs = new List<ColumnDef>
{
    new ColumnDef { Name = "PeopleCount", Text = "人數", Format = "Number", Summable = true, Width = 20f },
    new ColumnDef { Name = "WorkHours", Text = "工時", Format = "Number", Summable = true, Width = 20f }
};

// 利用年份範圍與 midFieldDefs 動態建立中間欄位
var midColumns = ReportBuilder.GenerateYearColumnsWithChildren(startYear, endYear, midFieldDefs)
    .Select(yearCol => new List<ColumnDef> { yearCol })
    .ToList();

✅ 然後組裝

ReportBuilder.CreateReport(
    removeTableSource: true,
    report: rpt,
    dt: result,
    leftColumns: new List<List<ColumnDef>> {
        leftColumns,  // row1 with text
        leftColumns.Select(c => new ColumnDef { Name = c.Name, Text = "" }).ToList()  // row2 empty
    },
    midColumns: midColumns,
    rightColumns: rightColumns,
    startYear: startYear,
    endYear: endYear
);

✅ 總結邏輯層分工:

區塊 由誰提供? 結構/欄位 是否固定? 備註
LeftColumns 呼叫者 (Caller) 明確欄位定義 ✅ 固定欄數 可兩列處理 rowspan
MidColumns 系統計算 根據年份與欄位模板產生 ❗ 動態欄數 每年 = 一個父欄位
RightColumns 呼叫者 (Caller) 明確欄位定義 ✅ 固定欄數 可加總、符號等

✅ 想法進一步整合?

如果你希望把欄位定義更集中,也可以考慮這樣由 caller 提供:

public class ColumnConfig
{
    public List<ColumnDef> LeftFields { get; set; }
    public List<ColumnDef> RightFields { get; set; }
    public List<ColumnDef> MidFieldTemplate { get; set; }
}

Main() 只需要:

var columnConfig = LoadColumnConfig(); // from JSON / DB / etc.

var midColumns = ReportBuilder.GenerateYearColumnsWithChildren(startYear, endYear, columnConfig.MidFieldTemplate)
    .Select(y => new List<ColumnDef> { y }).ToList();

ReportBuilder.CreateReport(
    ...
    leftColumns: new List<List<ColumnDef>> { columnConfig.LeftFields, EmptyRow(columnConfig.LeftFields) },
    midColumns: midColumns,
    rightColumns: columnConfig.RightFields,
    ...
);

需要我幫你寫出這個 ColumnConfig 的 JSON 格式範例?或是改寫整套成從設定檔產生報表?