zoukankan      html  css  js  c++  java
  • NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)

    因工作需要用到跨合并单元格获取数据,所以写了个NPOI扩展类。

    主要方法如下:

    1.判断指定行/列索引(单元格)是否为合并单元格。

    2.获取指定列索引的实际含有数据的单元格。

    3.返回指定行/列索引的上一个实际含有数据的行。

    4.返回指定行/列索引的下一个实际含有数据的行。

    5.返回指定行/列索引的上一个实际含有数据的单元格。

    6.返回指定行/列索引的下一个实际含有数据的单元格。

      1 namespace NPOI
      2 {
      3     /// <summary>
      4     /// 表示单元格的维度,通常用于表达合并单元格的维度
      5     /// </summary>
      6     public struct Dimension
      7     {
      8         /// <summary>
      9         /// 含有数据的单元格(通常表示合并单元格的第一个跨度行第一个跨度列),该字段可能为null
     10         /// </summary>
     11         public ICell DataCell;
     12 
     13         /// <summary>
     14         /// 行跨度(跨越了多少行)
     15         /// </summary>
     16         public int RowSpan;
     17 
     18         /// <summary>
     19         /// 列跨度(跨越了多少列)
     20         /// </summary>
     21         public int ColumnSpan;
     22 
     23         /// <summary>
     24         /// 合并单元格的起始行索引
     25         /// </summary>
     26         public int FirstRowIndex;
     27 
     28         /// <summary>
     29         /// 合并单元格的结束行索引
     30         /// </summary>
     31         public int LastRowIndex;
     32 
     33         /// <summary>
     34         /// 合并单元格的起始列索引
     35         /// </summary>
     36         public int FirstColumnIndex;
     37 
     38         /// <summary>
     39         /// 合并单元格的结束列索引
     40         /// </summary>
     41         public int LastColumnIndex;
     42     }
     43 
     44     public static class ExcelExtension
     45     {
     46         /// <summary>
     47         /// 判断指定行列所在的单元格是否为合并单元格,并且输出该单元格的维度
     48         /// </summary>
     49         /// <param name="sheet">Excel工作表</param>
     50         /// <param name="rowIndex">行索引,从0开始</param>
     51         /// <param name="columnIndex">列索引,从0开始</param>
     52         /// <param name="dimension">单元格维度</param>
     53         /// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
     54         public static bool IsMergeCell(this ISheet sheet, int rowIndex, int columnIndex, out Dimension dimension)
     55         {
     56             dimension = new Dimension
     57             {
     58                 DataCell = null,
     59                 RowSpan = 1,
     60                 ColumnSpan = 1,
     61                 FirstRowIndex = rowIndex,
     62                 LastRowIndex = rowIndex,
     63                 FirstColumnIndex = columnIndex,
     64                 LastColumnIndex = columnIndex
     65             };
     66 
     67             for (int i = 0; i < sheet.NumMergedRegions; i++)
     68             {
     69                 CellRangeAddress range = sheet.GetMergedRegion(i);
     70                 sheet.IsMergedRegion(range);
     71 
     72                 //这种算法只有当指定行列索引刚好是合并单元格的第一个跨度行第一个跨度列时才能取得合并单元格的跨度
     73                 //if (range.FirstRow == rowIndex && range.FirstColumn == columnIndex)
     74                 //{
     75                 //    dimension.DataCell = sheet.GetRow(range.FirstRow).GetCell(range.FirstColumn);
     76                 //    dimension.RowSpan = range.LastRow - range.FirstRow + 1;
     77                 //    dimension.ColumnSpan = range.LastColumn - range.FirstColumn + 1;
     78                 //    dimension.FirstRowIndex = range.FirstRow;
     79                 //    dimension.LastRowIndex = range.LastRow;
     80                 //    dimension.FirstColumnIndex = range.FirstColumn;
     81                 //    dimension.LastColumnIndex = range.LastColumn;
     82                 //    break;
     83                 //}
     84 
     85                 if ((rowIndex >= range.FirstRow && range.LastRow >= rowIndex) && (columnIndex >= range.FirstColumn && range.LastColumn >= columnIndex))
     86                 {
     87                     dimension.DataCell = sheet.GetRow(range.FirstRow).GetCell(range.FirstColumn);
     88                     dimension.RowSpan = range.LastRow - range.FirstRow + 1;
     89                     dimension.ColumnSpan = range.LastColumn - range.FirstColumn + 1;
     90                     dimension.FirstRowIndex = range.FirstRow;
     91                     dimension.LastRowIndex = range.LastRow;
     92                     dimension.FirstColumnIndex = range.FirstColumn;
     93                     dimension.LastColumnIndex = range.LastColumn;
     94                     break;
     95                 }
     96             }
     97 
     98             bool result;
     99             if (rowIndex >= 0 && sheet.LastRowNum > rowIndex)
    100             {
    101                 IRow row = sheet.GetRow(rowIndex);
    102                 if (columnIndex >= 0 && row.LastCellNum > columnIndex)
    103                 {
    104                     ICell cell = row.GetCell(columnIndex);
    105                     result = cell.IsMergedCell;
    106 
    107                     if (dimension.DataCell == null)
    108                     {
    109                         dimension.DataCell = cell;
    110                     }
    111                 }
    112                 else
    113                 {
    114                     result = false;
    115                 }
    116             }
    117             else
    118             {
    119                 result = false;
    120             }
    121 
    122             return result;
    123         }
    124 
    125         /// <summary>
    126         /// 判断指定行列所在的单元格是否为合并单元格,并且输出该单元格的行列跨度
    127         /// </summary>
    128         /// <param name="sheet">Excel工作表</param>
    129         /// <param name="rowIndex">行索引,从0开始</param>
    130         /// <param name="columnIndex">列索引,从0开始</param>
    131         /// <param name="rowSpan">行跨度,返回值最小为1,同时表示没有行合并</param>
    132         /// <param name="columnSpan">列跨度,返回值最小为1,同时表示没有列合并</param>
    133         /// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
    134         public static bool IsMergeCell(this ISheet sheet, int rowIndex, int columnIndex, out int rowSpan, out int columnSpan)
    135         {
    136             Dimension dimension;
    137             bool result = sheet.IsMergeCell(rowIndex, columnIndex, out dimension);
    138 
    139             rowSpan = dimension.RowSpan;
    140             columnSpan = dimension.ColumnSpan;
    141 
    142             return result;
    143         }
    144 
    145         /// <summary>
    146         /// 判断指定单元格是否为合并单元格,并且输出该单元格的维度
    147         /// </summary>
    148         /// <param name="cell">单元格</param>
    149         /// <param name="dimension">单元格维度</param>
    150         /// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
    151         public static bool IsMergeCell(this ICell cell, out Dimension dimension)
    152         {
    153             return cell.Sheet.IsMergeCell(cell.RowIndex, cell.ColumnIndex, out dimension);
    154         }
    155 
    156         /// <summary>
    157         /// 判断指定单元格是否为合并单元格,并且输出该单元格的行列跨度
    158         /// </summary>
    159         /// <param name="cell">单元格</param>
    160         /// <param name="rowSpan">行跨度,返回值最小为1,同时表示没有行合并</param>
    161         /// <param name="columnSpan">列跨度,返回值最小为1,同时表示没有列合并</param>
    162         /// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
    163         public static bool IsMergeCell(this ICell cell, out int rowSpan, out int columnSpan)
    164         {
    165             return cell.Sheet.IsMergeCell(cell.RowIndex, cell.ColumnIndex, out rowSpan, out columnSpan);
    166         }
    167 
    168         /// <summary>
    169         /// 返回上一个跨度行,如果rowIndex为第一行,则返回null
    170         /// </summary>
    171         /// <param name="sheet">Excel工作表</param>
    172         /// <param name="rowIndex">行索引,从0开始</param>
    173         /// <param name="columnIndex">列索引,从0开始</param>
    174         /// <returns>返回上一个跨度行</returns>
    175         public static IRow PrevSpanRow(this ISheet sheet, int rowIndex, int columnIndex)
    176         {
    177             return sheet.FuncSheet(rowIndex, columnIndex, (currentDimension, isMerge) =>
    178             {
    179                 //上一个单元格维度
    180                 Dimension prevDimension;
    181                 sheet.IsMergeCell(currentDimension.FirstRowIndex - 1, columnIndex, out prevDimension);
    182                 return prevDimension.DataCell.Row;
    183             });
    184         }
    185 
    186         /// <summary>
    187         /// 返回下一个跨度行,如果rowIndex为最后一行,则返回null
    188         /// </summary>
    189         /// <param name="sheet">Excel工作表</param>
    190         /// <param name="rowIndex">行索引,从0开始</param>
    191         /// <param name="columnIndex">列索引,从0开始</param>
    192         /// <returns>返回下一个跨度行</returns>
    193         public static IRow NextSpanRow(this ISheet sheet, int rowIndex, int columnIndex)
    194         {
    195             return sheet.FuncSheet(rowIndex, columnIndex, (currentDimension, isMerge) =>
    196                 isMerge ? sheet.GetRow(currentDimension.FirstRowIndex + currentDimension.RowSpan) : sheet.GetRow(rowIndex));
    197         }
    198 
    199         /// <summary>
    200         /// 返回上一个跨度行,如果row为第一行,则返回null
    201         /// </summary>
    202         /// <param name="row"></param>
    203         /// <returns>返回上一个跨度行</returns>
    204         public static IRow PrevSpanRow(this IRow row)
    205         {
    206             return row.Sheet.PrevSpanRow(row.RowNum, row.FirstCellNum);
    207         }
    208 
    209         /// <summary>
    210         /// 返回下一个跨度行,如果row为最后一行,则返回null
    211         /// </summary>
    212         /// <param name="row"></param>
    213         /// <returns>返回下一个跨度行</returns>
    214         public static IRow NextSpanRow(this IRow row)
    215         {
    216             return row.Sheet.NextSpanRow(row.RowNum, row.FirstCellNum);
    217         }
    218 
    219         /// <summary>
    220         /// 返回上一个跨度列,如果columnIndex为第一列,则返回null
    221         /// </summary>
    222         /// <param name="row"></param>
    223         /// <param name="columnIndex">列索引,从0开始</param>
    224         /// <returns>返回上一个跨度列</returns>
    225         public static ICell PrevSpanCell(this IRow row, int columnIndex)
    226         {
    227             return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) =>
    228             {
    229                 //上一个单元格维度
    230                 Dimension prevDimension;
    231                 row.Sheet.IsMergeCell(row.RowNum, currentDimension.FirstColumnIndex - 1, out prevDimension);
    232                 return prevDimension.DataCell;
    233             });
    234         }
    235 
    236         /// <summary>
    237         /// 返回下一个跨度列,如果columnIndex为最后一列,则返回null
    238         /// </summary>
    239         /// <param name="row"></param>
    240         /// <param name="columnIndex">列索引,从0开始</param>
    241         /// <returns>返回下一个跨度列</returns>
    242         public static ICell NextSpanCell(this IRow row, int columnIndex)
    243         {
    244             return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) =>
    245                 row.GetCell(currentDimension.FirstColumnIndex + currentDimension.ColumnSpan));
    246         }
    247 
    248         /// <summary>
    249         /// 返回上一个跨度列,如果cell为第一列,则返回null
    250         /// </summary>
    251         /// <param name="cell">单元格</param>
    252         /// <returns>返回上一个跨度列</returns>
    253         public static ICell PrevSpanCell(this ICell cell)
    254         {
    255             return cell.Row.PrevSpanCell(cell.ColumnIndex);
    256         }
    257 
    258         /// <summary>
    259         /// 返回下一个跨度列,如果columnIndex为最后一列,则返回null
    260         /// </summary>
    261         /// <param name="cell">单元格</param>
    262         /// <returns>返回下一个跨度列</returns>
    263         public static ICell NextSpanCell(this ICell cell)
    264         {
    265             return cell.Row.NextSpanCell(cell.ColumnIndex);
    266         }
    267 
    268         /// <summary>
    269         /// 返回指定行索引所在的合并单元格(区域)中的第一行(通常是含有数据的行)
    270         /// </summary>
    271         /// <param name="sheet">Excel工作表</param>
    272         /// <param name="rowIndex">行索引,从0开始</param>
    273         /// <returns>返回指定列索引所在的合并单元格(区域)中的第一行</returns>
    274         public static IRow GetDataRow(this ISheet sheet, int rowIndex)
    275         {
    276             return sheet.FuncSheet(rowIndex, 0, (currentDimension, isMerge) => sheet.GetRow(currentDimension.FirstRowIndex));
    277         }
    278 
    279         /// <summary>
    280         /// 返回指定列索引所在的合并单元格(区域)中的第一行第一列(通常是含有数据的单元格)
    281         /// </summary>
    282         /// <param name="row"></param>
    283         /// <param name="columnIndex">列索引</param>
    284         /// <returns>返回指定列索引所在的合并单元格(区域)中的第一行第一列</returns>
    285         public static ICell GetDataCell(this IRow row, int columnIndex)
    286         {
    287             return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) => currentDimension.DataCell);
    288         }
    289 
    290         private static T FuncSheet<T>(this ISheet sheet, int rowIndex, int columnIndex, Func<Dimension, bool, T> func)
    291         {
    292             //当前单元格维度
    293             Dimension currentDimension;
    294             //是否为合并单元格
    295             bool isMerge = sheet.IsMergeCell(rowIndex, columnIndex, out currentDimension);
    296 
    297             return func(currentDimension, isMerge);
    298         }
    299     }
    300 }
  • 相关阅读:
    manage.py migrate 报错
    pip安装django出错 Could not install packages due to an EnvironmentError: [Errno 13]
    利用beautifulsoup下载网页html代码中的css, js, img文件并保存
    itchat库微信自动回复祝福语
    关于阿里云Mysql分页查询不走索引的问题
    如何成为PHP程序员?
    Linux常用命令之scp
    PHP版本的区别与用法详解
    Linux常用命令之ftp
    Linux常用命令之权限管理
  • 原文地址:https://www.cnblogs.com/VAllen/p/NPOI-Extension-Get-Dimension.html
Copyright © 2011-2022 走看看