美文网首页Java学习之路我爱编程java
使用Apache POI导出Excel小结--导出XLS格式文档

使用Apache POI导出Excel小结--导出XLS格式文档

作者: JianweiZhou | 来源:发表于2016-11-09 14:36 被阅读3135次

    使用Apache POI导出Excel小结

    关于使用Apache POI导出Excel我大概会分三篇文章去写

    导出XLS格式文档

    做企业应用项目难免会有数据导出到Excel的需求,最近在使用其,并对导出Excel封装成工具类开放出来供大家参考。关于Apache POI Excel基本的概念与操作我在这里就不啰嗦了。

    请大家参考如下:

    在使用Apache POI导出Excel有以下限制:

    • Excel <=2003 数据限制,行(65536)*列(256)
    • Excel =2007 数据限制,行(1048576)*列(16384)

    POI结构说明

    包名称 说明

    HSSF提供读写Microsoft Excel XLS格式档案的功能。

    XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能。

    SXSSF提供基于流式读写Microsoft Excel OOXML XLSX格式档案的功能(适用于大数据量)。

    POI常用类说明

    以HSSF为例其他的只是前缀命名变动

    • 如HSSF-->HSSFWorkbook、XSSF-->XSSFWorkbook、SXSSF-->SXSSFWorkbook

    类名 说明

    HSSFWorkbook Excel的文档对象

    HSSFSheet Excel的表单

    HSSFRow Excel的行

    HSSFCell Excel的格子单元

    HSSFFont Excel字体

    HSSFDataFormat 格子单元的日期格式

    HSSFHeader Excel文档Sheet的页眉

    HSSFFooter Excel文档Sheet的页脚

    HSSFCellStyle 格子单元样式

    HSSFDateUtil 日期

    HSSFPrintSetup 打印

    HSSFErrorConstants 错误信息表

    下来给大家依次展现代码:

    Maven依赖配置

    使用的Apache POI版本

    <poi.version>3.9</poi.version>
    
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>${poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>${poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>${poi.version}</version>
    </dependency>
    

    生成XLS格式Excel文档

    使用于小数据量生成

    • 受Excel XLS格式文档本身限制(XLS格式文档大约处理最大数据行[65536条])
    • 基于Excel模板写入数据会引发内存溢出

    注意:

    • 以下代码少ReportInternalException大家可以忽略(我们封装的一个异常类)
    • 导出的Excel同时考虑到数据的本身类型,如整数、小数、日期等
    • 第一种写入数据方式[writeExcel]方法为直接写入数据
    • 第二种写入数据方式需依次调用方法[writeExcelTitle、writeExcelData],先完成写入Excel标题与列名,再完成数据写入(或者说基于模板方式写入数据)
    • 第二种方式有内存溢出的可能性
    • 我们使用[styleMap]方法避免重复创建Excel单元格样式(否则受Excel创建样式数量限制)
    import org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.hssf.util.HSSFColor;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.ss.util.CellRangeAddress;
    
    import javax.imageio.ImageIO;
    import java.io.*;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Excel 相关操作类(小数据量写入<=65536)
     */
    public class Excel2003Utils {
    
        private static final int DEFAULT_COLUMN_SIZE = 30;
    
        /**
         * 断言Excel文件写入之前的条件
         *
         * @param directory 目录
         * @param fileName  文件名
         * @return file
         * @throws IOException
         */
        private static File assertFile(String directory, String fileName) throws IOException {
            File tmpFile = new File(directory + File.separator + fileName + ".xls");
            if (tmpFile.exists()) {
                if (tmpFile.isDirectory()) {
                    throw new IOException("File '" + tmpFile + "' exists but is a directory");
                }
                if (!tmpFile.canWrite()) {
                    throw new IOException("File '" + tmpFile + "' cannot be written to");
                }
            } else {
                File parent = tmpFile.getParentFile();
                if (parent != null) {
                    if (!parent.mkdirs() && !parent.isDirectory()) {
                        throw new IOException("Directory '" + parent + "' could not be created");
                    }
                }
            }
            return tmpFile;
        }
    
        /**
         * 日期转化为字符串,格式为yyyy-MM-dd HH:mm:ss
         */
        private static String getCnDate(Date date) {
            String format = "yyyy-MM-dd HH:mm:ss";
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        }
    
        /**
         * Excel 导出,POI实现
         *
         * @param fileName    文件名
         * @param sheetName   sheet页名称
         * @param columnNames 表头列表名
         * @param sheetTitle  sheet页Title
         * @param objects     目标数据集
         */
        public static File writeExcel(String directory, String fileName, String sheetName, List<String> columnNames,
                                      String sheetTitle, List<List<Object>> objects, boolean append) throws ReportInternalException, IOException {
            File tmpFile = assertFile(directory, fileName);
            return exportExcel(tmpFile, sheetName, columnNames, sheetTitle, objects, append);
        }
    
        /**
         * Excel 导出,POI实现,先写入Excel标题,与writeExcelData配合使用
         * 先使用writeExcelTitle再使用writeExcelData
         *
         * @param directory   目录
         * @param fileName    文件名
         * @param sheetName   sheetName
         * @param columnNames 列名集合
         * @param sheetTitle  表格标题
         * @param append      是否在现有的文件追加
         * @return file
         * @throws ReportInternalException
         * @throws IOException
         */
        public static File writeExcelTitle(String directory, String fileName, String sheetName, List<String> columnNames,
                                           String sheetTitle, boolean append) throws ReportInternalException, IOException {
            File tmpFile = assertFile(directory, fileName);
            return exportExcelTitle(tmpFile, sheetName, columnNames, sheetTitle, append);
        }
    
        /**
         * Excel 导出,POI实现,写入Excel数据行列,与writeExcelTitle配合使用
         * 先使用writeExcelTitle再使用writeExcelData
         *
         * @param directory 目录
         * @param fileName  文件名
         * @param sheetName sheetName
         * @param objects   数据信息
         * @return file
         * @throws ReportInternalException
         * @throws IOException
         */
        public static File writeExcelData(String directory, String fileName, String sheetName, List<List<Object>> objects)
                throws ReportInternalException, IOException {
            File tmpFile = assertFile(directory, fileName);
            return exportExcelData(tmpFile, sheetName, objects);
        }
    
        /**
         * 导出字符串数据
         *
         * @param file        文件名
         * @param columnNames 表头
         * @param sheetTitle  sheet页Title
         * @param append      是否追加写文件
         * @return file
         * @throws ReportInternalException
         */
        private static File exportExcelTitle(File file, String sheetName, List<String> columnNames,
                                             String sheetTitle, boolean append) throws ReportInternalException, IOException {
            // 声明一个工作薄
            Workbook workBook;
            if (file.exists() && append) {
                // 声明一个工作薄
                workBook = new HSSFWorkbook(new FileInputStream(file));
            } else {
                workBook = new HSSFWorkbook();
            }
            Map<String, CellStyle> cellStyleMap = styleMap(workBook);
            // 表头样式
            CellStyle headStyle = cellStyleMap.get("head");
            // 生成一个表格
            Sheet sheet = workBook.getSheet(sheetName);
            if (sheet == null) {
                sheet = workBook.createSheet(sheetName);
            }
            //最新Excel列索引,从0开始
            int lastRowIndex = sheet.getLastRowNum();
            if (lastRowIndex > 0) {
                lastRowIndex++;
            }
            // 设置表格默认列宽度
            sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE);
            // 合并单元格
            sheet.addMergedRegion(new CellRangeAddress(lastRowIndex, lastRowIndex, 0, columnNames.size() - 1));
            // 产生表格标题行
            Row rowMerged = sheet.createRow(lastRowIndex);
            lastRowIndex++;
            Cell mergedCell = rowMerged.createCell(0);
            mergedCell.setCellStyle(headStyle);
            mergedCell.setCellValue(new HSSFRichTextString(sheetTitle));
            // 产生表格表头列标题行
            Row row = sheet.createRow(lastRowIndex);
            for (int i = 0; i < columnNames.size(); i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(headStyle);
                RichTextString text = new HSSFRichTextString(columnNames.get(i));
                cell.setCellValue(text);
            }
            try {
                OutputStream ops = new FileOutputStream(file);
                workBook.write(ops);
                ops.flush();
                ops.close();
            } catch (IOException e) {
                throw new ReportInternalException(e);
            }
            return file;
        }
    
        /**
         * 导出字符串数据
         *
         * @param file    文件名
         * @param objects 目标数据
         * @return
         * @throws ReportInternalException
         */
        private static File exportExcelData(File file, String sheetName, List<List<Object>> objects) throws ReportInternalException, IOException {
            // 声明一个工作薄
            Workbook workBook;
            if (file.exists()) {
                // 声明一个工作薄
                workBook = new HSSFWorkbook(new FileInputStream(file));
            } else {
                workBook = new HSSFWorkbook();
            }
            Map<String, CellStyle> cellStyleMap = styleMap(workBook);
            // 正文样式
            CellStyle contentStyle = cellStyleMap.get("content");
            //正文整数样式
            CellStyle contentIntegerStyle = cellStyleMap.get("integer");
            //正文带小数整数样式
            CellStyle contentDoubleStyle = cellStyleMap.get("double");
            // 生成一个表格
            Sheet sheet = workBook.getSheet(sheetName);
            if (sheet == null) {
                sheet = workBook.createSheet(sheetName);
            }
            //最新Excel列索引,从0开始
            int lastRowIndex = sheet.getLastRowNum();
            if (lastRowIndex > 0) {
                lastRowIndex++;
            }
            // 设置表格默认列宽度
            sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE);
            // 遍历集合数据,产生数据行,前两行为标题行与表头行
            for (List<Object> dataRow : objects) {
                Row row = sheet.createRow(lastRowIndex);
                lastRowIndex++;
                for (int j = 0; j < dataRow.size(); j++) {
                    Cell contentCell = row.createCell(j);
                    Object dataObject = dataRow.get(j);
                    if (dataObject != null) {
                        if (dataObject instanceof Integer) {
                            contentCell.setCellStyle(contentIntegerStyle);
                            contentCell.setCellValue(Integer.parseInt(dataObject.toString()));
                        } else if (dataObject instanceof Double) {
                            contentCell.setCellStyle(contentDoubleStyle);
                            contentCell.setCellValue(Double.parseDouble(dataObject.toString()));
                        } else if (dataObject instanceof Long && dataObject.toString().length() == 13) {
                            contentCell.setCellStyle(contentStyle);
                            contentCell.setCellValue(getCnDate(new Date(Long.parseLong(dataObject.toString()))));
                        } else if (dataObject instanceof Date) {
                            contentCell.setCellStyle(contentStyle);
                            contentCell.setCellValue(getCnDate((Date) dataObject));
                        } else {
                            contentCell.setCellStyle(contentStyle);
                            contentCell.setCellValue(dataObject.toString());
                        }
                    } else {
                        contentCell.setCellStyle(contentStyle);
                        // 设置单元格内容为字符型
                        contentCell.setCellValue("");
                    }
                }
            }
            try {
                OutputStream ops = new FileOutputStream(file);
                workBook.write(ops);
                ops.flush();
                ops.close();
            } catch (IOException e) {
                throw new ReportInternalException(e);
            }
            return file;
        }
    
        /**
         * 导出字符串数据
         *
         * @param file        文件名
         * @param columnNames 表头
         * @param sheetTitle  sheet页Title
         * @param objects     目标数据
         * @param append      是否追加写文件
         * @return
         * @throws ReportInternalException
         */
        private static File exportExcel(File file, String sheetName, List<String> columnNames,
                                        String sheetTitle, List<List<Object>> objects, boolean append) throws ReportInternalException, IOException {
            // 声明一个工作薄
            Workbook workBook;
            if (file.exists() && append) {
                // 声明一个工作薄
                workBook = new HSSFWorkbook(new FileInputStream(file));
            } else {
                workBook = new HSSFWorkbook();
            }
            Map<String, CellStyle> cellStyleMap = styleMap(workBook);
            // 表头样式
            CellStyle headStyle = cellStyleMap.get("head");
            // 正文样式
            CellStyle contentStyle = cellStyleMap.get("content");
            //正文整数样式
            CellStyle contentIntegerStyle = cellStyleMap.get("integer");
            //正文带小数整数样式
            CellStyle contentDoubleStyle = cellStyleMap.get("double");
            // 生成一个表格
            Sheet sheet = workBook.getSheet(sheetName);
            if (sheet == null) {
                sheet = workBook.createSheet(sheetName);
            }
            //最新Excel列索引,从0开始
            int lastRowIndex = sheet.getLastRowNum();
            if (lastRowIndex > 0) {
                lastRowIndex++;
            }
            // 设置表格默认列宽度
            sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE);
            // 合并单元格
            sheet.addMergedRegion(new CellRangeAddress(lastRowIndex, lastRowIndex, 0, columnNames.size() - 1));
            // 产生表格标题行
            Row rowMerged = sheet.createRow(lastRowIndex);
            lastRowIndex++;
            Cell mergedCell = rowMerged.createCell(0);
            mergedCell.setCellStyle(headStyle);
            mergedCell.setCellValue(new HSSFRichTextString(sheetTitle));
            // 产生表格表头列标题行
            Row row = sheet.createRow(lastRowIndex);
            lastRowIndex++;
            for (int i = 0; i < columnNames.size(); i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(headStyle);
                RichTextString text = new HSSFRichTextString(columnNames.get(i));
                cell.setCellValue(text);
            }
            // 遍历集合数据,产生数据行,前两行为标题行与表头行
            for (List<Object> dataRow : objects) {
                row = sheet.createRow(lastRowIndex);
                lastRowIndex++;
                for (int j = 0; j < dataRow.size(); j++) {
                    Cell contentCell = row.createCell(j);
                    Object dataObject = dataRow.get(j);
                    if (dataObject != null) {
                        if (dataObject instanceof Integer) {
                            contentCell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                            contentCell.setCellStyle(contentIntegerStyle);
                            contentCell.setCellValue(Integer.parseInt(dataObject.toString()));
                        } else if (dataObject instanceof Double) {
                            contentCell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                            contentCell.setCellStyle(contentDoubleStyle);
                            contentCell.setCellValue(Double.parseDouble(dataObject.toString()));
                        } else if (dataObject instanceof Long && dataObject.toString().length() == 13) {
                            contentCell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            contentCell.setCellStyle(contentStyle);
                            contentCell.setCellValue(getCnDate(new Date(Long.parseLong(dataObject.toString()))));
                        } else if (dataObject instanceof Date) {
                            contentCell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            contentCell.setCellStyle(contentStyle);
                            contentCell.setCellValue(getCnDate((Date) dataObject));
                        } else {
                            contentCell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            contentCell.setCellStyle(contentStyle);
                            contentCell.setCellValue(dataObject.toString());
                        }
                    } else {
                        contentCell.setCellStyle(contentStyle);
                        // 设置单元格内容为字符型
                        contentCell.setCellValue("");
                    }
                }
            }
            try {
                OutputStream ops = new FileOutputStream(file);
                workBook.write(ops);
                ops.flush();
                ops.close();
            } catch (IOException e) {
                throw new ReportInternalException(e);
            }
            return file;
        }
    
        /**
         * 创建单元格表头样式
         *
         * @param workbook 工作薄
         */
        private static CellStyle createCellHeadStyle(Workbook workbook) {
            CellStyle style = workbook.createCellStyle();
            // 设置边框样式
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            style.setBorderTop(HSSFCellStyle.BORDER_THIN);
            //设置对齐样式
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            // 生成字体
            Font font = workbook.createFont();
            // 表头样式
            style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
            style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
            font.setFontHeightInPoints((short) 12);
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            // 把字体应用到当前的样式
            style.setFont(font);
            return style;
        }
    
        /**
         * 创建单元格正文样式
         *
         * @param workbook 工作薄
         */
        private static CellStyle createCellContentStyle(Workbook workbook) {
            CellStyle style = workbook.createCellStyle();
            // 设置边框样式
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            style.setBorderTop(HSSFCellStyle.BORDER_THIN);
            //设置对齐样式
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            // 生成字体
            Font font = workbook.createFont();
            // 正文样式
            style.setFillPattern(HSSFCellStyle.NO_FILL);
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
            // 把字体应用到当前的样式
            style.setFont(font);
            return style;
        }
    
        /**
         * 单元格样式(Integer)列表
         */
        private static CellStyle createCellContent4IntegerStyle(Workbook workbook) {
            CellStyle style = workbook.createCellStyle();
            // 设置边框样式
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            style.setBorderTop(HSSFCellStyle.BORDER_THIN);
            //设置对齐样式
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            // 生成字体
            Font font = workbook.createFont();
            // 正文样式
            style.setFillPattern(HSSFCellStyle.NO_FILL);
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
            // 把字体应用到当前的样式
            style.setFont(font);
            style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0"));//数据格式只显示整数
            return style;
        }
    
        /**
         * 单元格样式(Double)列表
         */
        private static CellStyle createCellContent4DoubleStyle(Workbook workbook) {
            CellStyle style = workbook.createCellStyle();
            // 设置边框样式
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            style.setBorderTop(HSSFCellStyle.BORDER_THIN);
            //设置对齐样式
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            // 生成字体
            Font font = workbook.createFont();
            // 正文样式
            style.setFillPattern(HSSFCellStyle.NO_FILL);
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
            // 把字体应用到当前的样式
            style.setFont(font);
            style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));//保留两位小数点
            return style;
        }
    
        /**
         * 单元格样式列表
         */
        private static Map<String, CellStyle> styleMap(Workbook workbook) {
            Map<String, CellStyle> styleMap = new LinkedHashMap<>();
            styleMap.put("head", createCellHeadStyle(workbook));
            styleMap.put("content", createCellContentStyle(workbook));
            styleMap.put("integer", createCellContent4IntegerStyle(workbook));
            styleMap.put("double", createCellContent4DoubleStyle(workbook));
            return styleMap;
        }
    
    }
    
    使用例子
    import java.io.IOException;
    import java.sql.Date;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * Excel2003Test
     * Created by jianwei.zhou on 2016/11/9.
     */
    public class Excel2003Test {
    
        public static void main(String[] args) throws IOException {
            String sheetName = "测试Excel格式";
            String sheetTitle = "测试Excel格式";
            List<String> columnNames = new LinkedList<>();
            columnNames.add("日期-String");
            columnNames.add("日期-Date");
            columnNames.add("时间戳-Long");
            columnNames.add("客户编码");
            columnNames.add("整数");
            columnNames.add("带小数的正数");
    
            //写入标题--第二种方式
            Excel2003Utils.writeExcelTitle("E:\\temp", "a", sheetName, columnNames, sheetTitle, false);
    
            List<List<Object>> objects = new LinkedList<>();
            for (int i = 0; i < 1000; i++) {
                List<Object> dataA = new LinkedList<>();
                dataA.add("2016-09-05 17:27:25");
                dataA.add(new Date(1451036631012L));
                dataA.add(1451036631012L);
                dataA.add("000628");
                dataA.add(i);
                dataA.add(1.323 + i);
                objects.add(dataA);
            }
            try {
                //写入数据--第二种方式
                Excel2003Utils.writeExcelData("E:\\temp", "a", sheetName, objects);
    
                //直接写入数据--第一种方式
                Excel2003Utils.writeExcel("E:\\temp", "a", sheetName, columnNames, sheetTitle, objects, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    

    相关文章

      网友评论

        本文标题:使用Apache POI导出Excel小结--导出XLS格式文档

        本文链接:https://www.haomeiwen.com/subject/otttpttx.html