java调用npoi_NPOI导入,导出

本文介绍了如何使用NPOI库在Java中进行Excel的导入与导出操作。NPOI是POI的.NET版本,用于在没有Office环境的情况下读写Excel文件。文章详细讲解了单元格数据的读取和类型转换,以及如何处理合并单元格。同时,展示了如何自定义策略接口来实现不同导入目标,如数据库存储。最后,给出了表格导入和导出的示例代码。
摘要由CSDN通过智能技术生成

概述

NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。NPOI 可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写,包含了大部分EXCEL的特性(单元格样式、数据格式、公式等等)。(复制百度百科)

表格导入导出的操作经常会碰到,最近抽空专门封装了一下。

遵循的原则:

1. 一行数据对应一个数据实体,需提供它们二者间的映射关系。

2. 支持合并单元格的导入导出(导出数据只支持竖向合并,导入数据遇到横向合并的单元格会抛出异常),图片未支持

导出的复杂在于样式的控制,当解决这一问题后后续操作就很简单了,而样式解析相关的代码行数也真的是不少,因为对API的不熟悉,连写带测折腾了不少时间。

导入因为行为的多变性,要求程序员调用时将具体的读写逻辑以策略的形式传入。所以代码量相对来说要少得多。其实也是避开了一些难题,比如公式符号,数字的上标,下标的解析(尚不知道怎么解决)。

7604283c475d52977e4a6b420e666d68.png

导出效果

eb8c36e0bdd6e85cf3219ae50e9f8801.png

表格导入

单元格数据的解析

1. 先依据单元格类的数据类型cell.CellType(枚举类型),读取其内部保存的数据,如果类型是公式的,则依据cell.CachedFormulaResultType再进行一次判别。

2. 从单元格读到数据后还再进一步完成一次类型的转换,将它转换为我们需要的类型。

///

/// 扩展

///

public static class IRowExtension

{

///

/// 读取表格中某单元格的值,如果单元格是合并单元格,则竖向合并的正常返回,横向合并的抛出异常

///

/// 要读取的数据类型

/// Excel中的某行数据

/// 行内的列下标

///

public static A GetValue(this IRow row, int index)

{

try

{

//获取单元格

ICell cell = row.GetCell(index);

//判别是否合并单元格

if (cell.IsMergedCell)

{

ISheet sheet = cell.Sheet;

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

{

var cellRange = sheet.GetMergedRegion(i);

if (cell.ColumnIndex >= cellRange.FirstColumn

&& cell.ColumnIndex <= cellRange.LastColumn

&& cell.RowIndex >= cellRange.FirstRow

&& cell.RowIndex <= cellRange.LastRow)

{

if (cellRange.FirstColumn != cellRange.LastColumn)

{

throw new Exception("不能有横向合并的单元格");

}

cell = sheet.GetRow(cellRange.FirstRow).GetCell(cellRange.FirstColumn);

}

}

}

return GetValue(cell);

}

catch (Exception ex)

{

//读取单元格信息时出错

throw new Exception("出错位置的列下标:" + index + ",报错信息:" + ex.Message);

}

}

///

/// 读取表格中某单元格的值,如果单元格是合并单元格,则竖向合并的正常返回,横向合并的抛出异常

///

/// 要读取的数据类型

/// Excel中的某单元格

///

private static A GetValue(ICell cell)

{

//依据单元格数据类型读取数据,并强转为目标类型

switch (cell.CellType)

{

case CellType.Boolean:

return cell.BooleanCellValue.ChangeType();

case CellType.Error:

return ErrorEval.GetText(cell.ErrorCellValue).ChangeType();

case CellType.Numeric:

if (DateUtil.IsCellDateFormatted(cell))

{

return cell.DateCellValue.ChangeType();

}

else

{

return cell.NumericCellValue.ChangeType();

}

case CellType.String:

string strValue = cell.StringCellValue;

if (string.IsNullOrEmpty(strValue))

{

return default(A);

}

else

{

return strValue.ChangeType();

}

case CellType.Formula://公式

switch (cell.CachedFormulaResultType)

{

case CellType.Boolean:

return cell.BooleanCellValue.ChangeType();

case CellType.Error:

return ErrorEval.GetText(cell.ErrorCellValue).ChangeType();

case CellType.Numeric:

if (DateUtil.IsCellDateFormatted(cell))

{

return cell.DateCellValue.ChangeType();

}

else

{

return cell.NumericCellValue.ChangeType();

}

case CellType.String:

string str = cell.StringCellValue;

if (string.IsNullOrEmpty(str))

{

return default(A);

}

else

{

return str.ChangeType();

}

case CellType.Unknown:

case CellType.Blank:

default:

return default(A);

}

case CellType.Unknown:

case CellType.Blank:

default:

return default(A);

}

}

}

类型转换

///

/// 调用Convert.ChangeType

///

/// 要返回的类型

/// 待转换的值

/// 转换后的值

public static T ChangeType(this object token)

{

object result = ChangeType(token, typeof(T));

if (result == null)

{

return default(T);

}

return (T)result;

}

///

/// 把对象类型转换为指定类型

///

/// 要转换的值

/// 目标类型

/// 转化后的指定类型的对象

public static object ChangeType(this object value, Type targetType)

{

if (value == null)

{

return null;

}

if (targetType.IsNullableType())

{

targetType = targetType.GetUnderlyingType();

}

if (targetType.IsEnum)

{

return Enum.Parse(targetType, value.ToString());

}

if (targetType == typeof(Guid))

{

return Guid.Parse(value.ToString());

}

return Convert.ChangeType(value, targetType);

}

导出代码的主体部分

策略接口

///

/// 提供每行数据的操作策略(不同的实现方式,达成不同的导入目标,存储目标不必一定是数据库)

/// 通过GetValue读取某单元格数据

///

public interface ExcelImportHelper

{

///

/// 判断本行数据是否数据库中已存在(有则会进行修改,没有则会新建)

///

/// Excel中的某行数据

/// 不存在则返回null,存在则返回该项数据

T IsExist(IRow row);

///

/// 新数据添加到数据库

///

/// 已完成映射的实体类实例

void Add(T model);

///

/// 更新数据库中的已有数据

///

/// 已完成映射的实体类实例

void Update(T model);

///

/// 提供从表格行数据映射到实体类的方法(解析失败的时候直接要抛出异常)

///

/// Excel中的某行数据

/// 新建的或刚从数据库中读取到的实体类实例

/// 映射失败或数据为空时返回false,则不会录入数据库

bool Map(IRow row, T model);

}

其他部分代码

///

/// 表格导入数据库

/// 也可以是导入DataTable等形式,只要提供不同的策略

///

/// Model的类型

public class ExcelImport where T : new()

{

private ExcelImportHelper helper;

///

/// 构造方法

///

/// 操作策略

public ExcelImport(ExcelImportHelper helper)

{

this.helper = helper;

}

///

/// 处理结果

///

public struct Result

{

private int num; //导入行数

private int num_add; //新增行数

private int num_edit; //修改行数

///

/// 导入行数

///

public int Num

{

get

{

return num;

}

set

{

num = value;

}

}

///

/// 新增行数

///

public int Num_add

{

get

{

return num_add;

}

set

{

num_add = value;

}

}

///

/// 修改行数

///

public int Num_edit

{

get

{

return num_edit;

}

set

{

num_edit = value;

}

}

///

/// 构造函数

///

/// 导入行数

/// 新增行数

/// 修改行数

internal Result(int num, int num_add, int num_edit)

{

this.num = num;

this.num_add = num_add;

this.num_edit = num_edit;

}

}

#region 导入操作

///

/// 表格导入到数据库

///

/// 上传控件的name

/// 最大上传的文件大小(MB)

/// 表格头部所占的高度

/// 表中的数据(只读取表中第一个Sheet)

public Result Inport(string name, int maxLength, int headerRowsNum)

{

Stream stream = null;

try

{

HttpContext context = HttpContext.Current;

HttpRequest request = context.Request;

//验证文件格式大小,返回文件流

stream = GetInputStream(request, name, maxLength);

//逐行读取文件内容并执行导入

return Operation(stream, headerRowsNum);

}

catch (Exception ex)

{

throw ex;

}

finally

{

if (stream != null)

{

stream.Close();

stream.Dispose();

}

}

}

private Result Operation(Stream stream,int headerRowsNum)

{

//操作结果

Result result = new Result(0, 0, 0);

//读取表格内容

try

{

using (stream)

{

//自动识别.xlsx(XSSFWorkbook),.xls(HSSFWorkbook)

IWorkbook workbook = WorkbookFactory.Create(stream);

if (workbook.NumberOfSheets == 0)

throw new Exception("报错信息:文件无数据");

//取第一张表

ISheet sheet = workbook.GetSheetAt(0);

if (sheet.PhysicalNumberOfRows == 0)

throw new Exception("报错信息:文件无数据");

//数据行数

int rowCount = sheet.LastRowNum;

//读取表中所有数据

for (int i = sheet.FirstRowNum + headerRowsNum; i <= rowCount; i++)

{

IRow row = sheet.GetRow(i);

if (row != null)

{

result.Num++;

T model = helper.IsExist(row);

if (model == null)

{

result.Num_add++;

//新建

model = new T();

bool ok = helper.Map(row, model);

if (ok)

{

helper.Add(model);

}

}

else

{

result.Num_edit++;

//修改

bool ok = helper.Map(row, model);

if (ok)

{

helper.Update(model);

}

}

}

}

}

return result;

}

catch (Exception ex)

{

//在异常信息中添加出错位置

throw new Exception("当前读取到第"+ result.Num + "行数据,已添加"+ result .Num_add+ "条,已更新"

+ result.Num_edit + "条," + ex.Message);

}

}

#endregion

}

调用

//策略

private class helper : ExcelImport.ExcelImportHelper

{

public void Add(B_NEWS model)

{

bll.Add(model);

}

public B_NEWS IsExist(IRow row)

{

return null;

}

public bool Map(IRow row, B_NEWS model)

{

model.id = row.GetValue(0);

model.c_info_title = row.GetValue(1);

model.c_info_content = row.GetValue(2);

model.d_list_date = row.GetValue(3);

model.d_add_date = row.GetValue(4);

model.n_is_active = (row.GetValue(5) ? 1 : 0);

model.int1 = row.GetValue(6);

return true;

}

public void Update(B_NEWS model)

{

bll.Update(model);

}

}

protected void daoru(object sender, EventArgs e)

{

new ExcelImport(new helper()).Inport("excel", 10, 2);

}

表格导出

调用者直接接触的操作类

public class ExcelExport

{

///

/// 每列数据的解析方法

///

private List> func = new List>();

private IExcelBuilder builder = new ExcelBuilder();

private string headJson;

///

/// 更换表格建造器

///

/// 自定义的建造器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值