因工作需要用到跨合并单元格获取数据,所以写了个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. 【Zookeeper】源码分析之请求处理链(二)

    一.前言 前面学习了请求处理链的RequestProcessor父类,接着学习PrepRequestProcessor,其通常是请求处理链的第一个处理器. 二.ZooKeeper源码分析 2.1 类的 ...

  2. spring+struts2+ibatis 框架整合以及解析

    一. spring+struts2+ibatis 框架 搭建教程 参考:http://biancheng.dnbcw.net/linux/394565.html 二.分层 1.dao: 数据访问层(增 ...

  3. vue路由组件群

    import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter) const first = { template: ...

  4. devexpress显示缓冲滚动条与实现类似QQ消息推送效果

    1.一般在项目中处理大数据,或者查询大量数据时,耗时会很长,这个时候缓冲条是必不可少的.这里展示一个devexpress不错的缓冲条,如图所示: 使用到了控件splashScreenManager,运 ...

  5. 【转】JDBC连接数据库

    创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lang.Class类的 ...

  6. Tomcat使用Memcached Session Manager管理Session

    Tomcat使用Memcached Session Manager管理Session 废话不多说,直接进入主题.项目使用阿里云负载均衡+ECS服务器集群进行部署,Tomcat使用8.5版本.阿里云负载 ...

  7. session 与 cookie的区别用法

    //设置cookie方法 setcookie("name",'zhangsan'); setcookie("name",'zhangsan',time()+60 ...

  8. Java 集合的简单实现 (ArrayList & LinkedList & Queue & Stack)

    ArrayList 就是数组实现的啦,没什么好说的,如果数组不够了就扩容到原来的1.5倍 实现了迭代器 package com.wenr.collection; import java.io.Seri ...

  9. smarty实例登陆、显示、分页

    1.先建立登陆页面,登陆页面的PHP文件和HTML文件是分开写的. 先建立一个登陆页的PHP文件, <?php include("../init.inc.php");//引入 ...

  10. Spring框架(4)---AOP讲解铺垫

    AOP讲解铺垫      不得不说,刚开始去理解这个Aop是有点难理解的,主要还是新的概念比较多,对于初学者一下子不一定马上能够快速吸收,所以我先对什么事Aop做一个解释: 首先说明:本文不是自己所写 ...