NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)
因工作需要用到跨合并单元格获取数据,所以写了个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扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)的更多相关文章
- 27.openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽
openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽 from openpyxl import Workbook,load_workbook from openpyxl.dra ...
- 【EXCEL终极总结分享】基于NPOI扩展封装的简易操作工具类库(简单灵活易用,支持导出、导入、上传等常见操作)
对于EXCEL的导入.导出,我之前已分享过多次,比如: 第一种方案:<我写的一个ExcelHelper通用类,可用于读取或生成数据>这个主要是利用把EXCEL当成一个DB来进行获取数据,导 ...
- asp.net将页面内容按需导入Excel,并设置excel样式,下载文件(解决打开格式与扩展名指定的格式不统一的问题)
//请求一个excel类 Microsoft.Office.Interop.Excel.ApplicationClass excel = null; //创建 Workbook对象 Microsoft ...
- 个人永久性免费-Excel催化剂功能第52波-相同内容批量合并单元格,取消合并单元格并填充内容
在高级Excel用户群体中无比痛恨的合并单元格,在现实的表格中却阴魂不散的纠缠不断.今天Excel催化剂也来成为“帮凶”,制造更多的合并单元格.虽然开发出此功能,请使用过程中务必要保持节制,在可以称为 ...
- javascript生成表格增删改查 JavaScript动态改变表格单元格内容 动态生成表格 JS获取表格任意单元格 javascript如何动态删除表格某一行
jsp页面表格布局Html代码 <body onload="show()"> <center> <input type="text" ...
- C# 对Excel 单元格格式, 及行高、 列宽、 单元格边框线、 冻结设置
一.对行高,列宽.单元格边框等的设置 这篇简短的文字对单元格的操作总结的比较全面,特此转载过来. private _Workbook _workBook = null; private Workshe ...
- String的两个API,判断指定字符串是否包含另一字符串,在字符串中删除指定字符串。
// 在字符串中删除指定字符串. String phoneNum="1795112345"; phoneNum = phoneNum.replace("17951&quo ...
- 打开Excel时提示"您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致"
问题描述: 系统安装了WPS时,Analyzer导出excel时候,会提示"您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致",这是Excel的安全问题, ...
- Excel:您尝试打开的文件的格式与文件扩展名指定的格式不一致
报错信息: 打开文件时提示"您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致.打开文件前请验证文件没有损坏且来源可信.是否立即打开该文件?",卸载Office 20 ...
随机推荐
- 谷歌YSlow准则
谷歌YSlow准则 YSlow可以对网站的页面进行分析,并告诉你为了提高网站性能,如何基于某些规则而进行优化. 测试个人站点 通过测试个人站点可以获得下面的数据 23条准则 Make fewer HT ...
- TFS应用经验-大型项目数据仓库抽取导致的TFS应用无法访问
在超过千人使用的TFS生产环境中,每天周期性出现无法正常查看工作项白板.无法签入代码.无法进行自动化构建.无法进行报表数据的查看等情况,真是一个让人焦灼的问题.作为TFS平台支持和运维的团队,也想进了 ...
- 【easyui】之treegrid的分页
easyui官网给的treegrid的分页是相当的复杂,我们来简化一下! 首先treegrid 分页和 datagrid一样需要设置一系列参数! 如下: depTreeGrid=$("#de ...
- 【G】开源的分布式部署解决方案(三) - 一期规划定稿与初步剖析
G.系列导航 [G]开源的分布式部署解决方案 - 预告篇 [G]开源的分布式部署解决方案(一) - 开篇 [G]开源的分布式部署解决方案(二) - 好项目是从烂项目基础上重构出来的 [G]开源的分布式 ...
- 跟着内核学框架-从misc子系统到3+2+1设备识别驱动框架
misc子系统在Linux中是一个非常简单的子系统,但是其清晰的框架结构非常适合用来研究设备识别模型.本文从misc子系统的使用出发,通过了解其机制来总结一套的设备识别的驱动框架,即使用使用同一个驱动 ...
- C# 多态理论基础
一.概述 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性. 可以用不同的方式实现组件中的多态性: ● 接口多态性. ● 继承多态性. ● 通过抽象类实现的多态性. 二.实 ...
- Spark源码分析之Spark Shell(下)
继上次的Spark-shell脚本源码分析,还剩下后面半段.由于上次涉及了不少shell的基本内容,因此就把trap和stty放在这篇来讲述. 上篇回顾:Spark源码分析之Spark Shell(上 ...
- Angular2 Service实践——实现简单音乐播放服务
引言: 如果说组件系统(Component)是ng2应用的躯体,那把服务(Service)认为是流通于组件之间并为其带来生机的血液再合适不过了.组件间通信的其中一种优等选择就是使用服务,在ng1里就有 ...
- 《剑指offer》— JavaScript(18)二叉树的镜像
二叉树的镜像 题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 相关知识 二叉树的镜像定义: 源二叉树 镜像二叉树 思路 有关二叉树的算法问题,一般都可以通过递归来解决.那么写一个正确的递归程序 ...
- Java日志工具之Log4J
Log4J与java.util.logging.Logger的使用方式出奇的相似,因此如果先看这篇文章<Java日志工具之java.util.logging.Logger>在来用Log4J ...