POI实现导入导出excel

article/2025/9/30 13:32:34

poi在日常的导入导出中是比较常用到的,最近也总结了下接触到的poi相关的导入导出的一些代码,有问题可以指出:

package com.poi;import km.org.apache.poi.hssf.usermodel.*;
import km.org.apache.poi.hssf.util.HSSFColor;
import km.org.apache.poi.ss.util.CellRangeAddress;
import km.org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.ss.usermodel.*;import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @Author: zhangximing* @Email: 530659058@qq.com* @Date: 2022/10/17 11:07* @Description: poi导入导出excel*/
public class operateExcel {/*** 导入excel* @param file*/public void importExcel(File file){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// 获取文件输入流,读取文件Workbook workbook = null;try {workbook = WorkbookFactory.create(new FileInputStream(file));} catch (IOException e) {e.printStackTrace();}// 读取第一个工作表,校验sheet文件是否合规。Sheet sheet = checkSheet(workbook);if(null!=sheet){//获取第一行Row firstRow = sheet.getRow(0);//获取总行数 若出现缺少一行的情况则用sheet.getPhysicalNumberOfRows();int totalRowNum = sheet.getLastRowNum();//获取总列数int totalCellNum = firstRow.getLastCellNum();// 遍历行for (int i = 0; i <=totalRowNum; i++) {Row row = sheet.getRow(i);//遍历列System.out.print("第"+(i+1)+"行:");for (int j = 0; j <=totalCellNum; j++){String value = "";if (null != row.getCell(j)){//单独过滤序号if (j > 0){value = getCellDate(row.getCell(j),sdf);}else{value = row.getCell(j).toString().trim();}}System.out.print(value);System.out.print(" ");}System.out.println();}}else{System.out.println("excel格式不合法");}}/*** 导出excel* @param dataList 数据集合* @param title excel内标题* @param exportPath 导出路径(文件路径)*/public void exportExcel(List<List<String>> dataList, String title, String exportPath){HSSFWorkbook wb = new HSSFWorkbook();// 创建一个Excel的SheetHSSFSheet sheet = wb.createSheet("first sheet");// 一般项目data的值需要校验是否为空,这边直接当做不为空处理// 行数int rowLen = dataList.size();// 列数List<String> btDataList = dataList.get(0);int cellLen = btDataList.size();//=========设置首行为标题,多列合并==========// 设置行-下面为第一行HSSFRow row0 = sheet.createRow(0);// 设置高度row0.setHeight((short)500);// 设置列-下面为第一行的第一列HSSFCell cell00 = row0.createCell(0);// 设置大标题字体HSSFFont headfont = setHSSFFontHt(wb,22);// 设置样式HSSFCellStyle headstyle = wb.createCellStyle();// 使用了上面设置的字体样式headstyle.setFont(headfont);headstyle.setLocked(true);// 设置样式setCellCommonStyle(headstyle,0);// 合并单元格:参数说明:1:开始行 2:结束行 3:开始列 4:结束列// 注意,在这里使用表字段名-1来作结束列,因为我们是从0开始数的,所以要减去一个CellRangeAddress range = new CellRangeAddress(0, 0, 0, cellLen - 1);// 将表的合并单元格样式设置进去sheet.addMergedRegion(range);// 标题单元格样式RegionUtil.setBorderTop(HSSFCellStyle.BORDER_THIN, range, sheet,wb);RegionUtil.setBorderRight(HSSFCellStyle.BORDER_THIN, range, sheet,wb);RegionUtil.setBorderLeft(HSSFCellStyle.BORDER_THIN, range, sheet,wb);// 设置表的第一行的第一列的样式cell00.setCellStyle(headstyle);// 设置大标题cell00.setCellValue(title);//=========设置第二行为表头=========HSSFRow row1 = sheet.createRow(1);// 设置字体HSSFFont columnHeadFont = setHSSFFontSt(wb,10);// 字体加粗columnHeadFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 列头的样式HSSFCellStyle columnHeadStyle = wb.createCellStyle();// 设置上面已经设置好的字体样式columnHeadStyle.setFont(columnHeadFont);columnHeadStyle.setLocked(true);// 设置样式setCellCommonStyle(columnHeadStyle,0);// 设置第二行的行高row1.setHeight((short) 750);// 设置表头的值for (int i=0;i<cellLen;i++){HSSFCell cell1 = row1.createCell(i);// 设置风格cell1.setCellStyle(columnHeadStyle);// 设置值cell1.setCellValue(btDataList.get(i));}//=========设置内容=========HSSFFont font = setHSSFFontSt(wb,10);HSSFCellStyle style = wb.createCellStyle();style.setFont(font);setCellCommonStyle(style,1);for (int i=1;i<rowLen;i++){HSSFRow row = sheet.createRow(i+1);//遍历数据并填充List<String> nrDataList = dataList.get(i);for (int j=0;j<nrDataList.size();j++){HSSFCell cell = row.createCell(j);cell.setCellValue(nrDataList.get(j));cell.setCellStyle(style);}}//设置默认宽度autoColumn(sheet);try {System.out.println("excel开始写入至"+exportPath);ByteArrayOutputStream os = new ByteArrayOutputStream();wb.write(os);InputStream input = new ByteArrayInputStream(os.toByteArray());// 测试导出到本地writeToLocal(exportPath,input);// 如果是网页请求可以返回如下:filename是导出时文件名称// Response.ok(input).header("Content-disposition", "attachment;filename=" + new String(filename.getBytes("GB2312"), "ISO8859-1") + ".xls").header("Cache-Control", "no-cache").build();System.out.println("excel完成写入"+exportPath);}catch (Exception e) {System.out.println("导出excel报错,错误信息为:" + e.getMessage());}}/*** 合法返回sheet 不合法返回null* @param workBook* @return*/public Sheet checkSheet(Workbook workBook){if(null == workBook){return null;}Sheet sheet = workBook.getSheetAt(0);//得到sheet的最后一行是否等于0int row = sheet.getLastRowNum();if(0==row){return null;}return sheet;}//设置字体(黑体)public HSSFFont setHSSFFontHt(HSSFWorkbook wb,int fontSize){HSSFFont headfont = wb.createFont();headfont.setFontName("黑体");// 字体大小headfont.setFontHeightInPoints((short) fontSize);return headfont;}//设置字体(宋体)public HSSFFont setHSSFFontSt(HSSFWorkbook wb,int fontSize){HSSFFont headfont = wb.createFont();headfont.setFontName("宋体");// 字体大小headfont.setFontHeightInPoints((short) fontSize);return headfont;}//获取表格时间转换public String getCellDate(Cell cell, SimpleDateFormat sdf){String cellValue = "";//自定义类型或数字类型(可以转换日期)if (cell.getCellType()==CellType.NUMERIC || cell.getCellType()==CellType.FORMULA){Date date = cell.getDateCellValue();cellValue = sdf.format(date);}else if (cell.getCellType()==CellType.STRING){cellValue = cell.toString().trim();cellValue = cellValue.replaceAll("\\/", "-");cellValue = cellValue.replace("年","-");cellValue = cellValue.replace("月","-");cellValue = cellValue.replace("日","");cellValue = cellValue.replace("时","-");cellValue = cellValue.replace("分","-");cellValue = cellValue.replace("秒","");}return cellValue;}/*** 设置样式* @param style* @param isContext 是否为内容 1是*/private void setCellCommonStyle(HSSFCellStyle style,int isContext){//内容自动换行style.setWrapText(true);if (isContext == 1){style.setAlignment(HSSFCellStyle.ALIGN_LEFT);}else{style.setAlignment(HSSFCellStyle.ALIGN_CENTER);}style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);style.setBorderBottom(HSSFCellStyle.BORDER_THIN);style.setBottomBorderColor(HSSFColor.BLACK.index);style.setBorderLeft(HSSFCellStyle.BORDER_THIN);style.setLeftBorderColor(HSSFColor.BLACK.index);style.setBorderRight(HSSFCellStyle.BORDER_THIN);style.setRightBorderColor(HSSFColor.BLACK.index);style.setBorderTop(HSSFCellStyle.BORDER_THIN);style.setTopBorderColor(HSSFColor.BLACK.index);}//设置默认列宽(支持自适应以及换行)private void autoColumn(HSSFSheet sheet){int maxColumn = sheet.getRow(0).getPhysicalNumberOfCells();//先自适应for(int i = 0; i < maxColumn; i++){//该只能针对英文、数字列宽自适应sheet.autoSizeColumn(i);// 解决自动设置列宽中文失效的问题sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);}//最大宽度,超过则自动换行,未超过则自适应int maxWidth = 50;//遍历列,做自适应加宽或换行for(int columnNum = 0; columnNum < maxColumn; columnNum++){int columnWidth = sheet.getColumnWidth(columnNum) / 256;for(int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++){HSSFRow currentRow;if(sheet.getRow(rowNum) == null){currentRow = sheet.createRow(rowNum);}else{currentRow = sheet.getRow(rowNum);}if(currentRow.getCell(columnNum) != null){HSSFCell currentCell = currentRow.getCell(columnNum);try {int length = currentCell.toString().getBytes("GBK").length;if(columnWidth < length + 1){columnWidth = length + 8;}} catch (Exception e) {e.printStackTrace();}}}System.out.println("第"+(columnNum+1)+"列:"+columnWidth+",最大列宽:"+maxWidth);if (columnWidth>maxWidth){columnWidth = maxWidth;}sheet.setColumnWidth(columnNum, columnWidth * 256);}}/*** 将InputStream写入本地文件* @param destination 写入本地目录* @param input 输入流* @throws IOException IOException*/public static void writeToLocal(String destination, InputStream input)throws IOException {int index;byte[] bytes = new byte[1024];FileOutputStream downloadFile = new FileOutputStream(destination);while ((index = input.read(bytes)) != -1) {downloadFile.write(bytes, 0, index);downloadFile.flush();}input.close();downloadFile.close();}public static void main(String[] args) {operateExcel operateExcel = new operateExcel();// 导入exceloperateExcel.importExcel(new File("C:\\Users\\53065\\Desktop\\外出登记台账.xlsx"));List<List<String>> dataList = new ArrayList<>();List<String> btDataList = new ArrayList<>();btDataList.add("名称");btDataList.add("毕业院校");btDataList.add("薪资");btDataList.add("工作地");btDataList.add("简介");dataList.add(btDataList);List<String> nrDataList1 = new ArrayList<>();nrDataList1.add("张三");nrDataList1.add("xx名校1");nrDataList1.add("12k");nrDataList1.add("广州");nrDataList1.add("");dataList.add(nrDataList1);List<String> nrDataList2 = new ArrayList<>();nrDataList2.add("李四");nrDataList2.add("xx名校2");nrDataList2.add("19k");nrDataList2.add("深圳");nrDataList2.add("一名2021年毕业于xx名校2的工程师,爱好打游戏、冲浪,一起么?");dataList.add(nrDataList2);List<String> nrDataList3 = new ArrayList<>();nrDataList3.add("王五");nrDataList3.add("xx本科");nrDataList3.add("8k");nrDataList3.add("中山");nrDataList3.add("没啥简介");dataList.add(nrDataList3);// 导出excel
//        operateExcel.exportExcel(dataList,"名校毕业生调查","D://名校毕业生调查表.xlsx");}
}

导入的excel:
在这里插入图片描述

导入打印结果:
在这里插入图片描述

第一次没进行某些日期转换时,可能出现纯数字的这种情况,设计出了以下方法:

//获取表格时间转换public String getCellDate(Cell cell, SimpleDateFormat sdf){String cellValue = "";//自定义类型或数字类型(可以转换日期)if (cell.getCellType()==CellType.NUMERIC || cell.getCellType()==CellType.FORMULA){Date date = cell.getDateCellValue();cellValue = sdf.format(date);}else if (cell.getCellType()==CellType.STRING){cellValue = cell.toString().trim();cellValue = cellValue.replaceAll("\\/", "-");cellValue = cellValue.replace("年","-");cellValue = cellValue.replace("月","-");cellValue = cellValue.replace("日","");cellValue = cellValue.replace("时","-");cellValue = cellValue.replace("分","-");cellValue = cellValue.replace("秒","");}return cellValue;}

但有个缺点,需要过滤掉不需要转换的数字类型,比如序号这些

修改后结果:
在这里插入图片描述

导出结果:
在这里插入图片描述
这里可以看到,在超过特定的宽度后内容会自动换行。

最后如果是放到服务器端,请求时需要返回HttpServletResponse的,看看下面返回:

return Response.ok(input).header("Content-disposition", "attachment;filename=" + new String(filename.getBytes("GB2312"), "ISO8859-1") + ".xls").header("Cache-Control", "no-cache").build();

在这里插入图片描述
有什么问题大家都可以指出,感谢学习(#.#)


http://chatgpt.dhexx.cn/article/NfutgcQa.shtml

相关文章

java使用Poi导出excel表格

随时随地阅读更多技术实战干货&#xff0c;获取项目源码、学习资料&#xff0c;请关注源代码社区公众号(ydmsq666) 在之前的一篇文章java操作Excel实战干货中展示了使用poi库读取excel表格的的用法&#xff0c;今天演示另一个常用功能&#xff0c;将数据导出到excel中&#xff…

POI导出Excel文件中文乱码

使用POI组件生产Excel文件时中文乱码&#xff0c;总结后可能错误原因如下&#xff1a; 后台导出Excel文件格式混乱 POI组件可生成.xls和.xlsx两种格式的Excel文件&#xff0c;设置文件格式时应注意与导出的格式相匹配。如果文件格式设置出错&#xff0c;则会出现以下错误&…

Java使用poi导出Excel之格式设置

最近接到一个需求&#xff0c;客户不满意原本导出的csv文件&#xff0c;想要导出Excel文件。不就导出Excel文件嘛&#xff0c;小意思&#xff0c;于是乎信心满满从网上扒导出的代码&#xff0c;一顿CV大法&#xff0c;搞定&#xff01;代码如下: import lombok.extern.slf4j.S…

Java使用POI导出Excel

目录 一、前景二、概念2.1. 简介2.2.Excel版本和相关对象2.3.WorkBook2.4.POI依赖 三、POI - 写3.1.代码示例3.2. 性能对比3.3. 测试rowAccessWindowSize3.4. 导出Excel样式设置 四、POI - 读4.1.代码示例4.2.读取不同的数据类型4.3.读取公式 五、POI - 遇到的坑5.1.为什么模板…

Java实现八大排序算法

原文链接&#xff1a; 八大排序算法总结与java实现 - iTimeTraveler 概述 因为健忘&#xff0c;加上对各种排序算法理解不深刻&#xff0c;过段时间面对排序就蒙了。所以决定对我们常见的这几种排序算法进行统一总结&#xff0c;强行学习。首先罗列一下常见的十大排序算法&…

通过java实现八大排序的功能

八大排序(java实现) 常见的排序算法如下&#xff1a; 直接插入排序希尔排序简单选择排序堆排序冒泡排序快速排序归并排序基数排序 它们都属于内部排序&#xff0c;也就是只考虑数据量较小仅需要使用内存的排序算法&#xff0c;他们之间关系如下&#xff1a; 稳定与非稳定 …

c语言基数为3变为基数为10,必须知道的C语言八大排序算法(收藏)

概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用时…

数据结构( 排序)

排序 1、排序的基本概念2、插入排序①.直接插入排序②.折半插入排序③.希尔排序 3、交换排序①.冒泡排序②.快速排序 4、选择排序①.简单选择排序②.树形选择排序③.堆排序 5、归并排序6、基数排序7、总结8、例题与应用 1、排序的基本概念 排序是计算机内经常进行的一种操作&a…

十大经典排序算法python版本_【程序员面试必备】动画详解十大经典排序算法(C语言版)...

欢迎访问我的博客原文 排序算法是程序员必备的基础知识&#xff0c;弄明白它们的原理和实现很有必要。本文中将通过非常细节的动画展示出算法的原理&#xff0c;配合代码更容易理解。 概述 由于待排序的元素数量不同&#xff0c;使得排序过程中涉及的存储器不同&#xff0c;可将…

八大排序算法详解(Java语言实现)

概述 因为健忘&#xff0c;加上对各种排序算法理解不深刻&#xff0c;过段时间面对排序就蒙了。所以决定对我们常见的这几种排序算法进行统一总结&#xff0c;强行学习。首先罗列一下常见的十大排序算法&#xff1a; 直接插入排序希尔排序简单选择排序堆排序冒泡排序快速排序归…

九大排序算法-C语言实现及详解

概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用…

常用的排序算法-C语言

目录 冒泡排序   鸡尾酒排序  选择排序插入排序 二分插入排序  希尔排序  归并排序堆排序快速排序 我们通常所说的排序算法往往指的是内部排序算法&#xff0c;即数据记录在内存中进行排序。 排序算法大体可分为两种&#xff1a; 一种是比较排序&#xff0c;时间复杂度…

九大排序算法详解 - C语言篇

概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用时…

数据结构排序算法总结

学完数据结构已经有好长一段时间了&#xff0c;最近又重新回顾&#xff0c;做一个八大排序的总结&#xff0c;以便后期回顾。 目录 一、插入排序 1.直接插入排序 2.希尔排序 二、交换排序 1.冒泡排序 2.快速排序 三、选择排序 1.简单选择排序 2.堆排序 四、归并排序 …

程序员面试必备——动画详解十大经典排序算法(C语言版)

博客原文地址 排序算法是程序员必备的基础知识&#xff0c;弄明白它们的原理和实现很有必要。本文中将通过非常细节的动画展示出算法的原理&#xff0c;配合代码更容易理解。 概述 由于待排序的元素数量不同&#xff0c;使得排序过程中涉及的存储器不同&#xff0c;可将排序方…

【C语言八大排序思想及代码实现】

文章目录 系列文章目录前言一、冒泡排序二、选择排序三、直接插入排序四、希尔排序五、归并排序六、基数&#xff08;桶&#xff09;排序七、堆排序八、快速排序总结 一、冒泡排序 思想&#xff1a; 从第一个数开始依次向后进行比较&#xff08;第一个和第二个比较然后第二个…

经典排序算法总结(C实现)

一 排序算法介绍 1.0 排序的概述 在计算机计算和处理加工数据时&#xff0c;经常会直接或间接地涉及到数据的排序问题。可以简单地将排序操作理解为&#xff1a;将一个按值无序的数据序列转换成为一个按值有序的数据序列的过程。例如&#xff0c;将一个无序的数组 A[5] {7, …

主元排序法c语言程序,C/C++实现八大排序算法汇总

概述排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用时间…

内排序算法小结

针对近两天所复盘的《数据结构》中的内排序部分&#xff0c;做一个小总结。尽力在最大程度上把考点重现出来&#xff0c;以便复盘之需。 本文所有算法均使用 C语言 实现。 本博客仅从个人的考点梳理为基&#xff0c;内容相较全局还有很多缺失&#xff0c;读者请权衡参考。 目…

数据结构-考研难点代码突破(C/C++/Java排序算法,性能及其稳定性分析(内部排序))

文章目录 1. 内部排序的基本种类2. 插入排序Ⅰ直接插入排序性能与稳定性分析Ⅱ 折半插入排序性能与稳定性分析Ⅲ 希尔排序性能与稳定性分析 3. 交换排序Ⅰ 冒泡排序性能与稳定性分析Ⅱ 快速排序key值选取&#xff08;三数取中&#xff09;三种交换方法① hoare左右指针② 挖坑法…