package com.ltmst.util; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import org.apache.poi.POIXMLException; import org.apache.poi.common.usermodel.Hyperlink; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFCreationHelper; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFHyperlink; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import com.fivefu.base.pojo.ExcelCellData; import com.fivefu.base.pojo.ExcelDataType; /** * 封装了Excel的一些工具方法 * @author Joy * @date 2020 */ public class ExcelUtil { /**单个sheet内最大行数*/ public static final int MAX_SHEET_ROWS = 20000; /**单元格最小宽度*/ public static final int MIN_COL_WIDTH = 12 * 256; /**单元格最大宽度*/ public static final int MAX_COL_WIDTH = 255 * 256; /** * 计算列宽 * @param colWidth 保存列宽设置的集合 * @param colIndex 当前列的下标 * @param content 当前列的内容(字符串形式) * @return 当前列的最佳列宽 * @throws UnsupportedEncodingException * @author Joy * */ public static int calColWidth(List<Integer> colWidth, int colIndex, String content) throws UnsupportedEncodingException{ int width = content.getBytes("UTF-8").length * 256 + 184;//根据当前内容计算单元格宽度 if(width < ExcelUtil.MIN_COL_WIDTH){ width = ExcelUtil.MIN_COL_WIDTH; } //每列的最大宽度不能超过255 * 256,超过这个值会报java.lang.IllegalArgumentException: the maximum column width in Excel is 255 characters if(width > ExcelUtil.MAX_COL_WIDTH){ width = ExcelUtil.MAX_COL_WIDTH; } if(null == colWidth){ colWidth = new ArrayList<Integer>(); } if(colWidth.isEmpty() || colWidth.size() - 1 < colIndex){//如果列宽集合为空或者当前列不存在时就添加设置 colWidth.add(width); }else{//否则读取设置 //如果当前列的最佳列宽已经存在,就从列宽记录里面读取当前列的最佳列宽 int bestWidth = colIndex > colWidth.size() - 1 ? width : (null != colWidth.get(colIndex) ? colWidth.get(colIndex).intValue() : width); if(bestWidth > width){//最佳宽度最合适,仍然取最佳宽度 colWidth.set(colIndex, bestWidth); }else{//否则说明当前数据的宽度超过了最佳宽度 colWidth.set(colIndex, width); } } return colIndex > colWidth.size() - 1 ? width : (null != colWidth.get(colIndex) ? colWidth.get(colIndex).intValue() : width); } /** * 写入标题到sheet中 * @param workbook 工作表 * @param sheet 要写入标题sheet * @param tableTitle 标题列表 * @param titleCellStyle 标题样式,为空则没有任何样式应用 * @param colWidth 列宽列表 * @param isNoCellStyle 是否屏蔽单元格样式 * @param isAutoCalCellWidth 是否自动计算列宽 * @return 生成的行数 * @throws Exception 抛出所有的异常 * @author Joy * */ public static int writeTitleToSheet(XSSFWorkbook workbook, XSSFSheet sheet, List<String> tableTitle, XSSFCellStyle titleCellStyle, List<Integer> colWidth, boolean isNoCellStyle, boolean isAutoCalCellWidth) throws Exception{ int createRowNums = 0;//创建行的次数 if(null != sheet && null != tableTitle && !tableTitle.isEmpty() && null != colWidth){ XSSFRow titleRow = sheet.createRow(0);//创建标题行 ++createRowNums;//每创建一行就累加一下行数 //写入标题 for(int i = 0; i < tableTitle.size(); ++i){ String content = null != tableTitle.get(i) ? tableTitle.get(i) : "";//取出标题内容 XSSFCell cell = titleRow.createCell(i);//创建单元格 cell.setCellValue(content);//设置单元格内容 if(!isNoCellStyle){//单元格计算样式 if(null != titleCellStyle){ cell.setCellStyle(titleCellStyle);//设置标题单元格样式 }else{ //设置字体 XSSFFont font = workbook.createFont(); font.setFontName("微软雅黑");//设置字体 titleCellStyle = workbook.createCellStyle();//创建标题单元格样式 titleCellStyle.setBorderLeft(XSSFCellStyle.BORDER_THICK);//设置单元格左边框为厚厚的边框单元格样式 titleCellStyle.setBorderTop(XSSFCellStyle.BORDER_THICK);//设置单元格上边框为厚厚的边框单元格样式 titleCellStyle.setBorderRight(XSSFCellStyle.BORDER_THICK);//设置单元格右边框为厚厚的边框单元格样式 titleCellStyle.setBorderBottom(XSSFCellStyle.BORDER_THICK);//设置单元格下边框为厚厚的边框单元格样式 titleCellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);//设置单元格对齐方式为水平居中 titleCellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);//设置单元格对齐方式为垂直居中 titleCellStyle.setFont(font);//将字体设置应用到标题中 cell.setCellStyle(titleCellStyle);//设置标题单元格样式 } } if(isAutoCalCellWidth){//启用了自动个计算列宽 sheet.setColumnWidth(i, ExcelUtil.calColWidth(colWidth, i, content));//计算并设置列宽 } } sheet.createFreezePane(0, 1, 0, 1);//冻结首行 } return createRowNums; } /** * 写入数据到sheet * @param workbook 工作表 * @param sheet 要写入数据的sheet * @param sheetName sheet的名称 * @param data 要写入的数据 * @param cellStyle 数据单元格样式 * @param colWidth 列宽列表 * @param tableTitle 标题列表 * @param titleCellStyle 标题样式 * @param isNoCellStyle 是否屏蔽单元格样式 * @param isAutoCalCellWidth 是否自动计算列宽 * @throws Exception 抛出所有的异常 * @author Joy * */ public static void writeDataToSheet(XSSFWorkbook workbook, XSSFSheet sheet, String sheetName, List<List<Object>> data, XSSFCellStyle cellStyle, List<Integer> colWidth, List<String> tableTitle, XSSFCellStyle titleCellStyle, boolean isNoCellStyle, boolean isAutoCalCellWidth) throws Exception{ if(null != workbook && null != sheet && null != data && !data.isEmpty()){ if(null == colWidth){//如果列宽设置列表为空,就新建一个 colWidth = new ArrayList<Integer>(); } int sheetNums = workbook.getNumberOfSheets();//获取excel内sheet的数量 for(int i = 0; i < data.size(); ++i){ List<Object> colList = data.get(i);//获取一行所有列的数据 int sheetTotalRows = sheet.getPhysicalNumberOfRows();//更新每个sheet内的行数 //每当一个sheet内的行数达到20000行之后就创建一个新的sheet放数据 if(0 == sheetTotalRows % ExcelUtil.MAX_SHEET_ROWS){ sheet = workbook.createSheet((null != sheetName ? sheetName : "") + "第" + (sheetNums + 1) + "页"); ++sheetNums;//累加sheet数量 sheetTotalRows = 0;//计数器清零 //写入标题 sheetTotalRows += ExcelUtil.writeTitleToSheet(workbook, sheet, tableTitle, titleCellStyle, colWidth, isNoCellStyle, isAutoCalCellWidth);//写入标题到sheet中,并累加当前sheet中的行数 } XSSFRow row = sheet.createRow(sheetTotalRows);//创建新的一行 XSSFDrawing draw = null; ++sheetTotalRows;//每创建一行就累加一下总行数 for(int j = 0; j < colList.size(); ++j){ Object obj = colList.get(j);//获取当前单元格数据 XSSFCell cell = row.createCell(j);//创建单元格 String content = "";//要写入的内容 if(obj instanceof ExcelCellData){ ExcelCellData cellData = (ExcelCellData)obj;//强转为Excel单元格数据信息对象 if(ExcelDataType.NUMBER == cellData.getDataType()){//要求按照数字格式写入数据 String value = cellData.getDataValue();//获取数据的字面值 cell.setCellValue(Double.parseDouble(value));//转为数字格式写入 }else if(ExcelDataType.DATE == cellData.getDataType()){//要求按照日期格式写入数据 Object value = cellData.getLinkData();//获取数据 if(value instanceof Date){//如果是日期类型 cell.setCellValue((Date)value);//转换为日期类型写入数据 }else{//无法转换为日期类型 cell.setCellValue(cellData.getDataValue());//直接获取当前数据的字面值数据写入,可能为空 } }else if(ExcelDataType.IMG == cellData.getDataType()){//说明要写入的是图片 if(null == draw){//画笔为空时才实例化对象 draw = sheet.createDrawingPatriarch();//往单元格中写入图片时使用 } //String value = cellData.getDataValue();//获取图片地址 Object value = cellData.getLinkData();//获取图片资源 ExcelUtil.writeImgToOneCell(value, cell, draw, workbook);//向当前单元格中写入数据 }else if(ExcelDataType.LINK == cellData.getDataType()){//要写入的数据是外部链接类型 String text = cellData.getDataValue();//获取要显示的文本 Object link = cellData.getLinkData();//获取链接的资源 XSSFCreationHelper creationHelper = workbook.getCreationHelper(); String address = ""; String regExpEmail = "\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";//邮箱正则表达式 String regExpURL = "[a-zA-z]+://[^\s]*";//URL正则表达式 XSSFHyperlink hyperLink = null; if(link instanceof String){//链接内容可能是URL或者Email address = String.valueOf(link);//将内容转为文本 if(address.matches(regExpURL)){//可能是一个URL hyperLink = (XSSFHyperlink)creationHelper.createHyperlink(Hyperlink.LINK_URL);//创建URL类型的链接 hyperLink.setAddress(address);//设置链接地址 }else if(address.matches(regExpEmail)){//可能是一个Email hyperLink = (XSSFHyperlink)creationHelper.createHyperlink(Hyperlink.LINK_EMAIL);//创建Email类型的链接 hyperLink.setAddress(address);//设置链接地址 }else{//如果两种都没有匹配上,就到外面去按照普通文本写入 ; } }else if(link instanceof File){//链接内容是外部文件 File linkFile = (File)link; hyperLink = (XSSFHyperlink)creationHelper.createHyperlink(Hyperlink.LINK_FILE);//创建文件链接 hyperLink.setAddress(linkFile.getAbsolutePath());//设置链接地址 }else{//本来还有一种链接类型是Hyperlink.LINK_DOCUMENT,暂未查到相关API,就直接当做普通文本写入不处理了 ; } cell.setCellValue(text);//设置单元格显示的内容 if(null != hyperLink){ cell.setHyperlink(hyperLink); } }else{//否则全部按照文字格式处理 content = String.valueOf(obj); content = Sys.isNotNull(content) ? content : ""; cell.setCellValue(content);//设置单元格数据 } }else{//没有指明数据格式则全部按照文本格式写入数据 content = String.valueOf(obj); content = Sys.isNotNull(content) ? content : ""; cell.setCellValue(content);//设置单元格数据 } if(!isNoCellStyle){//单元格设置样式 if(null != cellStyle){ cell.setCellStyle(cellStyle);//设置单元格样式 }else{ //设置字体 XSSFFont font = workbook.createFont(); font.setFontName("微软雅黑");//设置字体 cellStyle = workbook.createCellStyle();//创建数据区域表格样式 //设置单元格四周为浅边框线 cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN); cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN); cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN); cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); cellStyle.setAlignment(XSSFCellStyle.ALIGN_JUSTIFY);//设置文本适应单元格内容的宽度 cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);//设置文本垂直方向居中对齐 cellStyle.setFont(font);//将字体设置应用到数据区域中 cell.setCellStyle(cellStyle);//设置单元格样式 } } if(isAutoCalCellWidth){//启用了自动计算列宽 sheet.setColumnWidth(j, ExcelUtil.calColWidth(colWidth, j, content));//设置列宽 } } } } } /** * 追加形式写入数据到指定工作表中 * @param workbook 要写入数据的工作表 * @param tableTitle 表格标题 * @param data 表格数据 * @param sheetName 工作表名称 * @param isNoCellStyle 是否屏蔽单元格样式 * @param isAutoCalCellWidth 是否自动计算列宽 * @throws Exception 抛出所有异常 * @author Joy * */ public static void appendDataToExcel(XSSFWorkbook workbook, List<String> tableTitle, List<List<Object>> data, String sheetName, boolean isNoCellStyle, boolean isAutoCalCellWidth) throws Exception{ if(null != workbook && null != tableTitle && !tableTitle.isEmpty() && null != data && !data.isEmpty()){ int sheetNums = workbook.getNumberOfSheets();//获取工作表下sheet的数量 XSSFFont font = null;//字体设置 XSSFCellStyle titleCellStyle = null;//标题行单元格样式 XSSFCellStyle cellStyle = null;//数据区域单元格样式 List<Integer> colWidth = null;//用于保存列宽设置 if(0 == sheetNums){//只有第一次开始写入的时候才实例化字体、单元格样式以及其他设置、计数器之类的 //设置字体 font = workbook.createFont(); font.setFontName("微软雅黑");//设置字体 titleCellStyle = workbook.createCellStyle();//创建标题单元格样式 titleCellStyle.setBorderLeft(XSSFCellStyle.BORDER_THICK);//设置单元格左边框为厚厚的边框单元格样式 titleCellStyle.setBorderTop(XSSFCellStyle.BORDER_THICK);//设置单元格上边框为厚厚的边框单元格样式 titleCellStyle.setBorderRight(XSSFCellStyle.BORDER_THICK);//设置单元格右边框为厚厚的边框单元格样式 titleCellStyle.setBorderBottom(XSSFCellStyle.BORDER_THICK);//设置单元格下边框为厚厚的边框单元格样式 titleCellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);//设置单元格对齐方式为水平居中 titleCellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);//设置单元格对齐方式为垂直居中 titleCellStyle.setFont(font);//将字体设置应用到标题中 cellStyle = workbook.createCellStyle();//创建数据区域表格样式 //设置单元格四周为浅边框线 cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN); cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN); cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN); cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); cellStyle.setAlignment(XSSFCellStyle.ALIGN_JUSTIFY);//设置文本适应单元格内容的宽度 cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);//设置文本垂直方向居中对齐 cellStyle.setFont(font);//将字体设置应用到数据区域中 if(null == colWidth){ colWidth = new ArrayList<Integer>(); } } XSSFSheet sheet = null;//工作表 if(0 == sheetNums){//说明工作表中什么内容都没有,默认创建一张工作表,写入标题和数据 sheet = workbook.createSheet((null != sheetName ? sheetName : "") + "第" + (sheetNums + 1) + "页");//创建一个sheet ExcelUtil.writeTitleToSheet(workbook, sheet, tableTitle, titleCellStyle, colWidth, isNoCellStyle, isAutoCalCellWidth);//写入标题到sheet中,并累加当前sheet中的行数 //写入数据 ExcelUtil.writeDataToSheet(workbook, sheet, sheetName, data, cellStyle, colWidth, tableTitle, titleCellStyle, isNoCellStyle, isAutoCalCellWidth); }else{//说明工作表中已经有数据了 /* * 这个时候就需要注意了,这时就可以直接取出最后一个sheet(因为该方法是追加模式,每个sheet写满之后才创建新的sheet), * 判断其行数是否超过每个sheet设定的最大行数,如果超过了就自动创建一个新的sheet并往里面写入数据 */ sheet = workbook.getSheetAt(sheetNums - 1);//取出最后一个sheet //写入数据 ExcelUtil.writeDataToSheet(workbook, sheet, sheetName, data, cellStyle, colWidth, tableTitle, titleCellStyle, isNoCellStyle, isAutoCalCellWidth); } } } /** * 写入图片到一个单元格中 * @param imgAddress 图片地址,可以是URL也可以是本地路径 * @param rowIndex 写入单元格行下标 * @param colIndex 写入单元格列下标 * @param draw {@link XSSFDrawing}对象 * @param workbook {@link XSSFWorkbook}对象,要写入图片的工作薄 * @author Joy * */ public static void writeImgToOneCell(String imgAddress, int rowIndex, int colIndex, XSSFDrawing draw, XSSFWorkbook workbook){ ByteArrayOutputStream byteArrayOut = null; try { byteArrayOut = new ByteArrayOutputStream(); BufferedImage bufferImg = null; if(imgAddress.startsWith("http")){ bufferImg = ImageIO.read(new URL(imgAddress)); }else{ bufferImg = ImageIO.read(new File(imgAddress)); } String suffixName = imgAddress.substring(imgAddress.lastIndexOf(".") + 1);//获取文件后缀名 ImageIO.write(bufferImg, suffixName, byteArrayOut); //表示图片写入一个单元格内且图片四周与单元格的边距为0 XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, colIndex, (rowIndex + 1), (colIndex + 1), (rowIndex + 2)); writeImgToCell(workbook, draw, anchor, byteArrayOut, suffixName); } catch (Exception e) { System.err.println("ExcelUtil.writeImgToOneCell方法Exception:" + e.getMessage()); e.printStackTrace(); } finally { if(null != byteArrayOut){ try { byteArrayOut.flush(); byteArrayOut.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 写入图片到一个单元格中 * @param source 图片资源(目前只支持{@link URL}和{@link File}) * @param cell {@link XSSFCell}对象,要写入图片的单元格 * @param draw {@link XSSFDrawing}对象 * @param workbook {@link XSSFWorkbook}对象,要写入图片的工作薄 * @author Joy */ public static void writeImgToOneCell(Object source, XSSFCell cell, XSSFDrawing draw, XSSFWorkbook workbook){ ByteArrayOutputStream byteArrayOut = null; try { BufferedImage bufferImg = null; String suffixName = "jpg";//给个默认的图片格式,避免获取文件后缀名失败 if(source instanceof URL){ byteArrayOut = new ByteArrayOutputStream(); URL url = (URL)source; bufferImg = ImageIO.read(url); String query = url.getPath(); suffixName = query.substring(query.lastIndexOf(".") + 1);//获取文件后缀名 }else if(source instanceof File){ byteArrayOut = new ByteArrayOutputStream(); File file = (File)source; bufferImg = ImageIO.read(file); String addr = file.getAbsolutePath(); suffixName = addr.substring(addr.lastIndexOf(".") + 1);//获取文件后缀名 }else{//如果没匹配上,就跳过当前单元格 return; } ImageIO.write(bufferImg, suffixName, byteArrayOut); //表示图片写入一个单元格内且图片四周与单元格的边距为0 XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, cell.getColumnIndex(), cell.getRowIndex(), (cell.getColumnIndex() + 1), (cell.getRowIndex() + 1)); writeImgToCell(workbook, draw, anchor, byteArrayOut, suffixName); } catch (Exception e) { System.err.println("ExcelUtil.writeImgToOneCell方法Exception:" + e.getMessage()); e.printStackTrace(); } finally { if(null != byteArrayOut){ try { byteArrayOut.flush(); byteArrayOut.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 写入图片到单元格 * @param workbook 要写入图片的工作薄 * @param draw {@link XSSFDrawing}对象 * @param anchor {@link XSSFClientAnchor}对象 * @param byteArrayOut {@link ByteArrayOutputStream}对象 * @param suffixName 图片后缀名 * @author Joy * */ private static void writeImgToCell(XSSFWorkbook workbook, XSSFDrawing draw, XSSFClientAnchor anchor, ByteArrayOutputStream byteArrayOut, String suffixName){ try { //不同格式的图片采用不同的方法写入 if("bmp".equalsIgnoreCase(suffixName)){ draw.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_BMP)); }else if("eps".equalsIgnoreCase(suffixName)){ draw.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_EPS)); }else if("gif".equalsIgnoreCase(suffixName)){ draw.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_GIF)); }else if("tiff".equalsIgnoreCase(suffixName)){ draw.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_TIFF)); }else if("jpg".equalsIgnoreCase(suffixName) || "jpeg".equalsIgnoreCase(suffixName)){ draw.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG)); }else if("png".equalsIgnoreCase(suffixName)){ draw.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG)); } } catch (Exception e) { System.err.println("ExcelUtil.writeImgToCell方法Exception:" + e.getMessage()); e.printStackTrace(); } } /** * 读取单元格数据 * @param cell 要读取数据的单元格 * @return 有内容则返回{@link Object}类型的数据,否则返回<code>null</code>。 * @author Joy * */ public static Object readCellData(Cell cell){ Object cellContent = null; try { if(null != cell){ if(Cell.CELL_TYPE_NUMERIC == cell.getCellType()){//数字类型 cellContent = cell.getNumericCellValue(); }else if(Cell.CELL_TYPE_STRING == cell.getCellType()){//字符串类型 cellContent = cell.getStringCellValue(); }else if(Cell.CELL_TYPE_FORMULA == cell.getCellType()){//表达式类型 cellContent = cell.getCellFormula(); }else if(Cell.CELL_TYPE_BLANK == cell.getCellType()){//链接类型 cellContent = cell.getHyperlink(); }else if(Cell.CELL_TYPE_BOOLEAN == cell.getCellType()){//布尔值类型 cellContent = cell.getBooleanCellValue(); }else{//Cell.CELL_TYPE_ERROR类型,一个尚且未知的类型,姑且用String类型去读取(有可能会异常) cellContent = cell.getStringCellValue(); } } } catch (Exception e) { e.printStackTrace(); } return cellContent; } /** * 加载Excel文件 * 先以2010方式加载excel文件,如果异常了再尝试以97/03方式加载excel文件。 * @param excelFile 要加载的excel文件 * @return 加载成功返回{@link Workbook}对象,否则返回<code>null</code>。 * @author Joy * */ public static Workbook loadFile(File excelFile){ Workbook workbook = null; try { workbook = new XSSFWorkbook(new FileInputStream(excelFile));//先用2010方式解析 System.out.println("2010方式解析"); } catch (POIXMLException e) { if(e.getMessage().indexOf("org.apache.poi.openxml4j.exceptions.InvalidFormatException") >= 0){//如果报格式异常就尝试用97/03格式解析 try { workbook = new HSSFWorkbook(new FileInputStream(excelFile));//用97/03格式解析 System.out.println("97/03方式解析"); } catch (FileNotFoundException e1) { System.err.println("Excel文件找不到"); e1.printStackTrace(); } catch (IOException e1) { System.err.println("I/O异常"); e1.printStackTrace(); } }else{//未知异常 System.err.println("未知异常"); e.printStackTrace(); } } catch (FileNotFoundException e) { System.err.println("Excel文件找不到"); e.printStackTrace(); } catch (IOException e) { System.err.println("I/O异常"); e.printStackTrace(); } catch (Exception e) { System.err.println("未知异常"); e.printStackTrace(); } return workbook; } /** * 读取Excel里的数据并写入{@link List} * @param excelFile 要读取数据的Excel * @return 读取到了数据返回{@link List}<{@link List}<{@link Object}>>集合,否则返回<code>null</code>。 * @author Joy * */ public static List<List<Object>> readExcel(File excelFile){ List<List<Object>> data = null;//用来保存解析出来的数据 try { Workbook workbook = ExcelUtil.loadFile(excelFile);//加载Excel文件 if(null != workbook){ data = new ArrayList<List<Object>>(); int sheets = workbook.getNumberOfSheets();//excel内不为空的sheet的总数量 //遍历所有的sheet,取出每个sheet中的数据 for(int sheetNum = 0; sheetNum < sheets; ++sheetNum){ Sheet sheet = workbook.getSheetAt(sheetNum);//获取当前sheet int lastRowNum = sheet.getLastRowNum();//获取最后一行的下标 //遍历当前sheet中所有的行,取出每行的数据 for(int rowNum = 0; rowNum <= lastRowNum; ++rowNum){ Row row = sheet.getRow(rowNum);//获取当前行 int lastCellNum = row.getLastCellNum();//获取最后一列的下标 List<Object> rowData = new ArrayList<Object>(lastCellNum);//用来保存一行的数据 //遍历所有的列,取出当前行所有的数据 for(int colNum = 0; colNum < lastCellNum; ++colNum){ Cell cell = row.getCell(colNum);//获取当前单元格 Object cellValue = ExcelUtil.readCellData(cell);//读取单元格数据 rowData.add(cellValue); } data.add(rowData); } } } } catch (Exception e) { e.printStackTrace(); } return data; } }