此时情绪此时天,无事小神仙
好好生活,平平淡淡每一天

编辑

POI Demo

POI API

http://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Workbook.html

所需相关jar下载

commons-collections4-4.4.jar
commons-compress-1.19.jar
poi-4.1.1.jar
poi-ooxml-4.1.1.jar
poi-ooxml-schemas-4.1.1.jar

POI 中的CellType类型以及值的对应关系
CellType 类型
CELL_TYPE_NUMERIC 数值型 0
CELL_TYPE_STRING 字符串型 1
CELL_TYPE_FORMULA 公式型 2
CELL_TYPE_BLANK 空值 3
CELL_TYPE_BOOLEAN 布尔型 4
CELL_TYPE_ERROR 错误 5

POI读取Excel

Import Class
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
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.XSSFWorkbook;
根据Excel的地址读取Excel表格数据
/**
     * @Title:getDataFromExcel
     * @author:马家立
     * @date:2019年11月19日 上午10:02:22
     * @Description:TODO 根据Excel的地址读取Excel表格数据
     * @param filePathExcel的绝对路径
     * @return Map<String,Object> {end:ok或者error;msg:错误信息原因;counts:读取条数}
     * @throws IOException
     */
    public static Map<String, Object> getDataFromExcel(String filePath) throws IOException {
        // 声明结果map
        Map<String, Object> resultMap = new HashMap<String, Object>();
        // 判断是否为excel类型文件
        if (!filePath.endsWith(".xls") && !filePath.endsWith(".xlsx")) {
            System.out.println("文件不是excel类型");
            resultMap.put("end", "error");
            resultMap.put("msg", "文件不是excel类型");
            return resultMap;
        }
        // 声明文本输入流
        FileInputStream fis = null;
        // 声明一个新的工作簿
        Workbook wookbook = null;
        // 声明一个新的工作表
        Sheet sheet = null;
        try {
            // 获取一个绝对地址的流
            fis = new FileInputStream(filePath);
            // 2003版本的excel,用.xls结尾, 2007版本以.xlsx
            if (filePath.endsWith(".xls")) {
                wookbook = new HSSFWorkbook(fis);// 得到工作簿
            } else {
                // XSSFWorkbook
                wookbook = new XSSFWorkbook(fis);// 得到工作簿
            }
            // 得到第一个工作表
            sheet = wookbook.getSheetAt(0);
            // 得到第二个工作表
            // sheet = wookbook.getSheetAt(1);
            // 得到第三个工作表
            // sheet = wookbook.getSheetAt(2);
            // 封装处理Excel工作子表的数据
            resultMap = packageDataBySheet(sheet);
        } finally {
            if (!QwyUtil.isNullAndEmpty(wookbook)) {
                wookbook.close();
            }
        }
        return resultMap;
    }
封装处理Excel工作子表的数据

  /**
     * @Title:packageDataBySheet
     * @author:马家立
     * @date:2019年11月19日 上午9:55:26
     * @Description:TODO 封装处理Excel工作子表的数据
     * @param sheetExcel工作簿中的子表
     * @return Map<String,Object> {end:ok或者error;msg:错误信息原因;counts:读取条数}
     */
    public static Map<String, Object> packageDataBySheet(Sheet sheet) {
        // 返回结果map
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            resultMap.put("end", "ok");
            // 获得表头
            Row rowHead = sheet.getRow(0);
            // 获取Excel的所有行数量
            int rows = sheet.getLastRowNum();
            // 获取Excel的所有列数量
            int lines = rowHead.getPhysicalNumberOfCells();
            if (0 == rows) {
                System.out.println("Excel文件内没有数据!");
                resultMap.put("end", "error");
                resultMap.put("msg", "Excel文件内没有数据!");
                return resultMap;
            }
            // 读取条数
            int counts = 0;
            // 是否跳过读取下一行
            boolean isNext = false;
            // 外圈循环读取所有行:获得所有行的数据
            for (int i = 0; i <= rows; i++) {
                // 是否跳过读取下一行:每次初始化为false
                isNext = false;
                counts++;
                // 获得第i行对象
                Row row = sheet.getRow(i);
                // 获取单元格为空则直接下一行
                if (isNullAndEmpty(row)) {
                    continue;
                }
                List<String> list = new ArrayList<>();
                // 内圈循环读取所有列:遍历每一行的的数据,lineNum:列数
                for (int j = 0; j < lines; j++) {
                    // 获取该单元格相应的类型的值
                    String str = getRightTypeCell(row.getCell(j), i, j);
                    // 如果第一列为空则直接读取下一行
                    if (isNullAndEmpty(str) && (0 == j)) {
                        isNext = true;
                        break;
                    }
                    list.add(str);
                }
                // 是否跳过读取下一行
                if (isNext) {
                    continue;
                }
                String str1 = list.get(0); // 参数1
                // String str2 = list.get(1); // 参数2
                // String str3 = list.get(2); // 参数3
                // and so on...
                if (i == 0) {
                    if ("str1".endsWith(str1)) {
                        System.out.println("读取的排课Excel数据格式正确");
                    } else {
                        resultMap.put("end", "error");
                        resultMap.put("msg", "读取的排课Excel数据格式错误!");
                        System.err.println("读取的排课Excel数据格式错误");
                        break;
                    }
                } else {
                    /**
                     * 处理数据
                     */
                }

            }
            resultMap.put("counts", counts + "");
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("end", "error");
            resultMap.put("msg", "OperationExcel的packageDataBySheet方法异常!");
        }
        return resultMap;
    }
