【JAVA - POI 合集】之 POI EXCEL 大数据量导出 + 实现一个通用的EXCEL导出工具类

1.前言

        在java 开发过程中, EXCEL 导出大家都有遇到过。也遇到过各种问题,在这里也稍稍整理一下,算是一个这几年来对excel 导出的一些总结

2.常见的问题

        (1)excel 文字的导出目前分为两种,一种是以 xls 格式导出,其次就是以 xlsx 格式导出。

Excel版本最大行数最大列数最大sheet数
2003(XLS)65536(2的16次方)256(IV,2的8次方)255
2007以上(XLSX)1048576(2的20次方)16384(XFD,2的14次方)

无,受内存限制

表格中提到的受内存限制,那么就顺带一嘴, 如果服务器内存不够大, 一次性加载过多的数据, 在低版本的poi 中, 会出现内存溢出和性能问题。 所以在新的POI 版本中,例如:4.1.2 新增了一个专门处理大数据的 SXSSFWorkbook  对象, 这个实现的原理就是将数据直接写入到硬盘,在内存中存有少量的数据(创建对象的时候可以设置)。但是这个类也是存在弊端的。数据时写入到硬盘的,已经不再内存中, 即不能在对workbook 中数据进行操作。 要有针对性的选择 XSSFWorkbook 和  SXSSFWorkbook  

        (2)poi 升级之后会遇到的问题。

如果现在项目中所用的poi 版本为 3.XX 的版本 。升级到4.1.2 之后, 会有很多方法失效的情况。 尤其是在设置excel 的样式上。

                //POI 4.1.2 设置单元格属性
                CellStyle cellStyle = workbook.createCellStyle();
                 //设置单元格边框
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
                cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中


                //POI 3.17 设置单元格属性
                CellStyle cellStyle = wb.createCellStyle();
    		    cellStyle.setBorderTop(CellStyle.BORDER_THIN);
    	        cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
    	        cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
    	        cellStyle.setBorderRight(CellStyle.BORDER_THIN);
                cellStyle.setAlignment(CellStyle.ALIGN_RIGHT);//水平位置
                cellStyle.setVerticalAlignment(CellStyle.VERTICAL_BOTTOM);

3.如何实现一个通用的,兼容各种情况的导出工具类

        之前看到的很多所谓的通用EXCEL 导出工具类。 大多需要将要合并的表头,要导出的字段,分别定义一个map。在将除了数据之外的 keyMap 和 合并表头的Map 传到工具类中进行导出。每次新增一个页面, 就需要单独写返回字段的map 和合并表头的map . 如果涉及到的表头有2行或者3行将会更不好处理。

这次我们会实现一个兼容以上这种情况的 真 · 通用导出工具类。

实现该通用EXCEL 导出工具类的前提是需要和前端做配合, 定义一个字段, 将要导出的表头用json 格式传到后台接口中。

 如上图:导出一个只有单行表头的excel 表格. 

点击导出的时候,需要传以下格式的数据:(供参考)

header: excel 导出的表头 

field 对应数据的key , 用于获取对应的数据。

rowspan : 对应是数值表明是单行表头还是复合表头

colspan:对应的数值表明合并了多少列

columns:合并列下面对应的下级标题

还可以根据具体的需求, 加入指定的属性, 例如:dataType 属性,对指定的列进行格式化,时间格式,金额,百分比等。

[{
	"name": "",
	"visible": true,
	"header": "序号",
	"rowspan": 1
}, {
	"header": "商品名称",
	"name": "pName",
	"field": "pName",
	"visible": true
}, {
	"header": "订单ID",
	"name": "orderId",
	"field": "orderId",
	"visible": true
}, {
	"header": "订单描述",
	"name": "orderDesc",
	"field": "orderDesc",
	"visible": true
}, {
	"header": "年度",
	"name": "year",
	"field": "year",
	"visible": true
}, {
	"header": "截止日期",
	"name": "jzrq",
	"field": "jzrq",
	"visible": true
}, {
	"header": "创建人",
	"name": "cjr",
	"field": "cjr",
	"visible": true
}, {
	"header": "创建日期",
	"name": "cjrq",
	"field": "cjrq",
	"visible": true
}]
序号基本信息附加信息备注
名字年龄地址电话爱好XXXX

 此表格对应的数据格式看下方JSON 数据

[{
		"name": "",
		"header": "序号",
		"rowspan": 2
	},
	{
		"name": "",
		"header": "基本信息",
		"colspan": 4,
		"columns": [{
				"header": "名字",
				"name": "name",
				"field": "name"
			},
			{
				"header": "年龄",
				"name": "age",
				"field": "age"
			},
			{
				"header": "地址",
				"name": "add",
				"field": "add"
			},
			{
				"header": "电话",
				"name": "tel",
				"field": "tel"
			}
		]
	},
	{
		"name": "",
		"header": "附加信息",
		"colspan": 3,
		"columns": [{
				"header": "爱好",
				"name": "aih",
				"field": "aih"
			},
			{
				"header": "xx",
				"name": "xx",
				"field": "xx"
			},
			{
				"header": "xx",
				"name": "xx",
				"field": "xx"
			}
		]
	}
]
public class GeneralExportUtil {

    //Excel 导出, 每100W数据放入一个sheet页
    private static final Integer MAX_SEND = 10000000;

    /**
     * 构造数据, 生成符合导出的数据
     * @param jsonData   jQueryLogichandler 查询出来的 数据
     * @param columns    前台传过来的
     * @param sheetName
     * @param exportId  通过uuid 生成临时文件的名称, 前台通过UUID 下载文件, 和删除文件,
     */
    public static void buildDataAndExportExcel(String jsonData, String columns, String sheetName,String exportId) {

        List<JSONObject> dataList = JSONObject.parseArray(jsonData, JSONObject.class);
        List<JSONObject> columnList = JSONObject.parseArray(columns, JSONObject.class);

        List<String> col1 = new ArrayList<>(); //excel 第一行表头名称
        List<String> col2 = new ArrayList<>(); // excel 第二行表头名称
        List<String> col3 = new ArrayList<>(); // excel 第三行表头名称
        List<String> keyList = new ArrayList<>(); // 数据value 对应的key
        List<Integer[]> combinedTitle = new ArrayList<>(); //要合并的表头集合 第一行
        List<Integer[]> combinedTitleSec = new ArrayList<>(); //要合并的表头集合第二行
        List<Integer[]> combinedTitleThree = new ArrayList<>(); //要合并的表头集合第三行

        //表格中第一列是复选框的情况下,columnList 中的第一个元素需要移除
        JSONObject firstColumn = columnList.get(0);
        if (!firstColumn.containsKey("header")){
            columnList.remove(0);
        }

        //组织excel 表头信息
        int colNumIndexStart =0; // 从第一列到最后一列的下标
        for (JSONObject col : columnList) {
            int rowNumEnd=0; //合并行的结束
            int colNumIndexEnd=0;
            col1.add(col.getString("header").replace("<br>","")); //
            if (col.containsKey("rowspan")){
                rowNumEnd = col.getInteger("rowspan")-1;
            }
            if (col.containsKey("field")) {
                keyList.add(col.getString("field"));
            }

            if (col.containsKey("colspan")){//判断是否合并行
                colNumIndexEnd = colNumIndexStart+col.getInteger("colspan") - 1;
            }

            if (col.containsKey("columns")) {//判断是否合并列
                Integer[] array = {0,rowNumEnd,colNumIndexStart,colNumIndexEnd}; // 数组用于合并单元格
                combinedTitle.add(array);
                //构建第二行表头
                JSONArray secondRow = col.getJSONArray("columns");
                for (Object secCol : secondRow) {
                    colNumIndexEnd=0;
                    JSONObject jsonObject = (JSONObject) secCol;
                    col2.add(jsonObject.getString("header").replace("<br>",""));
                    if (jsonObject.containsKey("rowspan")) {
                        rowNumEnd = jsonObject.getInteger("rowspan");
                    }else{
                        rowNumEnd = 1;
                    }
                    if (jsonObject.containsKey("colspan")) { //第二行合并的表头
                        colNumIndexEnd = colNumIndexStart+jsonObject.getInteger("colspan") - 1;
                    }else{
                        colNumIndexEnd = colNumIndexStart;
                    }

                    if (jsonObject.containsKey("field")) {
                        keyList.add(jsonObject.getString("field"));
                    }

                    Integer[] array2 = {1,rowNumEnd,colNumIndexStart,colNumIndexEnd};
                    combinedTitleSec.add(array2);

                    /**
                     * 构建第三行表头
                     */
                    if (jsonObject.containsKey("columns")){

                        JSONArray secondThree = jsonObject.getJSONArray("columns");
                        for (Object threeCol : secondThree) {
                            JSONObject threeObject = (JSONObject) threeCol;
                            col3.add(threeObject.getString("header").replace("<br>",""));

                            if (threeObject.containsKey("field")) {
                                keyList.add(threeObject.getString("field"));
                            }
                            if (threeObject.containsKey("colspan")) { //第二行合并的表头
                                colNumIndexEnd = colNumIndexStart+threeObject.getInteger("colspan") - 1;
                            }else {
                                colNumIndexEnd = colNumIndexStart;
                            }

                            Integer[] array3 = {2,2,colNumIndexStart,colNumIndexEnd};
                            combinedTitleThree.add(array3);
                            colNumIndexStart++;
                        }
                    }else{
                        colNumIndexStart++;
                    }
                }

            }else{
                if (colNumIndexStart > 0 && colNumIndexEnd == 0) {
                    colNumIndexEnd = colNumIndexStart;
                }
                Integer[] array = {0,rowNumEnd,colNumIndexStart,colNumIndexEnd};
                combinedTitle.add(array);
                colNumIndexStart++;
            }


        }
        SXSSFWorkbook workbook = null;
        if (col2.size() == 0) {
            workbook = exportCellSingleTitle(sheetName, keyList, col1, dataList);
        }else if(col3.size() == 0){

            workbook = exportCellDoubleTitle(sheetName, keyList, col1, col2, dataList, combinedTitle);
        }else{
            workbook =exportCellThreeTitle(sheetName, keyList, col1, col2, col3, dataList, combinedTitle, combinedTitleSec,combinedTitleThree);
        }

        String tempPath = FxConstant.BASEPATH + "components" + File.separator + "fileio" + File.separator + "expfile";
        File outDir = new File(tempPath); // 生成本地存放临时文件的路径
        if (!outDir.exists()) {
            outDir.mkdirs();
        }
        FileOutputStream os = null;
        //临时文件生成
        try {
            os = new FileOutputStream(tempPath + File.separator + exportId+".xlsx");
            workbook.write(os);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                os.close();
                workbook.close();
                workbook.dispose();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     *
     * @param sheetName sheet 页名称
     * @param key_columns MAP 中对应的字段 key ,通过key 进行取值
     * @param value_columns1 表头合并第一行表头名称
     * @param value_columns2 第二行表头名称
     * @param datalistAll 要导出的数据
     * @param list3  要合并的表头 集合 例: 标题中如果有5个合并的表头, list3 的长度就为5  元素为数组, {0,1,0,0} 代表意思
     *               {行开始,行结束,列开始,列结束} 意为:第一列的第一行和第二行进行合并
     * @return
     */
    public static SXSSFWorkbook exportCellDoubleTitle(String sheetName, List<String> key_columns, List<String> value_columns1,
                                                 List<String> value_columns2, List<JSONObject> datalistAll, List<Integer[]> list3){

        SXSSFWorkbook workbook = null;
        Date date = new Timestamp(System.currentTimeMillis());
        System.out.println("excel开始时间:"+date.getTime());
        try {
            //XSSFWorkbook sheets = new XSSFWorkbook();
            //创建一个Excel文件
            workbook = new SXSSFWorkbook(100);
            List<List<JSONObject>> partition = ListUtils.partition(datalistAll, MAX_SEND);
            int sheetIndex=1;
            for (List<JSONObject> datalist : partition) {
                //创建一个工作表
                Sheet sheet = workbook.createSheet(sheetName+sheetIndex);
                sheetIndex++;
                //添加表头行
                Row row = sheet.createRow(0);
                //设置单元格格式
                CellStyle cellStyle = workbook.createCellStyle();
                //设置单元格边框
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
                cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中

                //将字段赋值到合并的单元格中
                CellStyle titleStyle = workbook.createCellStyle();
                Font titleFont = workbook.createFont();
                titleStyle.setBorderBottom(BorderStyle.THIN);
                titleStyle.setBorderTop(BorderStyle.THIN);
                titleStyle.setBorderRight(BorderStyle.THIN);
                titleStyle.setBorderLeft(BorderStyle.THIN);
                titleStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
                titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
                titleFont.setBold(true);
                titleStyle.setFont(titleFont);
                if (value_columns1.size()>0){
                    Cell cell = null;
                    for (int i = 0; i < value_columns1.size(); i++) {
                        cell = row.createCell(list3.get(i)[2]);
                        cell.setCellValue(value_columns1.get(i));
                        cell.setCellStyle(titleStyle);
                    }
                }
                int secRowCellIndex=0;
                for (Integer[] index: list3){
                    if (index[0] == index[1] && index[2]<=index[3]){
                        secRowCellIndex=index[2];
                        break;
                    }
                }


                row = sheet.createRow(1);
                for (String cellName:value_columns2) {
                    //添加表头内容
                    Cell cell = row.createCell(secRowCellIndex);
                    cell.setCellValue(cellName);
                    cell.setCellStyle(titleStyle);
                    sheet.setColumnWidth(secRowCellIndex,(int)((cellName.length()<=2?4:cellName.length())*2.5+0.72)*256);
                    secRowCellIndex++;
                }
                for (Integer[] arr : list3) {//合并表头
                    if(((arr[2]>0 ||arr[3]>0) && arr[2] != arr[3]) || (arr[0]>0 || arr[1]>0)) {
                        CellRangeAddress cellAddresses = new CellRangeAddress(arr[0], arr[1], arr[2], arr[3]);
                        sheet.addMergedRegion(cellAddresses);
                        RegionUtil.setBorderBottom(BorderStyle.THIN,cellAddresses,sheet);
                        RegionUtil.setBorderLeft(BorderStyle.THIN,cellAddresses,sheet);
                        RegionUtil.setBorderRight(BorderStyle.THIN,cellAddresses,sheet);
                        RegionUtil.setBorderTop(BorderStyle.THIN,cellAddresses,sheet);
                    }
                }

                boolean isHaveIndex = true;
                //判断表格是否有序号列
                if(!value_columns1.contains("序号") && !value_columns2.contains("序号")){
                    isHaveIndex = false;
                }

                //把数据添加到excel

                int ii = 0;

                for (int i = 0; i < datalist.size(); i++) {
                    row = sheet.createRow(ii + 2);
                    if (isHaveIndex){
                        //创建单元格,并设置值
                        int j = 1;
                        Cell cell = row.createCell(0);
                        cell.setCellValue(i+1);
                        cell.setCellStyle(cellStyle);
                        for (String s : key_columns) {
                            cell = row.createCell(j);
                            cell.setCellValue(datalist.get(i).getString(s));
                            cell.setCellStyle(cellStyle);
                            j++;
                        }
                        ii++;
                    }else {
                        //创建单元格,并设置值
                        int j = 0;
                        for (String s : key_columns) {
                            Cell cell = row.createCell(j);
                            cell.setCellValue(datalist.get(i).getString(s));
                            cell.setCellStyle(cellStyle);
                            j++;
                        }
                        ii++;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Date date1 = new Timestamp(System.currentTimeMillis());
        System.out.println("excel导出结束时间:"+(date1.getTime()-date.getTime()));
        return workbook;
    }


    /**
     * @param sheetName sheet 页名称
     * @param key_columns MAP 中对应的字段 key ,通过key 进行取值
     * @param value_columns 表头名称
     * @param datalistAll 要导出的数据
     * @return
     */
    public static SXSSFWorkbook exportCellSingleTitle(String sheetName, List<String> key_columns, List<String> value_columns,
                                                  List<JSONObject> datalistAll){

        SXSSFWorkbook workbook = null;
        Date date = new Timestamp(System.currentTimeMillis());
        System.out.println("excel开始时间:"+date.getTime());
        try {
            //XSSFWorkbook sheets = new XSSFWorkbook();
            //创建一个Excel文件
            workbook = new SXSSFWorkbook(100);
            List<List<JSONObject>> partition = ListUtils.partition(datalistAll, MAX_SEND);
            int sheetIndex=1;
            for (List<JSONObject> datalist : partition) {
                //创建一个工作表
                Sheet sheet = workbook.createSheet(sheetName+sheetIndex);
                sheetIndex++;
                //添加表头行
                Row row = sheet.createRow(0);
                //设置单元格格式
                CellStyle cellStyle = workbook.createCellStyle();
                //设置单元格边框
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
                cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中


                //将字段赋值到合并的单元格中
                CellStyle titleStyle = workbook.createCellStyle();
                Font titleFont = workbook.createFont();
                titleFont.setBold(true);
                titleStyle.cloneStyleFrom(cellStyle);
                titleStyle.setFont(titleFont);
                if (value_columns.size()>0){
                    Cell cell = null;
                    for (int i = 0; i < value_columns.size(); i++) {
                        cell = row.createCell(i);
                        cell.setCellValue(value_columns.get(i));
                        cell.setCellStyle(titleStyle);
                        //sheet.setDefaultColumnWidth(value_columns.get(i).length());
                        sheet.setColumnWidth(i,(int)((value_columns.get(i).length()<=2?4:value_columns.get(i).length())*2.5+0.72)*256);
                    }
                }
                //把数据添加到excel
                int ii = 0;

                for (int i = 0; i < datalist.size(); i++) {
                    row = sheet.createRow(ii + 1);

                    if (!value_columns.get(0).equals("序号")) {
                        //创建单元格,并设置值
                        int j = 0;
                        for (String s : key_columns) {
                            Cell cell = row.createCell(j);
                            cell.setCellValue(datalist.get(i).getString(s));
                            cell.setCellStyle(cellStyle);
                            j++;
                        }
                        ii++;
                    } else {
                        //创建单元格,并设置值
                        int j = 1;
                        Cell cell = row.createCell(0);
                        cell.setCellValue(i + 1);
                        cell.setCellStyle(cellStyle);
                        for (String s : key_columns) {
                            cell = row.createCell(j);
                            cell.setCellValue(datalist.get(i).getString(s));
                            cell.setCellStyle(cellStyle);
                            j++;
                        }
                        ii++;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Date date1 = new Timestamp(System.currentTimeMillis());
        System.out.println("excel导出结束时间:"+(date1.getTime()-date.getTime()));
        return workbook;
    }

    /**
     * 表头涉及到三行 包含合并单元格的导出情况
     * @param sheetName sheet 页名称
     * @param key_columns MAP 中对应的字段 key ,通过key 进行取值
     * @param value_columns1 表头合并第一行表头名称
     * @param value_columns2 第二行表头名称
     * @param datalistAll 要导出的数据
     * @param combinedTitle  要合并的表头 集合 例: 标题中如果有5个合并的表头, list3 的长度就为5  元素为数组, {0,1,0,0} 代表意思
     *               {行开始,行结束,列开始,列结束} 意为:第一列的第一行和第二行进行合并
     * @param combinedTitleSec  要合并的表头 集合 例: 标题中如果有5个合并的表头, list3 的长度就为5  元素为数组, {0,1,0,0} 代表意思
     *      *        {行开始,行结束,列开始,列结束} 意为:第一列的第一行和第二行进行合并
     * @return
     */
    public static SXSSFWorkbook exportCellThreeTitle(String sheetName, List<String> key_columns, List<String> value_columns1,
                                                 List<String> value_columns2,List<String> value_columns3,
                                                List<JSONObject> datalistAll, List<Integer[]> combinedTitle,
                                                List<Integer[]> combinedTitleSec,List<Integer[]> combinedTitleThree){

        SXSSFWorkbook workbook = null;
        Date date = new Timestamp(System.currentTimeMillis());
        System.out.println("excel下载开始时间:"+date.getTime());
        try {
            //XSSFWorkbook sheets = new XSSFWorkbook();
            //创建一个Excel文件
            workbook = new SXSSFWorkbook(100);
            List<List<JSONObject>> partition = ListUtils.partition(datalistAll, MAX_SEND);
            int sheetIndex=1;
            for (List<JSONObject> datalist : partition) {
                //创建一个工作表
                Sheet sheet = workbook.createSheet(sheetName + sheetIndex);


                //添加表头行
                Row row = sheet.createRow(0);
                //设置单元格格式
                CellStyle cellStyle = workbook.createCellStyle();
                //设置单元格边框
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
                cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中

                //将字段赋值到合并的单元格中
                CellStyle titleStyle = workbook.createCellStyle();
                Font titleFont = workbook.createFont();
                titleFont.setBold(true);
                titleStyle.cloneStyleFrom(cellStyle);
                titleStyle.setFont(titleFont);
                if (value_columns1.size() > 0) {
                    Cell cell = null;
                    for (int i = 0; i < value_columns1.size(); i++) {
                        cell = row.createCell(combinedTitle.get(i)[2]);
                        cell.setCellValue(value_columns1.get(i));
                        cell.setCellStyle(titleStyle);
                    }
                }
                row = sheet.createRow(1);
                for (int i = 0; i < value_columns2.size(); i++) {
                    //添加表头内容
                    Cell cell = row.createCell(combinedTitleSec.get(i)[2]);
                    cell.setCellValue(value_columns2.get(i));
                    cell.setCellStyle(titleStyle);
                    sheet.setColumnWidth(i, (int) ((value_columns2.get(i).length() <= 2 ? 4 : value_columns2.get(i).length()) * 2.5 + 0.72) * 256);
                }
                row = sheet.createRow(2);
                for (int i = 0; i < value_columns3.size(); i++) {
                    //添加表头内容
                    Cell cell = row.createCell(combinedTitleThree.get(i)[2]);
                    cell.setCellValue(value_columns3.get(i));
                    cell.setCellStyle(titleStyle);
                    sheet.setColumnWidth(i, (int) ((value_columns3.get(i).length() <= 2 ? 4 : value_columns3.get(i).length()) * 2.5 + 0.72) * 256);
                }
                if (sheetIndex == 1) {
                    combinedTitle.addAll(combinedTitleSec);//合并表头前将要合并的放到一个集合中
                }
                for (Integer[] arr : combinedTitle) {//合并表头
                    if (((arr[2] > 0 || arr[3] > 0) && arr[2] != arr[3]) || (arr[0] > 0 || arr[1] > 0)) {
                        CellRangeAddress cellAddresses = new CellRangeAddress(arr[0], arr[1], arr[2], arr[3]);
                        sheet.addMergedRegion(cellAddresses);
                        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
                        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
                        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
                        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);
                    }
                }
                boolean isHaveIndex = true;
                //判断表格是否有序号列
                if(!value_columns1.contains("序号") && !value_columns2.contains("序号")){
                    isHaveIndex = false;
                }
                //把数据添加到excel

                int ii = 0;

                for (int i = 0; i < datalist.size(); i++) {
                    row = sheet.createRow(ii + 3);
                    //创建单元格,并设置值
                    if (isHaveIndex){
                        //创建单元格,并设置值
                        int j = 1;
                        Cell cell = row.createCell(0);
                        cell.setCellValue(i+1);
                        cell.setCellStyle(cellStyle);
                        for (String s : key_columns) {
                            cell = row.createCell(j);
                            cell.setCellValue(datalist.get(i).getString(s));
                            cell.setCellStyle(cellStyle);
                            j++;
                        }
                        ii++;
                    }else {
                        //创建单元格,并设置值
                        int j = 0;
                        for (String s : key_columns) {
                            Cell cell = row.createCell(j);
                            cell.setCellValue(datalist.get(i).getString(s));
                            cell.setCellStyle(cellStyle);
                            j++;
                        }
                        ii++;
                    }

                }
                sheetIndex++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Date date1 = new Timestamp(System.currentTimeMillis());
        System.out.println("excel导出结束时间:"+(date1.getTime()-date.getTime()));
        return workbook;
    }

}

4.总结

        图上代码兼容单行标题, 两行 和三行标题的表头格式导出.  但是此方式略显麻烦。下一章将会对此工具类进行优化, 将会采用 EasyExcel 替换掉 SXSSFWorkbook . 前端传参的方式不变. 性能方面略有提升, 将 XSSF 替换为SXSSF 之后会有明显的性能提升

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值