该系列为java工具类系列,主要展示100个常用的java工具类。

此文重点讲述:多种方式解析Excel。

本文目录:

通过List生成Excel文件

解析Excel文件(入参是MultipartFile)

解析Excel文件(入参是Excel本地路径)


一、通过List生成Excel文件

import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; /** * @Author 程序幻境 * @Date 2022/11/19 * @Version 1.0 */ class ExcelUtils { private static ExcelUtils instance = new ExcelUtils(); private ExcelUtils(){} public static ExcelUtils getInstance(){ return instance; } /** * 将 List> 类型的数据导出为 Excel * 默认 Excel 文件的输出路径为 项目根目录下 * 文件名为 filename + 时间戳 + .xlsx * * @param mapList 数据源(通常为数据库查询数据) * @param filename 文件名前缀, 实际文件名后会加上日期 * @param title 表格首行标题 * @return 文件输出路径 */ public String createExcel(List> mapList, String filename, String title) { //获取数据源的 key, 用于获取列数及设置标题 Map map = mapList.get(0); Set stringSet = map.keySet(); ArrayList headList = new ArrayList<>(stringSet); //定义一个新的工作簿 XSSFWorkbook wb = new XSSFWorkbook(); //创建一个Sheet页 XSSFSheet sheet = wb.createSheet(title); //设置行高 sheet.setDefaultRowHeight((short) (2 * 256)); //为有数据的每列设置列宽 for (int i = 0; i < headList.size(); i++) { sheet.setColumnWidth(i, 8000); } //设置单元格字体样式 XSSFFont font = wb.createFont(); font.setFontName("等线"); font.setFontHeightInPoints((short) 16); //在sheet里创建第一行,并设置单元格内容为 title (标题) XSSFRow titleRow = sheet.createRow(0); XSSFCell titleCell = titleRow.createCell(0); titleCell.setCellValue(title); //合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列 sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headList.size() - 1)); // 创建单元格文字居中样式并设置标题单元格居中 XSSFCellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(HorizontalAlignment.CENTER); titleCell.setCellStyle(cellStyle); //获得表格第二行 XSSFRow row = sheet.createRow(1); //根据数据源信息给第二行每一列设置标题 for (int i = 0; i < headList.size(); i++) { XSSFCell cell = row.createCell(i); cell.setCellValue(headList.get(i)); } XSSFRow rows; XSSFCell cells; //循环拿到的数据给所有行每一列设置对应的值 for (int i = 0; i < mapList.size(); i++) { //在这个sheet页里创建一行 rows = sheet.createRow(i + 2); //给该行数据赋值 for (int j = 0; j < headList.size(); j++) { String value = mapList.get(i).get(headList.get(j)).toString(); cells = rows.createCell(j); cells.setCellValue(value); } } Date date = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); // 使用项目根目录, 文件名加上时间戳 String path = System.getProperty("user.dir") + "\" + filename + dateFormat.format(date) + ".xlsx"; try { File file = new File(path); FileOutputStream fileOutputStream = new FileOutputStream(file); wb.write(fileOutputStream); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } return path; } public static void main(String[] args) { List> list = new ArrayList<>(); for (int i = 0; i < 3; i++) { Map map = new HashMap<>(); map.put("测试1", i); map.put("测试2", i); map.put("测试3", i); list.add(map); } ExcelUtils.getInstance().createExcel(list,"data","测试数据"); } }


二、解析Excel文件(入参是Excel本地路径)

/** * @Author 程序幻境 * @Date 2022/11/19 * @Version 1.0 */ import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; /** * 解析excel 上传数据 */ public class ExcelUtil { private static final Logger log = Logger.getLogger(ExcelUtil.class); /** * 解析excel * @param file * @return * @throws IOException */ public static List getExcelData(MultipartFile file) throws IOException{ checkFile(file); //获得Workbook工作薄对象 Workbook workbook = getWorkBook(file); //创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回 List list = new ArrayList(); if(workbook != null){ for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){ //获得当前sheet工作表 Sheet sheet = workbook.getSheetAt(sheetNum); if(sheet == null){ continue; } //获得当前sheet的开始行 int firstRowNum = sheet.getFirstRowNum(); //获得当前sheet的结束行 int lastRowNum = sheet.getLastRowNum(); //循环除了所有行,如果要循环除第一行以外的就firstRowNum+1 for(int rowNum = firstRowNum;rowNum <= lastRowNum;rowNum++){ //获得当前行 Row row = sheet.getRow(rowNum); if(row == null){ continue; } //获得当前行的开始列 int firstCellNum = row.getFirstCellNum(); //获得当前行的列数 int lastCellNum = row.getLastCellNum(); String[] cells = new String[row.getLastCellNum()]; //循环当前行 for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){ Cell cell = row.getCell(cellNum); cells[cellNum] = getCellValue(cell); } list.add(cells); } } } return list; } /** * 检查文件 * @param file * @throws IOException */ public static void checkFile(MultipartFile file) throws IOException{ //判断文件是否存在 if(null == file){ log.error("文件不存在!"); } //获得文件名 String fileName = file.getOriginalFilename(); //判断文件是否是excel文件 if(!fileName.endsWith("xls") && !fileName.endsWith("xlsx")){ log.error(fileName + "不是excel文件"); } } public static Workbook getWorkBook(MultipartFile file) { //获得文件名 String fileName = file.getOriginalFilename(); //创建Workbook工作薄对象,表示整个excel Workbook workbook = null; try { //获取excel文件的io流 InputStream is = file.getInputStream(); //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象 if(fileName.endsWith("xls")){ //2003 workbook = new HSSFWorkbook(is); }else if(fileName.endsWith("xlsx")){ //2007 及2007以上 workbook = new XSSFWorkbook(is); } } catch (IOException e) { log.error(e.getMessage()); } return workbook; } public static String getCellValue(Cell cell){ String cellValue = ""; if(cell == null){ return cellValue; } //判断数据的类型 switch (cell.getCellType()){ case Cell.CELL_TYPE_NUMERIC: //数字 cellValue = stringDateProcess(cell); break; case Cell.CELL_TYPE_STRING: //字符串 cellValue = String.valueOf(cell.getStringCellValue()); break; case Cell.CELL_TYPE_BOOLEAN: //Boolean cellValue = String.valueOf(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: //公式 cellValue = String.valueOf(cell.getCellFormula()); break; case Cell.CELL_TYPE_BLANK: //空值 cellValue = ""; break; case Cell.CELL_TYPE_ERROR: //故障 cellValue = "非法字符"; break; default: cellValue = "未知类型"; break; } return cellValue; } public static String stringDateProcess(Cell cell){ String result = new String(); if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式 SimpleDateFormat sdf = null; if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) { sdf = new SimpleDateFormat("HH:mm"); } else {// 日期 sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); } Date date = cell.getDateCellValue(); result = sdf.format(date); } else if (cell.getCellStyle().getDataFormat() == 58) { // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); double value = cell.getNumericCellValue(); Date date = org.apache.poi.ss.usermodel.DateUtil .getJavaDate(value); result = sdf.format(date); } else { double value = cell.getNumericCellValue(); CellStyle style = cell.getCellStyle(); DecimalFormat format = new DecimalFormat(); String temp = style.getDataFormatString(); // 单元格设置成常规 if (temp.equals("General")) { format.applyPattern("#"); } result = format.format(value); } return result; } }


三、解析Excel文件(入参是MultipartFile)

MultipartFile是一种可以接收使用多种请求方式来进行上传文件的代表形式。

MultipartFile是一个接口,继承自InputStreamSource,封装了getInputStream方法,因此MultipartFile文件可以转换为输入流。

/** * @Author 程序幻境 * @Date 2022/11/19 * @Version 1.0 */ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; /** * 解析excel 上传数据 */ public class ExcelUtil { private static final Logger log = Logger.getLogger(ExcelUtil.class); public static void main(String[] args) { try { getExcelData("C:\Users\ZXC\Desktop\1.xlsx"); } catch (IOException e) { e.printStackTrace(); } } /** * 解析excel * @param file * @return * @throws IOException */ public static List getExcelData(String filePath) throws IOException{ //通过输入流,读取excel文件 FileInputStream input = new FileInputStream(filePath); //将输入流传入Workbook Workbook workbook = new XSSFWorkbook(input); //创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回 List list = new ArrayList(); if(workbook != null){ for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){ //获得当前sheet工作表 Sheet sheet = workbook.getSheetAt(sheetNum); if(sheet == null){ continue; } //获得当前sheet的开始行 int firstRowNum = sheet.getFirstRowNum(); //获得当前sheet的结束行 int lastRowNum = sheet.getLastRowNum(); //循环除了所有行,如果要循环除第一行以外的就firstRowNum+1 for(int rowNum = firstRowNum;rowNum <= lastRowNum;rowNum++){ //获得当前行 Row row = sheet.getRow(rowNum); if(row == null){ continue; } //获得当前行的开始列 int firstCellNum = row.getFirstCellNum(); //获得当前行的列数 int lastCellNum = row.getLastCellNum(); String[] cells = new String[row.getLastCellNum()]; //循环当前行 for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){ Cell cell = row.getCell(cellNum); cells[cellNum] = getCellValue(cell); } list.add(cells); } } } return list; } /** * 检查文件 * @param file * @throws IOException */ public static void checkFile(MultipartFile file) throws IOException{ //判断文件是否存在 if(null == file){ log.error("文件不存在!"); } //获得文件名 String fileName = file.getOriginalFilename(); //判断文件是否是excel文件 if(!fileName.endsWith("xls") && !fileName.endsWith("xlsx")){ log.error(fileName + "不是excel文件"); } } public static Workbook getWorkBook(MultipartFile file) { //获得文件名 String fileName = file.getOriginalFilename(); //创建Workbook工作薄对象,表示整个excel Workbook workbook = null; try { //获取excel文件的io流 InputStream is = file.getInputStream(); //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象 if(fileName.endsWith("xls")){ //2003 workbook = new HSSFWorkbook(is); }else if(fileName.endsWith("xlsx")){ //2007 及2007以上 workbook = new XSSFWorkbook(is); } } catch (IOException e) { log.error(e.getMessage()); } return workbook; } public static String getCellValue(Cell cell){ String cellValue = ""; if(cell == null){ return cellValue; } //判断数据的类型 switch (cell.getCellType()){ case Cell.CELL_TYPE_NUMERIC: //数字 cellValue = stringDateProcess(cell); break; case Cell.CELL_TYPE_STRING: //字符串 cellValue = String.valueOf(cell.getStringCellValue()); break; case Cell.CELL_TYPE_BOOLEAN: //Boolean cellValue = String.valueOf(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: //公式 cellValue = String.valueOf(cell.getCellFormula()); break; case Cell.CELL_TYPE_BLANK: //空值 cellValue = ""; break; case Cell.CELL_TYPE_ERROR: //故障 cellValue = "非法字符"; break; default: cellValue = "未知类型"; break; } return cellValue; } public static String stringDateProcess(Cell cell){ String result = new String(); if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式 SimpleDateFormat sdf = null; if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) { sdf = new SimpleDateFormat("HH:mm"); } else {// 日期 sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); } Date date = cell.getDateCellValue(); result = sdf.format(date); } else if (cell.getCellStyle().getDataFormat() == 58) { // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); double value = cell.getNumericCellValue(); Date date = org.apache.poi.ss.usermodel.DateUtil .getJavaDate(value); result = sdf.format(date); } else { double value = cell.getNumericCellValue(); CellStyle style = cell.getCellStyle(); DecimalFormat format = new DecimalFormat(); String temp = style.getDataFormatString(); // 单元格设置成常规 if (temp.equals("General")) { format.applyPattern("#"); } result = format.format(value); } return result; } }


本文仅供个人记录,大家可以借鉴,每行代码都是自己手打,亲测可直接粘贴执行,如有任何问题可在评论区提问,欢迎大家交流。

编辑人:程序幻境

码字不易,不喜勿踩

写代码使我快乐