返回该单元格相应的类型的值
/**
     * @Title:getRightTypeCell
     * @author:马家立
     * @date:2020年6月26日 上午11:55:55
     * @Description:TODO 返回该单元格相应的类型的值
     * @param cell--一个单元格的对象
     * @param rowNum--行数
     * @param lineNum--列数
     * @return String
     * @throws Exception
     */
    public static String getRightTypeCell(Cell cell, int rowNum, int lineNum) throws Exception {
        // 单元格内容
        String result = "";
        System.out.println("rowNum:" + rowNum + "\tlineNum:" + lineNum);
        // 如果单元格为空或者单元格里面的数据为空则返回
        if ((cell == null) || cell.equals(null) || (CellType.BLANK == cell.getCellType())) {
            result = "";
        } else {
            // 判断数据类型
            switch (cell.getCellType()) {
                case BLANK:
                    result = cell.getStringCellValue();
                    break;
                case BOOLEAN:
                    result = String.valueOf(cell.getBooleanCellValue());
                    break;
                case ERROR:
                    result = String.valueOf(cell.getErrorCellValue());
                    break;
                case FORMULA:
                    result = cell.getCellFormula();
                    break;
                case NUMERIC:
                    result = String.valueOf(cell.getNumericCellValue());
                    /**
                     * --#与0的区别{#:没有则为空;0:没有则补0}
                     */
                    // 没有则自动补.00--100则为100.00;100.00则为100.00;1.05则为1.05;1.5则为1.50
                    // result = new DecimalFormat("0.00").format(cell.getNumericCellValue());
                    // 100则为100;100.00则为100;1.05则为1.05;1.5则为1.5
                    result = new DecimalFormat("0.##").format(cell.getNumericCellValue());
                    break;
                case STRING:
                    result = cell.getRichStringCellValue().getString();
                    break;
                default:
                    result = cell.getStringCellValue();
                    break;
            }
        }
        return result;
    }
校验对象是否为空
/**
     * @Title:isNullAndEmpty
     * @author:马家立
     * @date:2019年11月19日 上午10:23:49
     * @Description:TODO 校验对象是否为空
     * @param obj校验对象
     * @return boolean
     */
    public static boolean isNullAndEmpty(Object obj) {
        if ((null != obj) && !"".equals(obj.toString()) && !"null".equals(obj)) {
            return false;
        } else {
            return true;
        }
    }
