POI导出Excel,并合并单元格

最近根据公司需求,写一个导出Excel的功能,我使用的是POI,没有选择easyPOI,这里根据POI的基本功能,自己写了一个工具类,可以大大减少工作量,分享到这里,希望能帮到有需要的小伙伴。

先上结果

1.使用的是postman

        说明:这里是根据时间段来查询数据的。

2.controller层的代码就不贴了,直接上service层的

@Override
    public void Settlement(Map<String, Object> map, HttpServletResponse response) {
        ReportBaseReq req;
        req = new ReportBaseReq();
        req.setEndTime(map.get("endTime").toString());
        req.setStartTime(map.get("startTime").toString());
        List<SybxCntTimeSettlementResp> obj = rfAccountService.sybxCntTimeSettlement(req.getStartTime(), req.getEndTime());

        if (obj==null){
            return;
        }
        String filePath = "excelTemplate/reportformaccount/sybx_cntTimeSettlementD.xls";
        //添加表格数据
        HSSFWorkbook workbook = ExportUtils.structureExcel(obj, filePath, 4);      

        //合并单元格
        ExportUtils.mergeCells(obj,workbook,4,0,1);

        //下载表格
        ExportUtils.downLoadTable(workbook,response);
    }

2.1 请求参数:

        map是接收startTime和endTime这两个参数的

2.2 添加表格数据

       obj:是查询出来的数据对象

        filePath:这里我使用的是模板,只使用了表头的部分,filePath为加载模板的路径

        rowBegin:是开始添加数据的行数,4:为从第4行开始添加数据

2.3 合并单元格

obj:查询数据的对象

workbook:工作薄对象

mergeRowBegin:和之前的rowBegin值时一样的,但这里的意思是:开始合并的行数

columns:是需要合并的列数,0,1:合并第0 列和第1列

2.4 下载表格,固定写法

3. 然后就是下载的工具类

package com.mbf.tianjin.common.utils;

import com.mbf.tianjin.common.enums.*;
import com.mbf.tianjin.common.po.bigDataAnalysis.InsuPopKpiCntD;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author: sniper
 * @Date: 2021/06/18
 * @Description: 导出表格工具类
 */
@Slf4j
public class ExportUtils {
    /**
     * 构造Excel表
     * @param obj
     * @param filePath
     * @param rowBegin
     * @param <T>
     * @return
     */
    public static <T> HSSFWorkbook structureExcel(List<T> obj,String filePath,int rowBegin){
        Resource resource = new ClassPathResource(filePath);
        HSSFWorkbook workbook = null;
        try {
            InputStream inputStream = resource.getInputStream();
            POIFSFileSystem fspoi=new POIFSFileSystem(inputStream);
            //创建工作薄对象
             workbook=new HSSFWorkbook(fspoi);
            //获取工作表对象
            HSSFSheet sheet=workbook.getSheet("sheet1");

            //定义单元格格式
            HSSFCellStyle cellStyle = CellStyleUtils.createCellStyle(workbook,sheet, (short) 9,false,true,false,false,12,false,true);
            //填写报表数据
            int r = rowBegin;
            for(T resp :obj){
                Field[] field = resp.getClass().getDeclaredFields();
                HSSFRow  row = sheet.createRow(r);//行
                for (int i = 0; i < resp.getClass().getDeclaredFields().length; i++) {
                    field[i].setAccessible(true);//设置字段可访问, 否则无法访问private修饰的变量值
                    HSSFCell cell = row.createCell(i);//列
                    cell.setCellValue(field[i].get(resp)+"");//如果使用.toString可能会报空指针异常
                    cell.setCellStyle(cellStyle);
                }
                r++;
            }
            //修改报表日期
            LocalDate now = LocalDate.now();
            HSSFRow row = sheet.createRow(r);
            HSSFCell cell = row.createCell(0);
            cell.setCellValue("下载日期:"+now);
            CellRangeAddress cellAddresses = new CellRangeAddress(r , r, 0, 2);
            sheet.addMergedRegion(cellAddresses);
        } catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e) {
            log.info("获取属性值失败:"+e);
        }
        return workbook;
    }

    /**
     * 合并单元格
     * @param workbook
     * @param mergeRowBegin 开始合并的行
     * @param columns 需要合并的列
     */
    public static <T> void mergeCells(List<T> obj,HSSFWorkbook workbook,int mergeRowBegin,Integer... columns){
        HSSFSheet sheet = workbook.getSheet("sheet1");
        String[] str = new String[obj.size()];
        for (Integer column : columns) {
            int rowBegin = mergeRowBegin;
            //获取指定列,不同行的单元格值
            try {
                for (int i = 0; i < obj.size(); i++) { //遍历行
                    HSSFRow row = sheet.getRow(rowBegin);
                    HSSFCell cell = row.getCell(column);
                    String value = cell.getStringCellValue();
                    str[i] = value;
                    rowBegin++;
                }
            } catch (Exception e) {
                log.info("获取单元格值失败:" + e);
            }
            //合并
            try {
                int index = 0;//计数器
                for (int i = 0; i < str.length - 1; i++) {
                    index++;//1 2 3
                    //判断单元格值是否相同
                    if (!str[i].equals(str[i + 1])) {
                        if (1 - index != 0) { //如果只有一个单元格,不合并
                            CellRangeAddress cellAddresses = new CellRangeAddress(i + 1 - index + mergeRowBegin, i + mergeRowBegin, column, column);
                            sheet.addMergedRegion(cellAddresses);
                            index = 0;
                        }

                    }
                    //判断是否循环到最后一行
                    if (i + 1 == str.length - 1) {
                        if ( index != 0) {//如果只有一个单元格,不合并
                            CellRangeAddress cellAddresses = new CellRangeAddress(i + 1 - index + mergeRowBegin, i + 1 + mergeRowBegin, column, column);
                            sheet.addMergedRegion(cellAddresses);
                        }
                    }
                }
            } catch (Exception e) {
                log.info("合并单元格失败:" + e);
            }
        }
    }

    /**
     * 添加维度值
     * @param obj
     * @param workbook
     * @param rowBegin 行
     * @param map  key:维度类型  value:需要合并的列
     * @param <T>
     * @return
     */
    public static <T> HSSFWorkbook replaceValue(List<T> obj, HSSFWorkbook workbook, int rowBegin, Map<String,Integer> map){
        HSSFSheet sheet = workbook.getSheet("sheet1");
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            int r = rowBegin;
            //医疗类别('0':住院,'1':门诊,'2':门特) MED_TYPE
            if (AllDimension.MedType.getName().equals(entry.getKey())){
                for (int i = 0; i < obj.size(); i++) {
                    HSSFRow row = sheet.getRow(r);
                    HSSFCell cell = row.getCell(entry.getValue());
                    String value = cell.getStringCellValue();
                    cell.setCellValue("0".equals(value)? MedType.MedType0.getName():
                            "1".equals(value)?MedType.MedType1.getName():MedType.MedType2.getName());
                    r++;
                }
            }
}
           
    /**
     * 下载
     * @param workbook
     * @param response
     */
    public static void downLoadTable(HSSFWorkbook workbook, HttpServletResponse response){
        try {
            workbook.write(response.getOutputStream());
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode( "test.xls", "UTF-8"));
        }catch (Exception e){
            log.info("下载失败:"+e);
        }
    }
}

