Spring RESTful使用java POI导出数据库记录到Excel(包含图片)

本文介绍如何在Spring RESTful应用中使用Java POI库将数据库记录导出为Excel文件,并且包含图片。首先,讨论了项目的需求背景,然后详细解释了解决方案的四个步骤:添加POI依赖、实现service和服务实现、定义Controller的REST接口以及创建测试HTML页面。

目的:Spring RESTful使用java POI导出数据库记录到Excel(包含图片)

环境:
win10 x64
Idea 2018.2.3

问题分析:

项目临时需要添加导出mysql数据记录到Excel的功能

解决方案:

使用Java POI包进行数据导出

方法步骤:

1. Pom文件中添加对于POI包依赖

<!-- POI套件 ver3.9-->
<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
</dependency>

2. service和serviceImpl,导出示例:

CommonDataDealServiceImpl.class

@Override 
public void outputPersonInfoToExcel(HttpServletResponse response){
    /* 查询personInfo */
    PersonExampl personExample = new PersonExample();
    List<PersonExample> personList = personMapper.selectByExample(personExample);

    /* 数据库无记录 */
    if(personList.isEmpty()){
        throw new CommonException(CommonMessage.NO_DATA);
    }

    /* 设置导出Excel信息 */
    HSSFWorkbook workbook = new HSSFWorkbook();          // 创建workbook
    HSSFSheet sheet = workbook.createSheet("人员记录");   // 创建sheet, 并设置sheet名
    
    String fileName = "人员信息表.xls";                   // 导出Excel文件名
    String[] headers ={"姓名", "性别", "年龄", "头像"};    // Excel中表头

    HSSFRow headerRow = sheet.createRow)(0);            // 创建表头
    for(int i = 0; i < headers.length; i ++){
        HSSFCell cellTemp = headerRow.createCell(i);
        HSSFRichTextString headerText = new HSSFRichTextString(header[i]);
        cellTemp.setCellValue(headerText);
    }

    /* 插入数据 */
    int rowNum = 1; //从第二行(表头下一行开始插入)

    for(Person person : personList){
        HSSFRow rowTemp = sheet.createRow(rowNum);

        /* 按表头顺序插入姓名、性别、年龄 */
        rowTemp.createCell(0).setCellValue(person.getName);
        rowTemp.createCell(1).setCellValue(person.getSex);
        rowTemp.createCell(2).setCellValue(person.getAge);

        /* 插入头像图片 */
        //下载图片(插入Excel需要byte[]形式的图片, 可自行获取)
        byte[] imgBytes = localFileService.downloadFile(person.getImgPath);  

        if(image != null){  //如图片byte[]有效, 则执行插入图片到头像列
            HSSFPatriarch drawingPatriarch = sheet.createDrawingPatriarch();

            /** anchor主要用于设置图片的属性, 这里详细说明下HSSFClientAnchor的参数
            * HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)

            * dx1  左上角所在cell的偏移x坐标,一般可设0,范围值为:0~1023,超过1023就到右侧相邻的单元格里
            * dy1  左上角所在cell的偏移y坐标,一般可设0,范围值为:0~256,超过256就到下方的单元格里
            * dx2  右下角所在cell的偏移x坐标,一般可设0,范围值为:0~1023,超过1023就到右侧相邻的单元格里
            * dy2  右下角所在cell的偏移y坐标,一般可设0,范围值为:0~256,超过256就到下方的单元格里
            * col1 左上角所在列
            * row1 左上角所在行
            * col2 右下角所在列 
            * row2 右下角所在行
            * 综上: 如果图片较大, 会占据多行的多个cell, 那么就用图片所在的左上角的cell的cellNum和rowNum及图片右下角所在的cell的cellNum和rowNum来界定图片范围。
            *
            * 例: 假如人员头像占据区域是两行两列的4个cell, 下面写法需要如下(相应的循环里面的row自增时需要对应调整为 rowNum += 2):
            *  HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 3, rowNum, (short) 4, rowNum + 1);
            */
            HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 3, rowNum, (short) 3, rowNum);
            HSSFPicture pict = drawingPatriarch.createPicture(anchor, workbook.addPicture(imgBytes, HSSFWorkbook.PICTURE_TYPE_PNG));

            pict.resize(0.5);                                 // 图片等比例缩小
            sheet.setColumnWidth(3, (int) (50 + 0.72) * 256); // 设置列宽, 旧版本该函数参数类型为short
            rowTemp.setHeight((short) 256);                   // 设置行高

        }else{ //如未找到对应头像,则值设置为空
            HSSFCell cellTemp = rowTemp.createCell(3);
            cellTemp.setCellType(HSSFCell.CELL_TYPE_STRING);
            cellTemp.setCellValue("无");
        }

        rowNum += 1;
    }
    
    /* 设置response的header */
    response.setHeader("Content-disposition", "attachment; filename=" + fileName);  
    response.setContentType("application/application/Vnd.ms-excel;charset=UTF-8"); 

    try{
        response.flushBuffer();
        workbook.write(response.getOutputStream());
    } catch (IOException e){
        throw new BaseException(CommonMessage.RESPONSE_STREAM_ERROR);
    }
}

3. Controller中RESTful

@ResponseBody
@RequestMapping(value = "/output/perosnInfo", method = RequestMethod.GET)
public void outputPersonInfo(HttpServletResponse response){
    commonDataDealServiceImpl.outputPersonInfoToExcel(response);
}

4. 测试Html

<html>
    <head>
        <script>
        function dowloadFile(){
            window.location.href="http://localhost:8080/output/personInfo";
        }
        </script>
    </head>
<body>
        <table border="0" style="margin-top: 4px; margin-left: 18px">
                <tr>
                    <td> <a href="#" class="easyui-linkbutton" onclick="dowloadFile();"> 数据导出 </a></td>
                </tr>
        </table>
</body>
</html>

Tips

1. row和cell的关系, 还有序号都是从0开始。
2. 设置列宽和行高的方法。
3. 如含有图片时, 注意计算好图片占据的行列(图片实际覆盖多少格), 然后设置HSSFClientAnchor。
4. 如若请求是POST,只是添加参数,流程类似GET
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值