因工作需要用到跨合并单元格获取数据,所以写了个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. 随机生成并排序 C,去同,有序数组合并排序

    #include<iostream> #include<stdlib.h> #include<time.h> using namespace std; int ma ...

  2. c++ TCP keepalive 使用

    来源:http://blog.csdn.net/weiwangchao_/article/details/7225338 http://www.cnitblog.com/zouzheng/archiv ...

  3. XML入门知识

    什么是XML? 答:指可扩展标记语言(eXtensible Markup Language),被设计用来传输和存储数据:标签没有被预定义.您需要自行定义标签:被设计为具有自我描述性. XML和HTML ...

  4. Angular2 路由问题修复 、求解

    Angular2 提供了比angular1 更为强大的路由功能,但是在具体使用路由过程中,可是出现了很多路由不按照预想的方式执行的问题.为了说明今天的问题,我特地新建了一个测试工程.欢迎交流. 首先介 ...

  5. Laravel路由

    Laravel安装,这里使用一键安装包. 使用PHP内置的Web服务器,在PHP文件夹下运行命令行 php -S 0.0.0.0:1024 一.设置路由 路由文件在app\HTTP\routes.ph ...

  6. C#中运算符的应用

    c#中的运算符(只说我自己熟悉和常用的)一.算数运算:加 +减 -乘 *除 / (整型的除法是不算小数点的,也就是说结果是整数,余数舍去了,求余数看下面)求余数 % 加减乘好理解,整型的除法和求余数因 ...

  7. iOS 原生的 UIButton 点击事件是不允许带多参数的,唯一的一个参数就是默认UIButton本身 那么我们该怎么实现传递多个参数的点击事件呢?

    UIButton *btn = // create the button objc_setAssociatedObject(btn, "firstObject", someObje ...

  8. Jackson学习(一)

    Jackson的一些配置.使用方式以及效率方面的简单介绍. 1.jackson的maven依赖 <!-- jackson依赖 --> <dependency> <grou ...

  9. 关于Dapper.NET的相关论述

    年少时,为何不为自己的梦想去拼搏一次呢?纵使头破血流,也不悔有那年少轻狂.感慨很多,最近事情也很多,博客也很少更新了,毕竟每个人都需要为自己的生活去努力. 最近在一个群里遇到一个人说的话,在这里不再赘 ...

  10. C++ 11 学习1:类型自动推导 auto和decltype

    Cocos 3.x 用了大量的C++ 11 的东西,所以作为一个C++忠实粉丝,有必要对C++ 11进行一个系统的学习. 使用C++11之前,一定要注意自己使用的编译器对C++11的支持情况,有些编译 ...