Fork me on GitHub

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 }

 

posted @ 2017-03-31 16:12  VAllen  阅读(7254)  评论(1编辑  收藏  举报