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

主要方法如下:

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

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

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

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

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

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

 namespace NPOI
{
/// <summary>
/// 表示单元格的维度,通常用于表达合并单元格的维度
/// </summary>
public struct Dimension
{
/// <summary>
/// 含有数据的单元格(通常表示合并单元格的第一个跨度行第一个跨度列),该字段可能为null
/// </summary>
public ICell DataCell; /// <summary>
/// 行跨度(跨越了多少行)
/// </summary>
public int RowSpan; /// <summary>
/// 列跨度(跨越了多少列)
/// </summary>
public int ColumnSpan; /// <summary>
/// 合并单元格的起始行索引
/// </summary>
public int FirstRowIndex; /// <summary>
/// 合并单元格的结束行索引
/// </summary>
public int LastRowIndex; /// <summary>
/// 合并单元格的起始列索引
/// </summary>
public int FirstColumnIndex; /// <summary>
/// 合并单元格的结束列索引
/// </summary>
public int LastColumnIndex;
} public static class ExcelExtension
{
/// <summary>
/// 判断指定行列所在的单元格是否为合并单元格,并且输出该单元格的维度
/// </summary>
/// <param name="sheet">Excel工作表</param>
/// <param name="rowIndex">行索引,从0开始</param>
/// <param name="columnIndex">列索引,从0开始</param>
/// <param name="dimension">单元格维度</param>
/// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
public static bool IsMergeCell(this ISheet sheet, int rowIndex, int columnIndex, out Dimension dimension)
{
dimension = new Dimension
{
DataCell = null,
RowSpan = ,
ColumnSpan = ,
FirstRowIndex = rowIndex,
LastRowIndex = rowIndex,
FirstColumnIndex = columnIndex,
LastColumnIndex = columnIndex
}; for (int i = ; i < sheet.NumMergedRegions; i++)
{
CellRangeAddress range = sheet.GetMergedRegion(i);
sheet.IsMergedRegion(range); //这种算法只有当指定行列索引刚好是合并单元格的第一个跨度行第一个跨度列时才能取得合并单元格的跨度
//if (range.FirstRow == rowIndex && range.FirstColumn == columnIndex)
//{
// dimension.DataCell = sheet.GetRow(range.FirstRow).GetCell(range.FirstColumn);
// dimension.RowSpan = range.LastRow - range.FirstRow + 1;
// dimension.ColumnSpan = range.LastColumn - range.FirstColumn + 1;
// dimension.FirstRowIndex = range.FirstRow;
// dimension.LastRowIndex = range.LastRow;
// dimension.FirstColumnIndex = range.FirstColumn;
// dimension.LastColumnIndex = range.LastColumn;
// break;
//} if ((rowIndex >= range.FirstRow && range.LastRow >= rowIndex) && (columnIndex >= range.FirstColumn && range.LastColumn >= columnIndex))
{
dimension.DataCell = sheet.GetRow(range.FirstRow).GetCell(range.FirstColumn);
dimension.RowSpan = range.LastRow - range.FirstRow + ;
dimension.ColumnSpan = range.LastColumn - range.FirstColumn + ;
dimension.FirstRowIndex = range.FirstRow;
dimension.LastRowIndex = range.LastRow;
dimension.FirstColumnIndex = range.FirstColumn;
dimension.LastColumnIndex = range.LastColumn;
break;
}
} bool result;
if (rowIndex >= && sheet.LastRowNum > rowIndex)
{
IRow row = sheet.GetRow(rowIndex);
if (columnIndex >= && row.LastCellNum > columnIndex)
{
ICell cell = row.GetCell(columnIndex);
result = cell.IsMergedCell; if (dimension.DataCell == null)
{
dimension.DataCell = cell;
}
}
else
{
result = false;
}
}
else
{
result = false;
} return result;
} /// <summary>
/// 判断指定行列所在的单元格是否为合并单元格,并且输出该单元格的行列跨度
/// </summary>
/// <param name="sheet">Excel工作表</param>
/// <param name="rowIndex">行索引,从0开始</param>
/// <param name="columnIndex">列索引,从0开始</param>
/// <param name="rowSpan">行跨度,返回值最小为1,同时表示没有行合并</param>
/// <param name="columnSpan">列跨度,返回值最小为1,同时表示没有列合并</param>
/// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
public static bool IsMergeCell(this ISheet sheet, int rowIndex, int columnIndex, out int rowSpan, out int columnSpan)
{
Dimension dimension;
bool result = sheet.IsMergeCell(rowIndex, columnIndex, out dimension); rowSpan = dimension.RowSpan;
columnSpan = dimension.ColumnSpan; return result;
} /// <summary>
/// 判断指定单元格是否为合并单元格,并且输出该单元格的维度
/// </summary>
/// <param name="cell">单元格</param>
/// <param name="dimension">单元格维度</param>
/// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
public static bool IsMergeCell(this ICell cell, out Dimension dimension)
{
return cell.Sheet.IsMergeCell(cell.RowIndex, cell.ColumnIndex, out dimension);
} /// <summary>
/// 判断指定单元格是否为合并单元格,并且输出该单元格的行列跨度
/// </summary>
/// <param name="cell">单元格</param>
/// <param name="rowSpan">行跨度,返回值最小为1,同时表示没有行合并</param>
/// <param name="columnSpan">列跨度,返回值最小为1,同时表示没有列合并</param>
/// <returns>返回是否为合并单元格的布尔(Boolean)值</returns>
public static bool IsMergeCell(this ICell cell, out int rowSpan, out int columnSpan)
{
return cell.Sheet.IsMergeCell(cell.RowIndex, cell.ColumnIndex, out rowSpan, out columnSpan);
} /// <summary>
/// 返回上一个跨度行,如果rowIndex为第一行,则返回null
/// </summary>
/// <param name="sheet">Excel工作表</param>
/// <param name="rowIndex">行索引,从0开始</param>
/// <param name="columnIndex">列索引,从0开始</param>
/// <returns>返回上一个跨度行</returns>
public static IRow PrevSpanRow(this ISheet sheet, int rowIndex, int columnIndex)
{
return sheet.FuncSheet(rowIndex, columnIndex, (currentDimension, isMerge) =>
{
//上一个单元格维度
Dimension prevDimension;
sheet.IsMergeCell(currentDimension.FirstRowIndex - , columnIndex, out prevDimension);
return prevDimension.DataCell.Row;
});
} /// <summary>
/// 返回下一个跨度行,如果rowIndex为最后一行,则返回null
/// </summary>
/// <param name="sheet">Excel工作表</param>
/// <param name="rowIndex">行索引,从0开始</param>
/// <param name="columnIndex">列索引,从0开始</param>
/// <returns>返回下一个跨度行</returns>
public static IRow NextSpanRow(this ISheet sheet, int rowIndex, int columnIndex)
{
return sheet.FuncSheet(rowIndex, columnIndex, (currentDimension, isMerge) =>
isMerge ? sheet.GetRow(currentDimension.FirstRowIndex + currentDimension.RowSpan) : sheet.GetRow(rowIndex));
} /// <summary>
/// 返回上一个跨度行,如果row为第一行,则返回null
/// </summary>
/// <param name="row">行</param>
/// <returns>返回上一个跨度行</returns>
public static IRow PrevSpanRow(this IRow row)
{
return row.Sheet.PrevSpanRow(row.RowNum, row.FirstCellNum);
} /// <summary>
/// 返回下一个跨度行,如果row为最后一行,则返回null
/// </summary>
/// <param name="row">行</param>
/// <returns>返回下一个跨度行</returns>
public static IRow NextSpanRow(this IRow row)
{
return row.Sheet.NextSpanRow(row.RowNum, row.FirstCellNum);
} /// <summary>
/// 返回上一个跨度列,如果columnIndex为第一列,则返回null
/// </summary>
/// <param name="row">行</param>
/// <param name="columnIndex">列索引,从0开始</param>
/// <returns>返回上一个跨度列</returns>
public static ICell PrevSpanCell(this IRow row, int columnIndex)
{
return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) =>
{
//上一个单元格维度
Dimension prevDimension;
row.Sheet.IsMergeCell(row.RowNum, currentDimension.FirstColumnIndex - , out prevDimension);
return prevDimension.DataCell;
});
} /// <summary>
/// 返回下一个跨度列,如果columnIndex为最后一列,则返回null
/// </summary>
/// <param name="row">行</param>
/// <param name="columnIndex">列索引,从0开始</param>
/// <returns>返回下一个跨度列</returns>
public static ICell NextSpanCell(this IRow row, int columnIndex)
{
return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) =>
row.GetCell(currentDimension.FirstColumnIndex + currentDimension.ColumnSpan));
} /// <summary>
/// 返回上一个跨度列,如果cell为第一列,则返回null
/// </summary>
/// <param name="cell">单元格</param>
/// <returns>返回上一个跨度列</returns>
public static ICell PrevSpanCell(this ICell cell)
{
return cell.Row.PrevSpanCell(cell.ColumnIndex);
} /// <summary>
/// 返回下一个跨度列,如果columnIndex为最后一列,则返回null
/// </summary>
/// <param name="cell">单元格</param>
/// <returns>返回下一个跨度列</returns>
public static ICell NextSpanCell(this ICell cell)
{
return cell.Row.NextSpanCell(cell.ColumnIndex);
} /// <summary>
/// 返回指定行索引所在的合并单元格(区域)中的第一行(通常是含有数据的行)
/// </summary>
/// <param name="sheet">Excel工作表</param>
/// <param name="rowIndex">行索引,从0开始</param>
/// <returns>返回指定列索引所在的合并单元格(区域)中的第一行</returns>
public static IRow GetDataRow(this ISheet sheet, int rowIndex)
{
return sheet.FuncSheet(rowIndex, , (currentDimension, isMerge) => sheet.GetRow(currentDimension.FirstRowIndex));
} /// <summary>
/// 返回指定列索引所在的合并单元格(区域)中的第一行第一列(通常是含有数据的单元格)
/// </summary>
/// <param name="row">行</param>
/// <param name="columnIndex">列索引</param>
/// <returns>返回指定列索引所在的合并单元格(区域)中的第一行第一列</returns>
public static ICell GetDataCell(this IRow row, int columnIndex)
{
return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) => currentDimension.DataCell);
} private static T FuncSheet<T>(this ISheet sheet, int rowIndex, int columnIndex, Func<Dimension, bool, T> func)
{
//当前单元格维度
Dimension currentDimension;
//是否为合并单元格
bool isMerge = sheet.IsMergeCell(rowIndex, columnIndex, out currentDimension); return func(currentDimension, isMerge);
}
}
}

NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)的更多相关文章

  1. 27.openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽

    openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽 from openpyxl import Workbook,load_workbook from openpyxl.dra ...

  2. 【EXCEL终极总结分享】基于NPOI扩展封装的简易操作工具类库(简单灵活易用,支持导出、导入、上传等常见操作)

    对于EXCEL的导入.导出,我之前已分享过多次,比如: 第一种方案:<我写的一个ExcelHelper通用类,可用于读取或生成数据>这个主要是利用把EXCEL当成一个DB来进行获取数据,导 ...

  3. asp.net将页面内容按需导入Excel,并设置excel样式,下载文件(解决打开格式与扩展名指定的格式不统一的问题)

    //请求一个excel类 Microsoft.Office.Interop.Excel.ApplicationClass excel = null; //创建 Workbook对象 Microsoft ...

  4. 个人永久性免费-Excel催化剂功能第52波-相同内容批量合并单元格,取消合并单元格并填充内容

    在高级Excel用户群体中无比痛恨的合并单元格,在现实的表格中却阴魂不散的纠缠不断.今天Excel催化剂也来成为“帮凶”,制造更多的合并单元格.虽然开发出此功能,请使用过程中务必要保持节制,在可以称为 ...

  5. javascript生成表格增删改查 JavaScript动态改变表格单元格内容 动态生成表格 JS获取表格任意单元格 javascript如何动态删除表格某一行

    jsp页面表格布局Html代码 <body onload="show()"> <center> <input type="text" ...

  6. C# 对Excel 单元格格式, 及行高、 列宽、 单元格边框线、 冻结设置

    一.对行高,列宽.单元格边框等的设置 这篇简短的文字对单元格的操作总结的比较全面,特此转载过来. private _Workbook _workBook = null; private Workshe ...

  7. String的两个API,判断指定字符串是否包含另一字符串,在字符串中删除指定字符串。

    // 在字符串中删除指定字符串. String phoneNum="1795112345"; phoneNum = phoneNum.replace("17951&quo ...

  8. 打开Excel时提示"您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致"

    问题描述:     系统安装了WPS时,Analyzer导出excel时候,会提示"您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致",这是Excel的安全问题,   ...

  9. Excel:您尝试打开的文件的格式与文件扩展名指定的格式不一致

    报错信息: 打开文件时提示"您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致.打开文件前请验证文件没有损坏且来源可信.是否立即打开该文件?",卸载Office 20 ...