main方法测试
public static void main(String[] args) {
        try {
            // 读取文件地址
            String file_path = "D:\\123.xlsx";
            String end;
            // 传路径是为了方法灵活
            Map<String, Object> map = getDataFromExcel(file_path);
            end = map.get("end") + "";
            System.out.println("封装处理结果:" + end);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

POI导出Excel

maven项目引用POI的jar
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.14</version>
</dependency>

<!-- 引入后XSSFWorkbook依旧无法使用的话,需要继续引用这个jar包 -->
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.14</version>
</dependency>
Import Class
import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
POI-Excel默认样式
/**
     * @Title:getPOIStyle
     * @Description:TODO 获取POI-Excel默认样式
     * @author:马家立
     * @date:2020-7-6 11:33:21
     * @param workbook
     * @return XSSFCellStyle
     * @throws Exception
     */
    public static XSSFCellStyle getPOIStyle(XSSFWorkbook workbook) throws Exception {
        XSSFCellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直
        // 加粗字体
        XSSFFont font = workbook.createFont();
        // 字体大小
        font.setFontHeight(12);
        // 字体颜色
        //font.setColor(new XSSFColor(Color.green));
     //font.setColor(new XSSFColor(new Color(9, 99, 9)));//rgb颜色
        // 字体加粗
        // font.setBold(true);
        style.setFont(font);
        return style;
    }

POI-Excel标题样式
/**
     * @Title:getPOITitleStyle
     * @Description:TODO 获取POI-Excel标题样式
     * @author:马家立
     * @date:2020-7-6 11:34:12
     * @param workbook
     * @return XSSFCellStyle
     * @throws Exception
     */
    public static XSSFCellStyle getPOITitleStyle(XSSFWorkbook workbook) throws Exception {
        XSSFCellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直
        // 加粗字体
        XSSFFont font = workbook.createFont();
        // 字体大小
        font.setFontHeight(15);
        // 字体颜色
        // font.setColor(Font.COLOR_RED);
        // 字体加粗
        font.setBold(true);
        style.setFont(font);
        return style;
    }
创建单元格,写入数据
/**
     * @Title:creatCell
     * @Description:TODO 创建单元格,写入数据
     * @author:马家立
     * @date:2020-7-6 12:03:54
     * @param xssfRow--行
     * @param content--内容
     * @param line--第几列
     * @param style--样式
     * @throws Exception
     * void
     */
    public static void creatCell(XSSFRow xssfRow, String content, int line, XSSFCellStyle style) throws Exception {
        // 创建列
        XSSFCell cell = xssfRow.createCell(line);
        if (null!=content&&!"".equals(content)) {
            // 写入内容
            cell.setCellValue(content);
        }
        // 设置样式
        cell.setCellStyle(style);
    }
POI-Excel写入内容并生成文件
/**
     * @Title:writeExcel
     * @Description:TODO Excel写入内容并生成文件
     * @author:马家立
     * @date:2020-7-6 11:43:51
     * @param filePath--文件路径(C:\\Users\\userName\\Desktop\\")
     * @param fileName--文件名字,带后缀(POIExcel.xls)
     * @throws Exception
     * void
     */
    public void writeExcel(String filePath,String fileName)  throws Exception {
        XSSFWorkbook workbook = null;
        FileOutputStream fout = null;
        try {
            // 路径若为空则默认为桌面
            if(null==filePath||"".equals(filePath)) {
                filePath = "C:\\Users\\"+System.getenv().get("USERNAME")+"\\Desktop\\";
            }
            // 文件名若为空则默认为POIExcel.xls
            if(null==fileName||"".equals(fileName)) {
                fileName = "POIExcel.xls";
            }
            /**
             * -- 第一步:创建一个webbook,对应一个Excel文件
             */
            workbook = new XSSFWorkbook();
            /**
             * -- 第二步:在webbook中添加一个sheet,对应Excel文件中的sheet
             */
            XSSFSheet sheet = workbook.createSheet("子表名");
            /**
             * --第三步:声明格式写入内容
             */
            // 声明标题样式
            XSSFCellStyle titleStyle = getPOITitleStyle(workbook);
            // 声明内容样式
            XSSFCellStyle contentStyle = getPOIStyle(workbook);
            // 合并单元格格式:起始行号,终止行号, 起始列号,终止列号
            CellRangeAddress region = new CellRangeAddress(0, 0, 0, 2);
            sheet.addMergedRegion(region);
            // 第一行写入数据
            int row = 0;
            XSSFRow xssfRow = sheet.createRow(row);
            creatCell(xssfRow, "第一行第一列", 0, titleStyle);
            // 第二行写入数据
            row++;
            xssfRow = sheet.createRow(row);
            creatCell(xssfRow, "第二行第一列", 0, contentStyle);
            creatCell(xssfRow, "第二行第二列", 1, contentStyle);
            creatCell(xssfRow, "第二行第三列", 2, contentStyle);
            // 设置每一列的宽度为自适应
            int lines = 3;
            for (int i = 0; i < lines; i++) {
                sheet.autoSizeColumn(i, true);
                sheet.setColumnWidth(i, (sheet.getColumnWidth(i) * 17) / 10);
            }
            /**
             * --创建多个表
             */
            XSSFSheet sheet2 = workbook.createSheet("子表名2");
            // 合并单元格格式:起始行号,终止行号, 起始列号,终止列号
            sheet2.addMergedRegion(region);
            // 第一行写入数据
            row = 0;
            xssfRow = sheet2.createRow(row);
            creatCell(xssfRow, "第一行第一列222", 0, titleStyle);
            // 第二行写入数据
            row++;
            xssfRow = sheet2.createRow(row);
            creatCell(xssfRow, "第二行第一列222", 0, contentStyle);
            creatCell(xssfRow, "第二行第二列222", 1, contentStyle);
            creatCell(xssfRow, "第二行第三列222", 2, contentStyle);
            // 设置每一列的宽度为自适应
            lines = 3;
            for (int i = 0; i < lines; i++) {
                sheet2.autoSizeColumn(i, true);
                sheet2.setColumnWidth(i, (sheet.getColumnWidth(i) * 17) / 10);
            }
            /**
             * --第四步:创建File文件,把workbook写入File
             */
            File file = new File(filePath+fileName);
            if (!file.exists()) {
                // 文件不存在则创建新文件
                file.createNewFile();
                fout = new FileOutputStream(file);
                workbook.write(fout);
            } else {
                // 文件存在则覆盖写入数据
                fout = new FileOutputStream(file);
                workbook.write(fout);
            }
        } finally {
            if (null != fout) {
                fout.close();
            }
            if (null != workbook) {
                workbook.close();
            }
        }
    }
main函数POI方式导出Excel
public static void main(String[] args) {
        POIExcel poiExcel = new POIExcel();
        try {
            // 测试POI写入Excel
            poiExcel.writeExcel(null, null);
            System.out.println("ok");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

POI 工具方法

POI-Excel宽度自适应
public static void autoColumn(XSSFSheet sheet){
    int maxColumn = sheet.getRow(0).getPhysicalNumberOfCells();
    for(int i = 0; i < maxColumn; i++){
        sheet.autoSizeColumn(i);
    }
    for(int columnNum = 0; columnNum <= maxColumn; columnNum++){
        int columnWidth = sheet.getColumnWidth(columnNum) / 256;
        for(int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++){
            Row currentRow;
            if(sheet.getRow(rowNum) == null){
                currentRow = sheet.createRow(rowNum);
            }else{
                currentRow = sheet.getRow(rowNum);
            }

            if(currentRow.getCell(columnNum) != null){
                Cell currentCell = currentRow.getCell(columnNum);
                try {
                    int length = currentCell.toString().getBytes("GBK").length;
                    if(columnWidth < length + 1){
                        columnWidth = length + 8;
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        sheet.setColumnWidth(columnNum, columnWidth * 256);
    }
}
POI 使用输出流向前端返回Excel文件
poi向前端返回excel,有两种方法,先介绍简单粗暴的,就是最常用的直接用流向浏览器返回文件,比较简单粗暴,前端直接使用get方法即可,主要是后台的操作。 前端页面: window.location.href="这里写路径,有参数的话也可以带上"; 后端java代码,注意一下火狐浏览器的文件名的特殊处理:
    /**
     * 下载材料excel方法1,该方法暂时没启用 2020年3月12日 14:33:26
     * excel 
     * @param req
     * @param res
     */ 
    @RequestMapping(method={RequestMethod.GET, RequestMethod.POST,RequestMethod.HEAD},value="getMaterialsExcel",produces="application/json")
    public void getMaterialsExcel(HttpServletRequest req,HttpServletResponse res){
        ServletOutputStream sos = null;
        try{
            logger.debug("************************开始下载材料excel*******************");
            // 不用分页了,注意要带上过滤条件
            Map<String, Object> param = new HashMap<String,Object>(); // 查询的过滤条件
            param.put("productName", req.getParameter("productName"));
            param.put("model", req.getParameter("model"));
            param.put("productStatus", req.getParameter("productStatus"));

            res.setContentType("application/json");
            res.setCharacterEncoding("utf-8");
            // service中得到具体业务相关的HSSFWorkbook
            HSSFWorkbook wb = downloadExcelService.getMaterialsExcel(param);

            String fileName = "测试测试.xls";

            String agent = req.getHeader("USER-AGENT").toLowerCase();
            String uncodeFileNameString = "";
            if(agent.contains("firefox")){
                // 火狐
                uncodeFileNameString = "=?UTF-8?B?" + (new String(Base64Utils.encodeToString(fileName.getBytes("UTF-8")))) + "?=";
                logger.debug("火狐浏览器");
            }else{
                // 其他
                uncodeFileNameString = URLEncoder.encode(fileName, "UTF-8");
                uncodeFileNameString = uncodeFileNameString.replace("+", "%20"); // 空格被转为了 "+" ,要转成utf-8的空格符号 "%20"
                logger.debug("不是火狐浏览器");
            }
            res.setContentType("application/octet-stream;charset=UTF-8");
            res.setHeader("Content-disposition", "attachment; filename=" + uncodeFileNameString);
            sos = res.getOutputStream();
            wb.write(sos);
        }catch(Exception e){
            e.printStackTrace();
            logger.error("下载材料excel时异常:  ", e);
        }finally{
            if(sos != null){
                try {
                    // sos是字节流,不用flush了,直接close
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("未正确关闭sos");
                }
            }
        }
    }
posted @ 2019-11-19 10:40  踏步  阅读(1045)  评论(0编辑  收藏  举报