Skip to content

[Feature] Add Row Factory Support for Flexible Row Generation #832

@mrwangshipei

Description

@mrwangshipei

🚀 [Feature] Add Row Factory Support for Flexible Row Generation

📌 Summary

This PR introduces a Row Factory API to MiniExcel, allowing users to dynamically generate rows with fine-grained control, addressing limitations of the current template-based injection mechanism.

🎯 中文简介:本 PR 引入 行工厂模式(Row Factory),允许开发者以编程方式控制每一行的结构、内容和样式,解决现有模板模式在多表头、重复列名、隐藏行等场景下的局限性。


✅ Motivation

Currently, MiniExcel relies on traversing List or Dictionary to inject data into templates. This is simple and fast, but not suitable for:

  • Creating multiple header rows with partial visibility (e.g., hiding index row)
  • Handling duplicate column names (Dictionary keys must be unique)
  • Implementing complex row layout, such as merged cells or conditional formatting
  • Supporting streaming large datasets with lazy row generation

🧩 Proposed API

A new overload for SaveAs or similar method:

MiniExcel.SaveAs("file.xlsx", rowFactory, config);

Where rowFactory is defined as:

Func<int, RowContext, MiniExcelRow> rowFactory = (rowIndex, ctx) =>
{
    return new MiniExcelRow
    {
        Cells = new[] { "Index" + rowIndex, "Name", "Age" },
        IsHidden = rowIndex == 0
    };
};

🌟 Advantages

Feature Benefit
🎭 Dynamic content Vary structure and style per row
💨 Streaming Factory pattern supports deferred execution
🎨 Style control Apply conditional formats, custom fonts, merges, etc.

🛠️ Implementation Notes

  • MiniExcelRow is a new internal DTO containing:
    • object[] Cells
    • bool IsHidden
    • (Optionally) CellStyle[] Styles, int MergeAcross, etc.
  • Existing injection logic remains unchanged
  • Backward compatible — opt-in feature

🧪 Example Use Case

Generate hidden index row + repeated column names:

Hidden Row A B C
Index Row 1 2 3
Header Row 姓名 姓名 年龄
Func<int, RowContext, MiniExcelRow> rowFactory = (i, ctx) =>
{
    if (i == 0) return new MiniExcelRow { Cells = new[] { "1", "2", "3" }, IsHidden = true };
    if (i == 1) return new MiniExcelRow { Cells = new[] { "姓名", "姓名", "年龄" } };
    return new MiniExcelRow { Cells = new[] { "张三", "李四", 18 } };
};

🔄 Compatibility

  • ✅ No breaking changes
  • ✅ Can co-exist with template and dictionary modes
  • ✅ Easily unit-testable and extensible

📎 References


Thanks for reviewing!
If you think this should live under a separate namespace or extension method set, happy to adapt the structure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions