文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java操作Excel文件解析与读写方法详解

2022-11-13 19:25

关注

一、概述

在应用程序的开发过程中,经常需要使用 Excel 文件来进行数据的导入或导出。所以,在通过Java语言实现此 类需求的时候,往往会面临着Excel文件的解析(导入)或生成(导出)。

在Java技术生态圈中,可以进行Excel文件处理的主流技术包括: Apache POI 、 JXL 、 Alibaba EasyExcel 等。

二、Apache POI

Apache POI 是用 Java 编写的免费开源的跨平台的 Java API , Apache POI 提供 给 Java 程序对 Microsoft Office 格式档案进行读写功能的 API 开源类库。

它分别提供对不同格式文件的解析:

三、XSSF解析Excel文件

HSSF 用于解析旧版本(*.xls)Excel文件,由于旧版本的Excel文件只能存在65535行数据,所以目前已经不常用。所以 目前主要采用 XSSF 进行新版本(*.xlsx)Exce文件的解析。

1.Workbook(Excel文件)

Workbook 接口代表一个 Excel 文件,用于创建或加载(解析) Excel 文件。常见实现类是 XSSFWorkbook 。

创建Excel文件

try (Workbook workbook = new XSSFWorkbook();
				FileOutputStream fos = new FileOutputStream("c:\\test\\temp.xlsx")) {
    workbook.write(fos);
} catch (IOException e) {
    e.printStackTrace();
}

解析Excel文件

// 输入流
FileInputStream fis = new FileInputStream("c:\\test\\1627356554991.xlsx");
// Excel文件对象
Workbook workbook = new XSSFWorkbook(fis);

2.Sheet(工作簿)

通过 Workbook 来进行工作簿 Sheet 对象的获取或创建

创建工作簿

// 按照默认名称创建工作簿
Sheet sheet1 = workbook.createSheet();
// 按照自定义名称创建工作簿
Sheet sheet2 = workbook.createSheet("自定义工作簿2");

获取工作簿

// 按照工作簿下标获取Sheet
Sheet sheet01 = workbook.getSheetAt(0);
// 按照工作簿名称获取Sheet
Sheet sheet02 = workbook.getSheet("Sheet0");

获取工作簿的数量

int n = workbook.getNumberOfSheets();

3.Row(数据行)

通过 Sheet 来进行数据行 Row 对象的获取或创建

创建数据行

Row row = sheet.createRow(0);

获取首行下标和尾行下标

int first = sheet.getFirstRowNum();
int last = sheet.getLastRowNum();

根据下标获取指定行

Row row = sheet.getRow(0);

遍历所有行

for(Row row : sheet) {
    System.out.println(row);
}

遍历指定区域行

for (int i = 1; i <= sheet.getLastRowNum(); i++) {
    Row row = sheet.getRow(i);
    System.out.println(row);
}

4.Cell(单元格)

通过 Row 来进行单元格 Cell 对象的获取或创建。

创建单元格

Cell cell0 = row.createCell(0);

设置单元格值

cell0.setCellValue(UUID.randomUUID().toString());

根据下标获取单元格

Cell cell = row.getCell(1);

遍历所有单元格

for(Cell cell : row) {}

获取单元格的类型

CellType type = cell.getCellType();

设置单元格样式

// 创建单元格样式
DataFormat dataFormat = workbook.createDataFormat();
Short formatCode = dataFormat.getFormat("yyyy-MM-dd HH:mm:ss");
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setDataFormat(formatCode);
// 为当前行创建单元格
Cell cell1 = row.createCell(1);
cell1.setCellStyle(cellStyle); // 设置单元格样式
cell1.setCellValue(new Date()); // 保存当前日期时间至本单元格

设置单元格对齐

// 创建单元格样式
CellStyle cellStyle = workbook.createCellStyle();
//设置单元格的水平对齐类型。 此时水平居中
cellStyle.setAlignment(HorizontalAlignment.CENTER);
// 设置单元格的垂直对齐类型。 此时垂直靠底边
cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);

四、超大Excel文件读写

1.使用POI写入

使用 SXSSFWorkbook 进行写入,通过设置 SXXFWorkbook 的构造参数,可以设置每次在内存中保持的行 数,当达到这个值的时候,那么会把这些数据 flush 到磁盘上,这样就不会出现内存不够的情况。

try (Workbook workbook = new SXSSFWorkbook(100);
				FileOutputStream fos = new FileOutputStream("c:\\test\\temp.xlsx")) {
    Sheet sheet1 = workbook.createSheet();
    for (int i = 0; i <= 1000000; i++) {
        Row row = sheet1.createRow(i);
        Cell cell0 = row.createCell(0);
        cell0.setCellValue(UUID.randomUUID().toString());
        Cell cell1 = row.createCell(1);
        cell1.setCellValue(new Date());
    }
    workbook.write(fos);
} catch (IOException e) {
    e.printStackTrace();
}

但是读取超大Excel时POI会把文件的所有内容都加载到内存中,很容易占用大量内存;甚至发生out of memory异常。

2.使用EasyExcel

例:

//准备实体类
public class Order {
    @ExcelProperty("订单编号")
	private String orderId; // 订单编号
    @ExcelProperty("支付金额")
	@NumberFormat("¥#,###")
	private Double payment; // 支付金额
    @ExcelProperty(value = "创建日期",converter = LocalDateTimeConverter.class)
	private LocalDateTime creationTime; // 创建时间
	public Order() {
		this.orderId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss"))
				+ UUID.randomUUID().toString().substring(0, 5);
		this.payment = Math.random() * 10000;
		this.creationTime = LocalDateTime.now();
	}
	public String getOrderId() {
		return orderId;
	}
	public void setOrderId(String orderId) {
		this.orderId = orderId;
	}
	public Double getPayment() {
		return payment;
	}
	public void setPayment(Double payment) {
		this.payment = payment;
	}
	public LocalDateTime getCreationTime() {
		return creationTime;
	}
	public void setCreationTime(LocalDateTime creationTime) {
		this.creationTime = creationTime;
	}
	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", payment=" + payment + ", creationTime=" + creationTime + "]";
	}
}
//准备Converter转换类
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
	@Override
	public Class<LocalDateTime> supportJavaTypeKey() {
		return LocalDateTime.class;
	}
	@Override
	public CellDataTypeEnum supportExcelTypeKey() {
		return CellDataTypeEnum.STRING;
	}
	@Override
	public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
			GlobalConfiguration globalConfiguration) {
		return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
	}
	@Override
	public CellData<String> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty,
			GlobalConfiguration globalConfiguration) {
		return new CellData<>(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
	}
}

写入数据

import java.util.ArrayList;
import java.util.List;
import com.alibaba.excel.EasyExcel;
public class Demo01 {
	public static void main(String[] args) {
		long begin = System.currentTimeMillis();
		// 写入100w
        EasyExcel.write("D:\\java.workspace\\1000W.xlsx", Order.class)
                 .sheet("订单列表")
                 .doWrite(data());
        long end = System.currentTimeMillis();
		System.out.println("共耗时"+(end-begin)+"毫秒");
    }
    // 创建100w条订单数据
    private static List<Order> data() {
        List<Order> list = new ArrayList<Order>();
        for (int i = 0; i < 1000000; i++) {
            list.add(new Order());
        }
        return list;
    }
}

读取数据

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
public class Demo02 {
	public static void main(String[] args) {
		//用于保存读取到的结果
		List<Order> orderList = new ArrayList<Order>();
		//读取
		EasyExcel.read("D:\\java.workspace\\1000W.xlsx", Order.class,new AnalysisEventListener<Order>() {
		    @Override
		    public void invoke(Order order, AnalysisContext arg1) {
		        // 读取每条数据
		        orderList.add(order);
		    }
		    @Override
		    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
		        // 读取到列头
		        System.out.println(headMap);
		    }
		    @Override
		    public void doAfterAllAnalysed(AnalysisContext arg0) {
		        // 读取完毕
		        System.out.println("END");
		    }
		}).sheet().doRead();
		//遍历
		for(Order order : orderList) {
			System.out.println(order);
		}
	}
}

到此这篇关于Java操作Excel文件解析与读写方法详解的文章就介绍到这了,更多相关Java Excel文件解析内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