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         }
posted @ 2023-06-07 10:08  0Behavior  阅读(2052)  评论(0编辑  收藏  举报