Java导出Excel

一、导入pom

<!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
            <version>2.12.0</version>
        </dependency>

正常导出行列

public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
    /**
     * 导出excel
     */
    public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        File file = new File(tempPath);
        BigExcelWriter writer = ExcelUtil.getBigWriter(file);
        // 一次性写出内容,使用默认样式,强制输出标题
        writer.write(list, true);
        SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
        //上面需要强转SXSSFSheet  不然没有trackAllColumnsForAutoSizing方法
        sheet.trackAllColumnsForAutoSizing();
        //列宽自适应
        writer.autoSizeColumnAll();
        //列宽自适应支持中文单元格
        sizeChineseColumn(sheet, writer);
        //response为HttpServletResponse对象
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
        ServletOutputStream out = response.getOutputStream();
        // 终止后删除临时文件
        file.deleteOnExit();
        writer.flush(out, true);
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }

    /**
     * 自适应宽度(中文支持)
     */
    private static void sizeChineseColumn(SXSSFSheet sheet, BigExcelWriter writer) {
        for (int columnNum = 0; columnNum < writer.getColumnCount(); columnNum++) {
            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
            for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                SXSSFRow currentRow;
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }
                if (currentRow.getCell(columnNum) != null) {
                    SXSSFCell currentCell = currentRow.getCell(columnNum);
                    if (currentCell.getCellTypeEnum() == CellType.STRING) {
                        int length = currentCell.getStringCellValue().getBytes().length;
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }
            sheet.setColumnWidth(columnNum, columnWidth * 256);
        }
    }

以上这个方法可以放在FileUtils里进行调用,需要传入一个List<Map<String, Object>> list,实例如下:

public void download(List<FellowshipTask> fellowshipTasks, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (FellowshipTask ft : fellowshipTasks) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("任务标题", ft.getTitle());
            map.put("要求字数", ft.getWord());
            map.put("截止日期", ft.getDeadline());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

其中这个是Service层的方法,List fellowshipTasks是一个需要导出的数据集合,很好理解,照葫芦画瓢即可,“任务标题”、“要求字数”、“截至日期”即一共有三列,可以做到导出数据时列宽自适应,包括中文的。


这样可以导出最基本的行列数据,但是如果需要合并单元格,则需要对上述变量中的sheet做修改:

CellRangeAddress region = new CellRangeAddress(startRow, endRow, startCol, endCol);
sheet.addMergedRegion(region);

这里的一个region代表一个合并区域,需要指定开始行,结束行,开始列,结束列,就是一个矩形区域。所以这个地方需要结合自己的业务需求进行单独设置。

如果需要合并单元格,可以在downloadExcel方法参数中添加一个List regions参数,之后添加:

for (CellRangeAddress region : regions) {
     sheet.addMergedRegion(region);
}

接下来是设置某个单元格的具体样式,比如要设置某些单元格的样式为超链接:

// 设置超链接格式
SXSSFWorkbook workbook = new SXSSFWorkbook();
CreationHelper createHelper = workbook.getCreationHelper();
//如果有多个,下面的代码需要放循环里,动态指定cell的行列
XSSFHyperlink link = (XSSFHyperlink) createHelper.createHyperlink(HyperlinkType.URL);
SXSSFCell cell = sheet.getRow(1).getCell(1);
link.setAddress("https://www.makeyourchoice.cn");
cell.setHyperlink(link);
cell.setCellValue("皆非的万事屋");

如果要设置某个单元格具体的样式,例如字体、大小、颜色、斜体等,则:

CellStyle cs = workbook.createCellStyle();
Font font = workbook.createFont();
font.setItalic(true);
short i = 10;
font.setColor(i);
cs.setFont(font);
cell.setCellStyle(cs);

但是这样设置会报错误,目前还不知道具体原因,有知道的网友可以在下方评论。

最后修改:2020 年 10 月 25 日