Apache POI 使用Java处理Excel数据 进阶

1.POI入门教程链接

http://t.csdnimg.cn/Axn4Picon-default.png?t=N7T8http://t.csdnimg.cn/Axn4P建议:从入门看起会更好理解POI对Excel数据的使用和处理

记得引入依赖:

         <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.0.1</version></dependency>

2.POI对单元格样式处理

// JUnit的@Test注解表示这是一个测试方法@Testvoid testExcel() throws IOException {// 创建一个新的XSSFWorkbook对象,这是操作Excel文件的核心类XSSFWorkbook workbook = new XSSFWorkbook();// 在工作簿中创建一个名为"sheet1"的工作表XSSFSheet sheet = workbook.createSheet("sheet1");// 在工作表中创建第三行(行索引从0开始)Row row = sheet.createRow(2);// 在该行中创建第三个单元格(列索引从0开始)Cell cell = row.createCell(2);// 设置单元格的值为"Hello World 2024"cell.setCellValue("Hello World 2024");// 创建一个单元格样式CellStyle cellStyle = workbook.createCellStyle();// 设置单元格的上下左右边框为细线cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setBorderLeft(BorderStyle.THIN);cellStyle.setBorderRight(BorderStyle.THIN);// 创建一个字体对象Font font = workbook.createFont();// 设置字体为"宋体"font.setFontName("宋体");// 设置字体大小为32磅font.setFontHeightInPoints((short) 32);// 将字体应用到单元格样式中cellStyle.setFont(font);// 设置行高为50磅row.setHeightInPoints((short) 50);// 设置第三列的宽度为100 * 365(单位是1/256个字符宽度)sheet.setColumnWidth(2, 100 * 365);// 将单元格样式应用到单元格上cell.setCellStyle(cellStyle);// 创建一个文件输出流,用于将Excel文件写入磁盘FileOutputStream out = new FileOutputStream("D:\\Desktop\\JavaCode\\poi-demo\\src\\main\\resources\\test.xlsx");// 将工作簿写入输出流workbook.write(out);// 关闭输出流out.close();}

3.将图片写入Excel表格中

  // JUnit的@Test注解表示这是一个测试方法@Testvoid testDrawExcel() throws IOException {// 创建一个新的XSSFWorkbook对象,这是操作Excel文件的核心类XSSFWorkbook workbook = new XSSFWorkbook();// 在工作簿中创建一个名为"sheet1"的工作表XSSFSheet sheet = workbook.createSheet("sheet1");// 创建一个文件输入流,用于读取图片文件FileInputStream in = new FileInputStream("D:\\Desktop\\test.jpg");// 创建一个字节数组,长度为图片文件的大小byte[] bytes = new byte[in.available()];// 读取图片文件到字节数组in.read(bytes);// 关闭输入流in.close();// 将图片添加到工作簿,并返回图片的索引int index = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);// 获取创建助手,用于创建绘图对象CreationHelper helper = workbook.getCreationHelper();// 创建绘图对象,用于在工作表中绘制图片XSSFDrawing drawing = sheet.createDrawingPatriarch();// 创建客户端锚点,用于指定图片的位置ClientAnchor anchor = helper.createClientAnchor();// 设置图片的起始行anchor.setRow1(0);// 设置图片的起始列anchor.setCol1(1);// 创建图片对象,并将其插入到工作表中XSSFPicture picture = drawing.createPicture(anchor, index);// 调整图片大小以适应单元格picture.resize();// 创建一个文件输出流,用于将Excel文件写入磁盘FileOutputStream out = new FileOutputStream("D:\\Desktop\\JavaCode\\poi-demo\\src\\main\\resources\\test.xlsx");// 将工作簿写入输出流workbook.write(out);// 关闭输出流out.close();}

4.使用模版Excel

如何想根据模版进行创建Excel表格。而不是直接覆盖创建新的Excel表格的方式:

