NPOI导出Excel自适应行高
开发环境:.Net Core 3.1,NPOI 2.6.0
功能需求:导出的Excel的内容要自适应行高。
请注意:这里的自适应行高处理方案,仅仅是为了解决当有合并列单元格的时候,会导致的excel自适应高度失效,如果你没有合并列单元格,直接使用sheet1.AutoSizeRow(1);。
同理,你想解决非合并行自适应宽度问题,也可以使用sheet1.AutoSizeColumn(1);不过要先设置单元格自动换行与自适应行高,如下图。
如果有合并情况,这个auto函数就会失效就需要以下的方式来实现。
先看模板,这是一张质量检测报告单,打码部分属于其他敏感数据。
最终效果
需求分析:一顿网上查找“NPOI导出Excel自适应行高”,都是片段代码,很多参数不明,但是也提供了不错的思路,这里博主整理一下。
之前博主是在给行数据绑定值的时候,算字符串的长度,来决定行高,但是字符串中的汉字、字母和数字,以及符号、合并单元格列宽等因素,行高计算的实在不准。
重新整理思路,决定等Excel绑定值后,最后统一处理Excel内容。
解决方案:1.修正模板 2.自适应行高
首先,当前单元格或者整行,要设置成自动换行,如 wps下图
然后,待Excel绑定值后,开始处理自适应行高,代码内有的方法是来自Excel帮助类,参考 2.构建Excel帮助类 - 0Behavior - 博客园 (cnblogs.com)
1 //自适应高度,9代表从第10行开始,表头部分不会多行;endRow是结束的行,也就是有数据内容的行数,毕竟没内容的单元格,也没必要自适应行高 2 for (int i = 9; i < endRow; i++) 3 { 4 if (ws.GetRow(i) == null) 5 { 6 continue; 7 } 8 IRow ICurRow = ws.GetRow(i); 9 int OldHg = ICurRow.Height;//当前行高 10 int newHg = ICurRow.Height;//新行高,默认与当前行高一致 11 int j = 0;//第一列 12 while (j < excelNum2Digit("X"))//excelNum2Digit是获取下标的帮助方法,这里是到X列就终止了 13 { 14 if (ICurRow.GetCell(j) == null) 15 { 16 continue; 17 } 18 ICell CurCell = ICurRow.GetCell(j); 19 int lastCol = GetLastCol(ws, i, j);//获取合并行最后列的下标 20 if (CurCell.CellType == CellType.String && !string.IsNullOrEmpty(CurCell.StringCellValue)) 21 { 22 int cellWidth = 0;//当前单元格或者合并单元格的总宽度,此属性可以帮助计算不同字体大小的汉字或字母的宽度 23 if (CurCell.IsMergedCell)//计算出合并单元格的实际宽度 24 { 25 for (int f1 = 0; f1 <= lastCol - j; f1++) 26 { 27 cellWidth += ICurRow.Sheet.GetColumnWidth(j + f1); 28 } 29 } 30 else 31 { 32 cellWidth = ICurRow.Sheet.GetColumnWidth(j); 33 } 34 int cellStringLength = GetCellStringLength(CurCell.StringCellValue);//计算出字符串内容实际宽度 35 if (cellStringLength > cellWidth) 36 { 37 short newHg1 = (short)(OldHg * 38 (cellStringLength / cellWidth + 1)); 39 if (newHg1 > newHg) 40 { 41 newHg = newHg1; 42 } 43 } 44 } 45 if (CurCell.IsMergedCell) 46 { 47 j = lastCol + 1; 48 } 49 else 50 { 51 j++; 52 } 53 } 54 if (OldHg < newHg) 55 { 56 ICurRow.Height = Convert.ToInt16(newHg); 57 } 58 }
1 /// <summary> 2 /// 计算单元格内容长度 3 /// 用 ASCII 码范围判断字符是不是汉字 4 /// </summary> 5 /// <param name="text">待判断字符或字符串</param> 6 /// <returns>宽度</returns> 7 public int GetCellStringLength(string text) 8 { 9 //汉字 453、数字和字母 239 10 //这里的汉字与字母的宽度值,要根据Excel的字体大小计算 11 //例如你单元格宽度1000,能放10个汉字,那汉字宽度就是1000/10=100 12 //同理计算字母宽度 13 int result = 0; 14 foreach (char t in text) 15 { 16 if(t==10) 17 { 18 //忽略字符串中的换行符\n 19 continue; 20 } 21 else if (t > 127) 22 { 23 result += 453; 24 } 25 else 26 { 27 result += 239; 28 } 29 } 30 return result; 31 }