ExcelUtil工具类-1

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}&lt;{@link List}&lt;{@link Object}&gt;&gt;集合,否则返回<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;
    }
    
    
}
原文地址:https://www.cnblogs.com/weigy/p/13908777.html