// JUnit的@Test注解表示这是一个测试方法@Testvoid testDrawExcel() throws IOException {// 使用Spring的ClassPathResource来加载类路径下的资源文件Resource resource = new ClassPathResource("test.xlsx");// 获取资源文件的FileInputStreamFileInputStream resourceIn = new FileInputStream(resource.getFile());// 使用FileInputStream加载现有工作簿XSSFWorkbook workbook = new XSSFWorkbook(resourceIn);// 获取工作簿中的第一个工作表XSSFSheet sheet = workbook.getSheetAt(0);// 创建一个文件输入流,用于读取图片文件FileInputStream in = new FileInputStream("D:\\Desktop\\test.jpg");// 创建一个字节数组,长度为图片文件的大小byte[] bytes = new byte[in.available()];// 读取图片文件到字节数组in.read(bytes);// 关闭输入流in.close();// 将图片添加到工作簿,并返回图片的索引int index = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);// 获取创建助手,用于创建绘图对象CreationHelper helper = workbook.getCreationHelper();// 获取工作表中的绘图对象,如果没有则创建Drawing<?> drawing = sheet.createDrawingPatriarch();// 创建客户端锚点,用于指定图片的位置ClientAnchor anchor = helper.createClientAnchor();// 设置图片的起始行为第11行(行索引从0开始)anchor.setRow1(10);// 设置图片的起始列为第2列(列索引从0开始)anchor.setCol1(1);// 创建图片对象,并将其插入到工作表中Picture picture = drawing.createPicture(anchor, index);// 调整图片大小以适应单元格picture.resize();// 创建一个文件输出流,用于将Excel文件写入磁盘FileOutputStream out = new FileOutputStream("D:\\Desktop\\JavaCode\\poi-demo\\src\\main\\resources\\test.xlsx");// 将工作簿写入输出流workbook.write(out);// 关闭输出流out.close();}

5.自定义Excel工具类

(1)自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAttribute {/** 对应的列名称 */String name() default "";/** 列序号 */int sort();/** 字段类型对应的格式 */String format() default "";}

(2) 导出工具类:

public class ExcelExportUtil<T> {private int rowIndex;private int styleIndex;private String templatePath;private Class clazz;private  Field fields[];public ExcelExportUtil(Class clazz,int rowIndex,int styleIndex) {this.clazz = clazz;this.rowIndex = rowIndex;this.styleIndex = styleIndex;fields = clazz.getDeclaredFields();}/*** 基于注解导出*/public void export(HttpServletResponse response,InputStream is, List<T> objs,String 
fileName) throws Exception {XSSFWorkbook workbook = new XSSFWorkbook(is);Sheet sheet = workbook.getSheetAt(0);CellStyle[] styles = getTemplateStyles(sheet.getRow(styleIndex));AtomicInteger datasAi = new AtomicInteger(rowIndex);for (T t : objs) {Row row = sheet.createRow(datasAi.getAndIncrement());for(int i=0;i<styles.length;i++) {Cell cell = row.createCell(i);cell.setCellStyle(styles[i]);for (Field field : fields) {if(field.isAnnotationPresent(ExcelAttribute.class)){field.setAccessible(true);ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);if(i == ea.sort()) {cell.setCellValue(field.get(t).toString());}}}}}fileName = URLEncoder.encode(fileName, "UTF-8");response.setContentType("application/octet-stream");response.setHeader("content-disposition", "attachment;filename=" + new 
String(fileName.getBytes("ISO8859-1")));response.setHeader("filename", fileName);workbook.write(response.getOutputStream());}public CellStyle[] getTemplateStyles(Row row) {CellStyle [] styles = new CellStyle[row.getLastCellNum()];for(int i=0;i<row.getLastCellNum();i++) {styles[i] = row.getCell(i).getCellStyle();}return styles;}
}

(3)导入工具类:

