[Feature] Add Row Factory Support for Flexible Row Generation
🚀 [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
-
MiniExcelRowis 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
- [Issue: Multiple Header Rows with Hidden Index Mapping](https://github.com/mini-software/MiniExcel/issues/831)
- 表格自动向下填充新行 https://gitee.com/dotnetchina/MiniExcel/issues/ICJV59
Thanks for reviewing!
If you think this should live under a separate namespace or extension method set, happy to adapt the structure.
Thank you for the very detailed useful proposal. We are in the process of restructuring the codebase but we'll take this into consideration as soon as we can!