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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM