返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C# 基于NPOI操作Excel
  • 229
分享到

C# 基于NPOI操作Excel

2024-04-02 19:04:59 229人浏览 泡泡鱼
摘要

目录1 单元格下拉框 2 添加批注 3 读取数据 结语 常见问题解决NPOI 导出添加批注功能POI导出excel时下拉列表值超过255的问题日期格式导入混乱注意1 单元格下拉框

1 单元格下拉框

开发中我们会遇到为单元格设置下拉框。一般可以编写如下:


var cellRanges = new CellRangeAddressList(firstRow, lastRow, firstCol, latsCol);
DVConstraint constraint = DVConstraint.CreateExplicitListConstraint(stringArray);
HSSFDataValidation validate = new HSSFDataValidation(cellRanges, constraint);
validate.ShowProptBox = true;
sheet.AddValidationData(validate);

但是,如果字符串数组存在长度限制,如NPOI导出Excel时下拉列表值超过255的问题(String literals in fORMulas can't be bigger than 255 characters ASCII)
解决方案
通过额外新建Excel的Sheet页保存下拉内容,并转换为下拉框数据。


ISheet hidden = workbook.CreateSheet(columnName);
IRow row = null;
ICell cell = null;
for (int i = 0; i < stringArray.Length; i++)
{
    row = hidden.CreateRow(i);
    cell = row.CreateCell(0);
    cell.SetCellValue(stringArray[i]);
}
IName namedCell = workbook.CreateName();
namedCell.NameName = column.ColumnName;
// 注意下面的语法是Excel的公式,建议不要落掉一个`$`,很多文档都要所遗漏。
namedCell.RefersToFormula = $"{columnName}!$A$1:$A${stringArray.Length}";
DVConstraint constraint =  DVConstraint.CreateFormulaListConstraint(columnName);
CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, latsCol);
HSSFDataValidation validate = new HSSFDataValidation(addressList, constraint);
sheet.AddValidationData(dataValidate);

2 添加批注

代码如下:


HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
// 这个代码参数不要写成固定的,它用来定位你的批注的位置和大小。
HSSFComment comment = 
    (HSSFComment)patriarch.CreateCellComment(new HSSFFClientAnchor(0, 0, 255,255, col1, 0, col1 + 2, 5));
comment.Author = "Dison";
comment.String = new HSSFRichTextString($"内容");
cell.CellComment = comment;

3 读取数据

如何解析公式的结果
代码如下:


if (row.GetCell(i).CellType.Equals(CellType.Formula))
{
    var data = row.GetCell(i).RichStrinGCellValue;
}

如果希望读取公式也可以如下:


var data = row.GetCell(i).ToString();

但是需要注意结果没有等号“=”, 这里我是演示,所以写了局部变量。

日期格式 MM-dd-yy 转 yyyy-MM-dd
由于Excel的数字和日期都是Numeric格式,;处理如下:


if (row.GetCell(i).CellType.Equals(CellType.Numeric))
{
    ICell cell = row.GetCell(i);
    short format = cell.CellStyle.DataFormat;
    if (format != 0)
    {
        var data = cell.DateCellValue.ToString("yyyy-MM-dd");
    }
    else 
    {
        var data = cell.NumericCellValue;
    }
}

结语

NPOI还是一个相对成熟的Excel操作库。网上的资料确实写的比较潦草。但是作为程序员,必须学会耐心,尤其是debug。

常见问题解决

NPOI 导出添加批注功能


//添加批注
HSSFPatriarch patr = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
HSSFComment comment12 = patr.CreateComment(new HSSFClientAnchor(0, 0, 0, 0, 1, 2, 2, 3));//批注显示定位
comment12.String = new HSSFRichTextString("请填写完整部门名称!");
HSSFCell cell12 = (HSSFCell)headerRow.CreateCell(12);//将批注给予单元格
cell12.CellComment = comment12;

但是有个比较重要的地方需要澄清下,就是批注的位置和大小,这是由HSSFClientAnchor八个参数控制的,千万不能简单的写HSSFClientAnchor(0, 0, 0, 0, 1, 2, 2, 3),

因为每个单元格的批注的位置都是不一样的(编辑批注时的位置)。那么怎么办呢,当然是需要了解参数的意思:

简单说来:

关于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的参数,有必要在这里说明一下:

  • dx1:起始单元格的x偏移量;
  • dy1:起始单元格的y偏移量;
  • dx2:终止单元格的x偏移量;
  • dy2:终止单元格的y偏移量;
  • col1:起始单元格列序号;
  • row1:起始单元格行序号;
  • col2:终止单元格列序号;
  • row2:终止单元格行序号;

其实主要是前四个是偏移量,后四个关系到批注的位置和大小。

以我自己做的一个例子来说:


HSSFComment comment1 = (HSSFComment)patr.CreateCellComment(new HSSFClientAnchor(255, 125, 1023, 150, colindex + 1, rowIndex - 1,  colindex + 2, rowIndex + 4));
  • rowIndex 是当前单元格是第几行,colindex 是当前单元格是第几列。通过行列是可以定位到当前的单元格的。
  • colindex + 1 对应上面的参数是col1  表示批注起始的位置是当前单元格的列数的下一列,即原来是第5列,则批注起在第6列。
  • rowIndex - 1 对应上面的参数是row1  表示皮质起始的位置是当前单元格行数的上一行,即原来是第2行,则批注起在第1行。
  • colindex + 2, rowIndex + 4  这两个参数则是单元格终止的位置   +2  +4  则是决定了批注的大小,道理同colindex + 1,rowIndex - 1 。

但是NPOI导出有个坑   就是批注大小会随着所在位置的单元格大小变动  这个影响不大  如果想解决这个问题   只能换导出方法了。。。

千万别按照网上人家写的(0, 0, 0, 0, 1, 2, 2, 3),这会坑死的,批注位置一直不变  任何单元格的批注都在同一个位置,坑死。

POI导出Excel时下拉列表值超过255的问题


//创建Excel工作薄对象

Workbook workbook = new HSSFWorkbook();

//生成一个表格 设置:页签

Sheet sheet = workbook.createSheet("sheet1");

 

//去数据库中查询我们想要的数据

List<Product> productList = Ebean.getServer(GlobalDBControl.getDB()) .createQuery(Product.class, "find product where 1 = 1 and status = 0 and producttype is not null ") .findList();

//创建一个数组 用来存放 我们取出来的数据

String[] productNameArray = new String[productList.size()];

//遍历每个peoduct对象,来获取productName属性并添加到数组中

for (int i = 0; i < productList.size(); i++)

{ Product product = productList.get(i);

productNameArray[i] = product.getTitle(); }

//将下拉框数据放到新的sheet里,然后excle通过新的sheet数据加载下拉框数据

Sheet hidden = workbook.createSheet("hidden");

//创建单元格对象 Cell cell = null;

//遍历我们上面的数组,将数据取出来放到新sheet的单元格中

for (int i = 0, length = productNameArray.length; i < length; i++)

{ //取出数组中的每个元素

String name = productNameArray[i];

//根据i创建相应的行对象(说明我们将会把每个元素单独放一行)

Row row = hidden.createRow(i);

//创建每一行中的第一个单元格

cell = row.createCell(0);

//然后将数组中的元素赋值给这个单元格

cell.setCellValue(name); }

 

// 创建名称,可被其他单元格引用

Name namedCell = workbook.createName(); namedCell.setNameName("hidden");

// 设置名称引用的公式

namedCell.setRefersToFormula("hidden!$A$1:$A$" + productNameArray.length);

//加载数据,将名称为hidden的sheet中的数据转换为List形式

DVConstraint constraint = DVConstraint.createFormulaListConstraint("hidden");

// 设置第一列的3-65534行为下拉列表

// (3, 65534, 0, 0) ====> (起始行,结束行,起始列,结束列)

CellRangeAddressList regions = new CellRangeAddressList(3, 65534, 0, 0);

// 将设置下拉选的位置和数据的对应关系 绑定到一起

DataValidation dataValidation = new HSSFDataValidation(regions, constraint);

//将第二个sheet设置为隐藏 workbook.setSheetHidden(1, true);

//将数据赋给下拉列表 sheet.addValidationData(dataValidation);

//最后将文件导出就可以了,后面的代码就不写了,我只写一些这个问题相关的代码

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   如果出现多列情况,可复用下面方法

private void ExcelTo255(Workbook workbook,String sheetName,int sheetNameIndex,String[] sheetData,int firstRow,int lastRow,int firstCol,int lastCol){
    //将下拉框数据放到新的sheet里,然后excle通过新的sheet数据加载下拉框数据
    Sheet hidden = workbook.createSheet(sheetName);

    //创建单元格对象
    Cell cell =null;
    //遍历我们上面的数组,将数据取出来放到新sheet的单元格中
    for (int i = 0, length = sheetData.length; i < length; i++){
        //取出数组中的每个元素
        String name = sheetData[i];
        //根据i创建相应的行对象(说明我们将会把每个元素单独放一行)
        Row row = hidden.createRow(i);
        //创建每一行中的第一个单元格
        cell = row.createCell(0);
        //然后将数组中的元素赋值给这个单元格
        cell.setCellValue(name);
    }
    // 创建名称,可被其他单元格引用
    Name namedCell = workbook.createName();
    namedCell.setNameName(sheetName);
    // 设置名称引用的公式
    namedCell.setRefersToFormula(sheetName+"!$A$1:$A$" + sheetData.length);
    //加载数据,将名称为hidden的sheet中的数据转换为List形式
    DVConstraint constraint = DVConstraint.createFormulaListConstraint(sheetName);

    // 设置第一列的3-65534行为下拉列表
    // (3, 65534, 2, 2) ====> (起始行,结束行,起始列,结束列)
    CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
    // 将设置下拉选的位置和数据的对应关系 绑定到一起
    DataValidation dataValidation = new HSSFDataValidation(regions, constraint);

    //将第二个sheet设置为隐藏
    workbook.setSheetHidden(sheetNameIndex, true);
    //将数据赋给下拉列表
    workbook.getSheetAt(0).addValidationData(dataValidation);
}

日期格式导入混乱

原因

大概是NPOI导入时会大概判断一下Excel文档里面的单元格是什么格式的内容,

有Blank,Boolean,Numeric,String,Error,Formula 等几种,

但是就是没有日期的,日期的单元格会被判断成Numeric(数字)类型,

所以日期格式的单元格就按数字类型来取其中的值,

所以单元格被判断成数字的之后还要再判断一下是否为日期格式。


/// <summary>
        /// 获取单元格类型
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        private static object GetValueType(ICell cell)
        {
            if (cell == null)
                return null;
            switch (cell.CellType)
            {
                case CellType.Blank: //BLANK:  
                    return null;
                case CellType.Boolean: //BOOLEAN:  
                    return cell.BooleanCellValue;
                case CellType.Numeric: //NUMERIC:  
                    short format = cell.CellStyle.DataFormat;
                    if (format != 0) { return cell.DateCellValue; } else { return cell.NumericCellValue; }
                case CellType.String: //STRING:  
                    return cell.StringCellValue;
                case CellType.Error: //ERROR:  
                    return cell.ErrorCellValue;
                case CellType.Formula: //FORMULA:  
                default:
                    return "=" + cell.CellFormula;
            }
        }

注意

使用时Excel里的长数字类型,否则这类数据可能会被误判为日期类型

如:0000123,2017001等这类型的需要处理一下单元格格式->设置成"常规"类型

以上就是C# 基于NPOI操作Excel的详细内容,更多关于C# NPOI操作Excel的资料请关注编程网其它相关文章!

--结束END--

本文标题: C# 基于NPOI操作Excel

本文链接: https://lsjlt.com/news/128361.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C# 基于NPOI操作Excel
    目录1 单元格下拉框 2 添加批注 3 读取数据 结语 常见问题解决NPOI 导出添加批注功能POI导出Excel时下拉列表值超过255的问题日期格式导入混乱注意1 单元格下拉框 ...
    99+
    2024-04-02
  • C#基于NPOI操作Excel
    NPOI简介 NPOI是指构建在POI 3.x版本之上的一个程序,NPOI可以在没有安装Office的情况下对Word或Excel文档进行读写操作。 NPOI是一个开源的C#读写Ex...
    99+
    2024-04-02
  • C#基于NPOI怎么操作Excel
    这篇文章主要介绍“C#基于NPOI怎么操作Excel”,在日常操作中,相信很多人在C#基于NPOI怎么操作Excel问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#基于NPOI怎么操作Excel”的疑惑有所...
    99+
    2023-06-30
  • C#中怎么用NPOI操作Excel
    这篇“C#中怎么用NPOI操作Excel”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#中怎么用NPOI操作Excel”文...
    99+
    2023-06-29
  • C#利用NPOI操作Excel(单元格设置)
    本文实例为大家分享了C#利用NPOI操作Excel的单元格设置,供大家参考,具体内容如下 一.合并单元格 NOPI支持对单元格进行合并,还有单元格格式设置! 注意: 在进行单元格合并...
    99+
    2024-04-02
  • C#操作NPOI实现Excel数据导入导出
    目录1.NpoiExcelHelper.cs  Npoi操作Excel类2.WEB项目的调用方法首先在项目中引用NPOI,通过管理NuGet程序包,搜索NPOI,...
    99+
    2023-02-15
    C# NPOI Excel数据导入导出 C# Excel数据导入导出 C# NPOIExcel
  • 基于NPOI用C#开发的Excel以及表格设置
    本文为大家分享了基于NPOI用C#开发的Excel以及表格设置,供大家参考,具体内容如下 最近在项目中需要导出Excel。在这里做个记录。在网上查阅了一些资料。将自己最终的代码分享在...
    99+
    2024-04-02
  • 关于Python操作Excel的基本方法
    目录写入Excel1. 安装第三方模块2. 编写代码读取Excel1. 安装第三方模块小结写入Excel 1. 安装第三方模块 修改excel可以使用xlwt模块 pip insta...
    99+
    2023-05-18
    Python Excel Python操作Excel
  • C#使用NPOI导出Excel类封装
    NPOI是指构建在POI 3.x版本之上的一个程序,NPOI可以在没有安装Office的情况下对Word或Excel文档进行读写操作。 NPOI是一个开源的C#读写Excel、WOR...
    99+
    2024-04-02
  • C#使用NPOI读取excel转为DataSet
    本文实例为大家分享了C#使用NPOI读取excel转为DataSet的具体代码,供大家参考,具体内容如下 NPOI读取excel转为DataSet /// <summary&g...
    99+
    2024-04-02
  • C#使用NPOI库读写Excel文件
    本文实例为大家分享了C#使用NPOI库读写Excel文件的具体代码,供大家参考,具体内容如下 第一步添加程引用: 右键项目工程 — 管理 NuGet程序包 —...
    99+
    2024-04-02
  • C#实现NPOI的Excel导出详解
    技术点: 1.自定义attribute属性 2.通过反射取类及其属性的attribute属性值 3.NPOI包常用属性及方法(我也仅仅知道用到过的,陌生的要么见名知意,要么百度查) ...
    99+
    2024-04-02
  • C#用NPOI导出导入Excel帮助类
    本文实例为大家分享了C#用NPOI导出导入Excel帮助类的具体代码,供大家参考,具体内容如下 1、准备工作 在管理NuGet程序包中搜索 NPOI,安装 NPOI 到要项目中。 2...
    99+
    2024-04-02
  • C#通过NPOI导入导出数据EXCEL
    本文实例为大家分享了C#通过NPOI导入导出数据EXCEL的具体代码,供大家参考,具体内容如下 其实从数据库到服务器导入导出有很多方法,但是比较简单的有NPOI这个方法 准备工作,先...
    99+
    2024-04-02
  • C#使用NPOI设置Excel下拉选项
    本文实例为大家分享了C#使用NPOI设置Excel下拉选项的具体代码,供大家参考,具体内容如下 最近在做一个导出模板的功能,需要限制用户的某些单元格输入的内容。 期望达到的效果:单元...
    99+
    2024-04-02
  • 怎么用C#实现NPOI的Excel导出
    这篇文章主要讲解了“怎么用C#实现NPOI的Excel导出”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用C#实现NPOI的Excel导出”吧!技术点:自定义attribute属性通过反...
    99+
    2023-06-26
  • C#读取Excel的操作
    这篇文章主要讲解了“C#读取Excel的操作”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#读取Excel的操作”吧!C# 操作Excel之读取Excel操作的由来:看到论坛里面不断有人提...
    99+
    2023-06-17
  • python3编程基础:操作excel(
    目录 前言 安装模块 例1:创建一个excel 文件,并写入不同类的内容 例2:写入时间 例3:创建sheet 例4 :操作单元格 例5 :操作行/列/指定区域 例6:显示小数 例7:获取所有的行对象 例8:获取所有的列对象 例9:单元格...
    99+
    2023-01-31
    操作 基础 excel
  • 关于Python自动化操作Excel
    目录一、Python 操作 Excel 的常用库1. 使用第三方库 openpyxl2. 使用第三方库 xlrd 和 xlwt3. 使用 pandas 库二、Python 操作 ex...
    99+
    2023-05-15
    Python自动化 Python操作Excel Python自动化Excel
  • C#使用NPOI实现Excel和DataTable的互转
    什么是NPOI? NPOI是指构建在POI 3.x版本之上的一个程序,NPOI可以在没有安装Office的情况下对Word或Excel文档进行读写操作。 NPOI是一个开源的C#读写...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作