mymx2 commented on issue #114: URL: https://github.com/apache/fesod/issues/114#issuecomment-3755560355
我想这应该能通过简单的方法直接用,不过官方支持也是不错的。 https://pl.kotl.in/aRZwkOViC <details> <summary>demo</summary> ```kotlin import kotlin.reflect.KProperty1 /** Excel 合并单元格范围 */ data class MergeRange(val firstRow: Int, val lastRow: Int, val firstCol: Int, val lastCol: Int) /** Excel 列定义 */ data class MergeColumn<T>(val prop: KProperty1<T, *>, val index: Int, val merge: Boolean = false) /** Excel 合并单元格 */ object ExcelMergeMapper { /** * 根据 key 分组 + 列值相等计算纵向合并区间 * * @param startRow Excel 起始行(含表头偏移) * @param data 已排序的数据 * @param keySelector 分组 key 提取函数 * @param columns 需要参与合并的列 */ @Suppress("detekt:NestedBlockDepth") fun <T> verticalMerges( startRow: Int, data: List<T>, keySelector: (T) -> Any, columns: List<MergeColumn<T>>, ): List<MergeRange> { if (data.isEmpty()) return emptyList() val mergeCols = columns.filter { it.merge } if (mergeCols.isEmpty()) return emptyList() val result = mutableListOf<MergeRange>() var groupStart = 0 for (i in 1..data.size) { val isGroupEnd = i == data.size || keySelector(data[i]) != keySelector(data[groupStart]) if (isGroupEnd) { // 当前 key 分组范围是 groupStart..i-1 val groupData = data.subList(groupStart, i) // 对每列独立计算值相等的纵向合并 mergeCols.forEach { col -> var valStart = 0 for (j in 1..groupData.size) { val isValEnd = j == groupData.size || col.prop.get(groupData[j]) != col.prop.get(groupData[valStart]) if (isValEnd) { val size = j - valStart if (size > 1) { val firstRow = startRow + groupStart + valStart val lastRow = startRow + groupStart + j - 1 result += MergeRange(firstRow, lastRow, col.index, col.index) } valStart = j } } } groupStart = i } } return result } } data class Person(val id: Int, val name: String, val dept: String) fun main() { val rawData = listOf( Person(1, "Alice", "HR"), Person(1, "Alice", "HR"), Person(2, "Bob", "HR"), Person(2, "Bob", "IT"), Person(2, "Bob", "IT"), Person(3, "Charlie", "IT"), Person(3, "Charlie", "HR"), // dept 不相等,不会合并 ) .sortedBy { it.id } val merges = ExcelMergeMapper.verticalMerges( startRow = 1, data = rawData, keySelector = Person::id, columns = listOf( MergeColumn(Person::name, index = 0, merge = true), MergeColumn(Person::dept, index = 1, merge = true), ), ) merges.forEach { println(it) } } ``` </details> -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