工具类里的方法,如何调用上面已经说过了,里面有一个方法:添加维度值,后面再说

看一下此时的效果:

已经实现了合并,但是和第一张图的结果不一样呢?这里是因为,纬度值没有添加进去

这里用到了枚举类,放一个枚举类

@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum AllDimension {
 
    InsuType("insuType"),//险种类型(0:城镇职工,1:城乡居民) INSU_TYPE

    
    private String name;
}

参数介绍:

AllDimension.MedType.getName():险种的name
0:需要替换纬度值的第0列,

obj:查询的数据对象

workbook:工作薄对象

rowBegin:开始替换纬度值的行数

m:map对象

吧这个方法加上就可以替换维度了。

纯属原创分享,希望各路大神指点。

 个人LeetCode复习,可以在idea中随机获取一道题,再也不需要打开LeetCode官网了

GitHub - microsniper/leetcode-review: leetcode algorithm reviewleetcode algorithm review. Contribute to microsniper/leetcode-review development by creating an account on GitHub.https://github.com/microsniper/leetcode-review

 喜欢的朋友随手给个 star 呀

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Apache poi 导出excel合并单元格可以使用setRegionStyle方法来设置合并单元格的样式。这个方法接受三个参数,分别是Sheet对象、CellRangeAddress对象和CellStyle对象。在这个方法中,通过循环遍历合并单元格的每一行和每一列,然后获取对应的单元格并设置样式。具体的代码实现可以参考引用\[1\]中的示例代码。 此外,还可以使用PoiModel类来定义导出excel时的数据模型。这个类包含了内容、上一行同一位置内容、行标、列标等属性。可以根据实际需求来使用这个类。具体的代码实现可以参考引用\[2\]和引用\[3\]中的示例代码。 总结起来,Apache poi 导出excel合并单元格的步骤包括设置合并单元格的样式和定义导出数据的模型。可以根据具体的需求来使用相应的方法和类来实现导出功能。 #### 引用[.reference_title] - *1* *3* [poi 导出Excel 动态 合并单元格](https://blog.csdn.net/weixin_65436454/article/details/127806178)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [使用POI 导出Excel 动态合并单元格](https://blog.csdn.net/weixin_41722928/article/details/112849624)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值