随机推荐

  1. MATLAB 单变量函数一阶及N阶求导

    1 对一维函数的求导及求特定函数处的变量值 %%最简单的一阶单变量函数进行求导 function usemyfunArray() %主函数必须位于最上方 clc clear syms x %syms ...

  2. Dockerfile注意事项

    准则 尽量将Dockerfile放在空目录中,如果目录中必须有其他文件,则使用.dockerignore文件. 避免安装不必须的包. 每个容器应该只关注一个功能点. 最小化镜像的层数. 多行参数时应该 ...

  3. BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)

    首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...

  4. Javascript学习一

    //学习moocjs1 JavaScript-警告(alert 消息对话框) <script type="text/javascript"> var mynum = 3 ...

  5. 【前端】:jQuery下

    前言: 接上一篇博客: [前端]:jQuery上 一.jQuery属性操作 ① attr(设置或返回自定义属性值) input.select.textarea框中的内容, 可以通过attr来获取,但是 ...

  6. iOS回顾笔记( 01 )

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  7. Hibernate框架注解

    1.使用Hibernate注解的步骤                1.添加jar包                            Hibernate-annotations.jar      ...

  8. Express4.x动态的销毁或者替换中间件(app.unuse)

    需求描述 expres4.x托管静态资源时以中间件的方式将server-static挂载到app上,正常的使用没有问题,但是有时候我们需要动态的托管一些静态资源,也就是静态资源的目录不确定的时候该怎么 ...

  9. Spring RESTful + Redis全注解实现恶意登录保护机制

    好久没更博了... 最近看了个真正全注解实现的 SpringMVC 博客,感觉很不错,终于可以彻底丢弃 web.xml 了.其实这玩意也是老东西了,丢弃 web.xml,是基于 5.6年前发布的 Se ...

  10. jquery考试纠错笔记.

    1. 获取元素范围大小顺序依次为: $(#one).siblings("div")>$("#one~div")>$("#one +div& ...