public class ExcelImportUtil<T> {private Class clazz;private  Field fields[];public ExcelImportUtil(Class clazz) {this.clazz = clazz;fields = clazz.getDeclaredFields();}/*** 基于注解读取excel*/public List<T> readExcel(InputStream is, int rowIndex,int cellIndex) {List<T> list = new ArrayList<T>();T entity = null;try {XSSFWorkbook workbook = new XSSFWorkbook(is);Sheet sheet = workbook.getSheetAt(0);// 不准确int rowLength = sheet.getLastRowNum();System.out.println(sheet.getLastRowNum());for (int rowNum = rowIndex; rowNum <= sheet.getLastRowNum(); rowNum++) {Row row = sheet.getRow(rowNum);entity = (T) clazz.newInstance();System.out.println(row.getLastCellNum());for (int j = cellIndex; j < row.getLastCellNum(); j++) {Cell cell = row.getCell(j);for (Field field : fields) {if(field.isAnnotationPresent(ExcelAttribute.class)){field.setAccessible(true);ExcelAttribute ea = 
field.getAnnotation(ExcelAttribute.class);if(j == ea.sort()) {field.set(entity, covertAttrType(field, cell));}}}}list.add(entity);}} catch (Exception e) {e.printStackTrace();}return list;}/*** 类型转换 将cell 单元格格式转为 字段类型
*/private Object covertAttrType(Field field, Cell cell) throws Exception {String fieldType = field.getType().getSimpleName();if ("String".equals(fieldType)) {return getValue(cell);}else if ("Date".equals(fieldType)) {return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(getValue(cell)) ;}else if ("int".equals(fieldType) || "Integer".equals(fieldType)) {return Integer.parseInt(getValue(cell));}else if ("double".equals(fieldType) || "Double".equals(fieldType)) {return Double.parseDouble(getValue(cell));}else {return null;}}/*** 格式转为String* @param cell* @return*/public String getValue(Cell cell) {if (cell == null) {return "";}switch (cell.getCellType()) {case STRING:return cell.getRichStringCellValue().getString().trim();case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {Date dt = DateUtil.getJavaDate(cell.getNumericCellValue());return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(dt);} else {// 防止数值变成科学计数法String strCell = "";Double num = cell.getNumericCellValue();BigDecimal bd = new BigDecimal(num.toString());if (bd != null) {strCell = bd.toPlainString();}// 去除 浮点型 自动加的 .0if (strCell.endsWith(".0")) {strCell = strCell.substring(0, strCell.indexOf("."));}return strCell;}case BOOLEAN:return String.valueOf(cell.getBooleanCellValue());default:return "";}}

(4)工具类的使用

在User实体上对导出的字段名加上自定义注解@ExcelAttribute(序列号)

导入数据:

List<User> list = new ExcelImportUtil(User.class).readExcel(is, 1, 2);

导出数据:

@GetMapping("/export/{month}")public void export(@PathVariable(name = "month") String month) throws Exception {//1.构造数据List<EmployeeReportResult> list = 
userCompanyPersonalService.findByReport(companyId,month+"%");//2.加载模板流数据Resource resource = new ClassPathResource("excel-template/hr-demo.xlsx");FileInputStream fis = new FileInputStream(resource.getFile());new ExcelExportUtil(EmployeeReportResult.class,2,2).export(response,fis,list,"人事报表.xlsx");}

6.处理大量数据的文件(SXSSF)

(1)SXSSF和XSSF的区别

SXSSF和XSSF都是Apache POI库中用于处理Excel文件的API,它们属于POI项目中用于操作Excel 2007 OOXML (.xlsx)文件的组件。以下是SXSSF和XSSF的主要区别:

  1. 内存使用

    • XSSF:为处理大型Excel文件提供了完整的API支持,但它会将整个工作簿加载到内存中。这意味着对于非常大的Excel文件,它可能会消耗大量的Java堆内存。
    • SXSSF:是XSSF的流式扩展,目的是减少内存消耗。它不会将整个工作簿保留在内存中,而是仅保持一定数量的行在内存中,其余的行将被写入磁盘上的临时文件中。
  2. 性能

    • 使用XSSF处理非常大的Excel文件时,可能会遇到性能瓶颈,因为它需要更多的内存资源。
    • SXSSF在处理大型文件时性能更优,因为它使用了更少的内存,并且它的写入操作是流式的。
  3. 功能限制

    • XSSF提供了完整的Excel文件处理能力,但由于其内存占用较大,处理大型文件时可能会出现问题。
    • SXSSF由于使用了流式处理,因此有一些限制。例如,它不支持获取或设置单元格样式,也不支持插入或删除行。
  4. 使用场景

    • 如果您的应用程序需要处理中等大小的Excel文件,并且需要完整的Excel功能,XSSF是一个不错的选择。
    • 如果您需要处理大型Excel文件,并且可以接受SXSSF的一些限制,那么SXSSF可能是更好的选择。

(2)代码实现:

自定义处理器

/自定义Sheet基于Sax的解析处理器
public class SheetHandler implements XSSFSheetXMLHandler.SheetContentsHandler {//封装实体对象private PoiEntity entity;/*** 解析行开始*/@Overridepublic void startRow(int rowNum) {if (rowNum >0 ) {entity = new PoiEntity();}}/* * 解析每一个单元格*/@Overridepublic void cell(String cellReference, String formattedValue, XSSFComment comment) {if(entity != null) {switch (cellReference.substring(0, 1)) {case "A":entity.setId(formattedValue);break;case "B":entity.setBreast(formattedValue);break;case "C":entity.setAdipocytes(formattedValue);break;case "D":entity.setNegative(formattedValue);break;case "E":entity.setStaining(formattedValue);break;case "F":entity.setSupportive(formattedValue);break;default:break;}}}/*** 解析行结束*/public void endRow(int rowNum) {System.out.println(entity);}//处理头尾public void headerFooter(String text, boolean isHeader, String tagName) {}
}

自定义解析器

/*** 自定义Excel解析器*/
public class ExcelParser {public void parse (String path) throws Exception {//1.根据Excel获取OPCPackage对象OPCPackage pkg = OPCPackage.open(path, PackageAccess.READ);try {//2.创建XSSFReader对象XSSFReader reader = new XSSFReader(pkg);//3.获取SharedStringsTable对象SharedStringsTable sst = reader.getSharedStringsTable();//4.获取StylesTable对象StylesTable styles = reader.getStylesTable();//5.创建Sax的XmlReader对象XMLReader parser = XMLReaderFactory.createXMLReader();//6.设置处理器parser.setContentHandler(new XSSFSheetXMLHandler(styles,sst, new 
SheetHandler(), false));XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) 
reader.getSheetsData();//7.逐行读取while (sheets.hasNext()) {InputStream sheetstream = sheets.next();InputSource sheetSource = new InputSource(sheetstream);try {parser.parse(sheetSource);} finally {sheetstream.close();}}} finally {pkg.close();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/46208.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM高频面试点

文章目录 JVM内存模型程序计数器Java虚拟机栈本地方法栈Java堆方法区运行时常量池 Java对象对象的创建如何为对象分配内存 对象的内存布局对象头实例数据对齐填充 对象的访问定位 垃圾收集器找到垃圾引用计数法可达性分析&#xff08;根搜索法&#xff09; 引用概念的扩充回收方…

【Socket套接字编程】(实现TCP和UDP的通信)

&#x1f387;&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳&#xff0c;欢迎大佬指点&#xff01; 人生格言: 当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友…

创建通用JS公共模块并发布至npm

title: 创建通用JS公共模块并发布至npm tags: UMD rollup verdaccio npm categories: 模块化 概要内容 创建&#xff1a;JS公共模块 打包&#xff1a;使用rollup 打包公共模块 发布&#xff1a;js公共模块至verdaccio平台 发布&#xff1a;js公共模块至npm平台 如何创建JS公共模…

【PostgreSQL】Windows 上安装 PostgreSQL 16版本

博主介绍:✌全网粉丝20W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

基于jeecgboot-vue3的Flowable流程仿钉钉流程设计器-支持VForm3表单的选择与支持

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、初始化的时候加载表单 /** 查询表单列表 */ const getFormList () > {listForm().then(res > formOptions.value res.result.records) } 2、开始节点的修改&#xff0c;增加表…

计算机的错误计算(三十四)

摘要 用错数预测 &#xff08;或 pow(a,x)&#xff09;函数的结果中含有的错误数字的个数&#xff0c;并与Visual Studio 和Excel 的输出中含有的错误位数相比较。结果显示&#xff0c;预测与实际一致。 对于 &#xff08;或 pow(a,x)&#xff09;函数&#xff0c;根据 与 的不…

3.RabbitMQ安装-Centos7

官方网址&#xff1a;gInstalling RabbitMQ | RabbitMQ 安装前提&#xff0c;需要一个erlang语言环境。 下载 erlang: Releases rabbitmq/erlang-rpm GitHub rabbitmq-server: 3.8.8 Releases rabbitmq/rabbitmq-server GitHub 安装命令 (说明i表示安装&#xff…

SCI一区级 | Matlab实现SSA-CNN-GRU-Multihead-Attention多变量时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【SCI一区级】Matlab实现SSA-CNN-GRU-Multihead-Attention麻雀算法优化卷积门控循环单元融合多头注意力机制多变量时间序列预测&#xff0c;要求Matlab2023版以上&#xff1b; 2.输入多个特征&#xff0c;输出单个…

一文掌握Prometheus实现页面登录认证并集成grafana

一、接入方式 以保护Web站点的访问控制&#xff0c;如HTTP 服务器配置中实现安全的加密通信和身份验证&#xff0c;保护 Web 应用程序和用户数据的安全性。 1.1 加密密码 通过httpd-tools工具包来进行Web站点加密 yum install -y httpd-tools方式一&#xff1a;通过htpasswd生…

智慧物流园区整体架构方案(46页PPT)

PPT介绍 将深入探讨如何通过高度集成的信息技术和物联网设备&#xff0c;打造一个自动化、高效与可持续发展的现代物流体系。该方案从智能感知层开始&#xff0c;利用传感器、RFID技术、GPS等手段实时采集物流数据&#xff1b;接着是网络传输层&#xff0c;借助高速且稳定的通信…

姓名配对测试源码

源码简介 姓名配对测试源码&#xff0c;输入两人姓名即可测试缘分&#xff0c;可查看朋友到底喜欢谁的趣味源码。 自己手动在数据库里修改数据&#xff0c;数据库里有就会优先查询数据库的信息&#xff0c; 没设置的话第一次查询缘分都是非常好的 95-99&#xff0c;第二次查…

C++ map和set的使用

目录 0.前言 1.关联式容器 2.键值对 3.树形结构的关联式容器 3.1树形结构的特点 3.2树形结构在关联式容器中的应用 4.set 4.1概念与性质 4.2使用 5.multiset 5.1概念与性质 5.2使用 6.map 6.1概念与性质 6.2使用 7.multimap 7.1概念与性质 7.2使用 8.小结 &a…

Spring MVC 中 HttpMessageConverter 转换器

1. Spring MVC 中 HttpMessageConverter 转换器 文章目录 1. Spring MVC 中 HttpMessageConverter 转换器2. 补充&#xff1a;什么是 HTTP 消息3. 转换器3.1 转换器转换的是什么 4. Spring MVC中的 AJAX 请求5. ResponseBody 将服务器端的 return 返回值转化为“字符串(JSON格式…

rtf是什么格式的文件?rtf格式和word的区别是什么?

RTF是什么格式的文件? RTF&#xff08;富文本格式&#xff0c;Rich Text Format&#xff09;和Word文档&#xff08;以.doc和.docx为扩展名的Microsoft Word文档&#xff09;是两种常用的文本文件格式。它们在文件结构、兼容性、功能和使用场景等方面存在一些显著差异。 比如…

arcgis怎么选取某个指定区域地方的数据,比如从全国乡镇数据选取长沙市乡镇数据

一共5个步骤&#xff0c;没一句废话&#xff0c;耐心看完。 1、如图&#xff0c;先将数据加载到arcgis里面&#xff0c;我们要选取里面长沙市的范围数据。 2、选取长沙市的语句 “市” like ‘长沙%’ 切记&#xff0c;切记&#xff0c;切记。所有符号要在 输入法英文状态…

微信小程序 vant-weapp的 SwipeCell 滑动单元格 van-swipe-cell 滑动单元格不显示 和 样式问题 滑动后删除样式不显示

在微信小程序开发过程中 遇到个坑 此处引用 swipeCell 组件 刚开始是组件不显示 然后又遇到样式不生效 首先排除问题 是否在.json文件中引入了组件 {"usingComponents": {"van-swipe-cell": "vant/weapp/swipe-cell/index","van-cell-gro…

电脑系统重装数据被格式化,那些文件还有办法恢复吗?

在日常使用电脑的过程中&#xff0c;系统重装或格式化操作是常见的维护手段&#xff0c;尤其是在遇到系统崩溃、病毒感染或需要升级系统时。然而&#xff0c;这一操作往往伴随着数据丢失的风险&#xff0c;尤其是当C盘&#xff08;系统盘&#xff09;和D盘&#xff08;或其他数…

linux|多线程(一)

主要介绍了为什么要有线程 和线程的调用 和简单的对线程进行封装。 背景知识 a.重谈地址空间 我们知道物理内存的最小单元大小是4kB 物理内存是4G那么这样的单元友1M个 操作系统先描述再组织struct page[1M] 对于32位数据字长的机器&#xff0c;页表有2^32条也就是4G条&#…

LabVIEW Communications LTE Application Framework 读书笔记

目录 硬件要求一台设备2台USRPUSRP-2974 示例项目的组件文件夹结构DL Host.gcompeNodeB Host.gcompUE Host.gcompBuildsCommonUSRP RIOLTE 操作模式DLeNodeBUE 项目组件单机双机UDP readUDP writeMAC TXMAC RXDL TX PHYDL RX PHYUL TX PHYUL RX PHYSINR calculationRate adapta…

R语言优雅的把数据基线表(表一)导出到word

基线表&#xff08;Baseline Table&#xff09;是医学研究中常用的一种数据表格&#xff0c;用于在研究开始时呈现参与者的初始特征和状态。这些特征通常包括人口统计学数据、健康状况和疾病史、临床指标、实验室检测、生活方式、社会经济等。 本人在既往文章《scitb包1.6版本发…