java按需导出Excel并自动合同单元格

java导出excel并单元格自动合并

最近公司有一个需求,就是按到模版导出数据报表,并内容相同的单元格实现自动合并.具体业务设计图如下所示

需求分析
  1. 由于头部是固定不变的,先使用excel创建数据模版
  2. 单元格合并,前三列需要根据内容相同自动合并单元格
  3. 根据状态来判断,状态异常的红色字体,并且已红色×标识
  4. *情况,都是多选一的,数据库只会记录一种状态,后台需要判断并在指定的单元格添加标识符
代码开发
  1. 创建情况对应的魔法值对比索引 ```java /*

    • @ClassName PatrolExportEnum
    • @Description 方便单元格选择勾选
    • @Author xiongchao
    • @Date 2020/10/20 10:02 **/ public class PatrolExportEnum {

    // 进水情况 private static Map waterInCondition; // 出水情况 private static Map waterOutCondition; // 电力情况 private static Map electryCondition; // 是否与现场一直 private static Map liveCondition; // 管网情况 private static Map pipeCondition; // 配水情况 private static Map waterCondition;

    static {

    waterInCondition = new HashMap<>();
    waterOutCondition = new HashMap<>();
    electryCondition = new HashMap<>();
    liveCondition = new HashMap<>();
    pipeCondition = new HashMap<>();
    waterCondition = new HashMap<>();
    
    waterInCondition.put("无",0);
    waterInCondition.put("少",1);
    waterInCondition.put("正常",2);
    waterInCondition.put("有溢流",3);
    
    waterOutCondition.put("正常",0);
    waterOutCondition.put("无水",1);
    
    electryCondition.put("正常",0);
    electryCondition.put("故障",1);
    
    liveCondition.put("一致",0);
    liveCondition.put("不一致",1);
    
    pipeCondition.put("管道",0);
    pipeCondition.put("井盖",1);
    pipeCondition.put("沉沙井",2);
    
    waterCondition.put("均匀",0);
    waterCondition.put("堵塞",1);

    }

    public static Integer getWaterInCondition(String waterIn) { return waterInCondition.get(waterIn); }

    public static Integer getWaterOutCondition(String waiterOut) { return waterOutCondition.get(waiterOut); }

    public static Integer getElectryCondition(String electry) { return electryCondition.get(electry); }

    public static Integer getLiveCondition(String live) { return liveCondition.get(live); }

    public static Integer getPipeCondition(String pipe) { return pipeCondition.get(pipe); }

    public static Integer getWaterCondition(String water) { return waterCondition.get(water); }

}

```

  1. 导出数据实体类 ```java public class PatrolTaskExport {

    private String street;

    private String xVillage;

    private String zVlillage;

    private String patrolTime;

    private String patrolPerson;

    private String content;

    private String waterInCondition;

    private String waterOutCondition;

    private String electryCondition;

    private List equConditionList;

    private String isSame;

    private List pipeCondition;

    private String waterSupport;

    private String afforestCondition;

    public String getStreet() { return street; }

    public void setStreet(String street) { this.street = street; }

    public String getxVillage() { return xVillage; }

    public void setxVillage(String xVillage) { this.xVillage = xVillage; }

    public String getzVlillage() { return zVlillage; }

    public void setzVlillage(String zVlillage) { this.zVlillage = zVlillage; }

    public String getPatrolTime() { return patrolTime; }

    public void setPatrolTime(String patrolTime) { this.patrolTime = patrolTime; }

    public String getPatrolPerson() { return patrolPerson; }

    public void setPatrolPerson(String patrolPerson) { this.patrolPerson = patrolPerson; }

    public String getContent() { return content; }

    public void setContent(String content) { this.content = content; }

    public String getWaterInCondition() { return waterInCondition; }

    public void setWaterInCondition(String waterInCondition) { this.waterInCondition = waterInCondition; }

    public String getWaterOutCondition() { return waterOutCondition; }

    public void setWaterOutCondition(String waterOutCondition) { this.waterOutCondition = waterOutCondition; }

    public String getElectryCondition() { return electryCondition; }

    public void setElectryCondition(String electryCondition) { this.electryCondition = electryCondition; }

    public String getIsSame() { return isSame; }

    public void setIsSame(String isSame) { this.isSame = isSame; }

    public List getPipeCondition() { return pipeCondition; }

    public void setPipeCondition(List pipeCondition) { this.pipeCondition = pipeCondition; }

    public String getWaterSupport() { return waterSupport; }

    public void setWaterSupport(String waterSupport) { this.waterSupport = waterSupport; }

    public String getAfforestCondition() { return afforestCondition; }

    public void setAfforestCondition(String afforestCondition) { this.afforestCondition = afforestCondition; }

    public static class equCondition {

    public equCondition (String name,String value){
        this.name = name;
        this.value = value;
    }
    
    private String name;
    
    private String value;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getValue() {
        return value;
    }
    
    public void setValue(String value) {
        this.value = value;
    }

    }

    public List getEquConditionList() { return equConditionList; }

    public void setEquConditionList(List equConditionList) { this.equConditionList = equConditionList; } } ```

  2. 对应的服务类 ```java

/* * @ClassName ExcelExportService * @Description TODO * @Author xiongchao * @Date 2020/10/20 10:42 */ public interface ExcelExportService {

/**
 * 数据导出,格式转化
 * @param fileName
 * @param rootPath
 * @param list
 * @return
 */
FileData exportFile(String fileName, String rootPath, List<PatrolTaskExport> list);


/**
 * 获取导出数据
 * @param param
 * @return
 */
List<PatrolTaskExport> getExportData(Map<String,Object> param);

}

```

  1. 接口实现类 ```java

@Service public class ExcelExportServiceImpl implements ExcelExportService {

private static final String yes ="√";
private static final String no ="×";

private Logger log = LoggerFactory.getLogger(ExcelExportServiceImpl.class);

private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Override
public FileData exportFile(String fileName, String rootPath, List<PatrolTaskExport> list) {
    if (CollectionUtils.isEmpty(list)) {
        log.error("导出数据不能为空!");
        return null;
    }
    FileData fileData = null;
    Sheet sheet = null;
    Workbook workbook = null;
    Row row = null;
    try {
        workbook= ExcelUtil.readExcel(rootPath);
        CellStyle cellStyle =  workbook.createCellStyle();
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        Font font = workbook.createFont();
        font.setColor(HSSFColor.RED.index);

        //导出月份时间
        String month = getMonth();
        if(workbook != null) {
            sheet = workbook.getSheetAt(0);
        }
        if(sheet != null){
            //开始日期
            row= sheet.getRow(1);
            row.getCell(0).setCellValue(month);

            // 第四行开始写入数据
            int rowNum = 4;
            int index = 1;
            //明确只有 2,3,4 需要根据重复内容合并
            //上一个街镇名称
            String perPurpose = "";
            String perxVillage = "";
            String perzVliiage= "";
            //要融合的第一行
            int startMergeCol = 4;
            int xStartMergeCol = 4;
            int zStartMergeCol = 4;
            int xendMergeCol = 3;
            int zendMergeCol = 3;
            //要融合的最后行
            int endMergeCol = 3;
            //勾选的数字
            Integer selectIndex = null;
            //用来记录是否是第一次循环
            boolean flag = true;

            int cellNum = sheet.getRow(3).getLastCellNum();
            //先建单元格
            for(PatrolTaskExport vo :list){
                row = sheet.createRow(rowNum);
                for(int i=0;i<cellNum;i++){
                    row.createCell(i);
                }
                rowNum++;
            }

            rowNum =4;
            for(PatrolTaskExport vo :list){
                row = sheet.getRow(rowNum);
                //开始写入数据
                createCell(row,cellStyle,0,String.valueOf(index));
                createCell(row,cellStyle,1,vo.getStreet());
                if(flag){
                    perPurpose = vo.getStreet();
                    perzVliiage = vo.getzVlillage();
                    perxVillage =vo.getxVillage();
                    flag = false;
                }

                if(perzVliiage.equalsIgnoreCase(vo.getzVlillage())){
                    zendMergeCol ++;
                } else {
                    if(zendMergeCol > zStartMergeCol){
                        sheet.addMergedRegion(new CellRangeAddress(zStartMergeCol,zendMergeCol,3,3));
                    }
                    zStartMergeCol = rowNum;
                    zendMergeCol = zStartMergeCol;
                    perzVliiage = vo.getzVlillage();
                }

                if(perxVillage.equalsIgnoreCase(vo.getxVillage())){
                    xendMergeCol ++;
                } else {
                    if(xendMergeCol > xStartMergeCol){
                        sheet.addMergedRegion(new CellRangeAddress(xStartMergeCol,xendMergeCol,2,2));
                    }
                    xStartMergeCol = rowNum;
                    xendMergeCol = xStartMergeCol;
                    perxVillage = vo.getxVillage();
                }

                if(perPurpose.equals(vo.getStreet())){
                    endMergeCol ++;
                } else {
                    //并且之前相同的单元格
                    if(startMergeCol < endMergeCol){
                        sheet.addMergedRegion(new CellRangeAddress(startMergeCol,endMergeCol,1,1));
                    }
                    startMergeCol = rowNum;
                    endMergeCol = startMergeCol;
                    perPurpose = vo.getStreet();
                }
                createCell(row,cellStyle,2,vo.getxVillage());
                createCell(row,cellStyle,3,vo.getzVlillage());
                createCell(row,cellStyle,4,vo.getPatrolTime());

                selectIndex = PatrolExportEnum.getWaterInCondition(vo.getWaterInCondition());
                if(selectIndex != null) {
                    if(selectIndex.equals(3)){
                        CellStyle style = colorRed(workbook,font);
                        createCell(row,style,5 + selectIndex,no);
                    }else{
                        createCell(row,cellStyle,5 + selectIndex,yes);
                    }
                    selectIndex = null;
                }
                selectIndex = PatrolExportEnum.getWaterOutCondition(vo.getWaterOutCondition());
                if(selectIndex != null){
                    if(selectIndex.equals(1)){
                        CellStyle style = colorRed(workbook,font);
                        createCell(row,style,9 + selectIndex,no);
                    }else {
                        createCell(row,cellStyle,9 + selectIndex,yes);
                    }
                    selectIndex  = null;
                }

                selectIndex = PatrolExportEnum.getElectryCondition(vo.getElectryCondition());
                if(selectIndex != null) {
                    if(selectIndex.equals(1)){
                        CellStyle style = colorRed(workbook,font);
                        createCell(row,style,11 + selectIndex,no);
                    }else{
                        createCell(row,cellStyle,11 + selectIndex,yes);
                    }
                    selectIndex  = null;
                }
                List<PatrolTaskExport.equCondition> conditions = vo.getEquConditionList();
                if(!CollectionUtils.isEmpty(conditions)){
                    for(PatrolTaskExport.equCondition e : conditions){
                        String value = e.getValue();
                        String name = e.getName();
                        if ("格栅".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,13,value);
                        }
                        if ("水泵".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,14 ,value);
                        }
                        if ("风机".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,15 ,value);
                        }
                        if ("液位计".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,16 ,value);
                        }
                    }
                }
                selectIndex = PatrolExportEnum.getLiveCondition(vo.getIsSame());
                if(selectIndex != null) {
                    if (selectIndex.equals(1)) {
                        CellStyle style = colorRed(workbook,font);
                        createCell(row,style,17 + selectIndex,no);
                    }else {
                        createCell(row,cellStyle,17 + selectIndex,yes);
                    }
                   selectIndex = null;
                }

                List<PatrolTaskExport.equCondition> pipeCodintion = vo.getPipeCondition();
                if(!CollectionUtils.isEmpty(pipeCodintion)){
                    for(PatrolTaskExport.equCondition e : pipeCodintion){
                        String value = e.getValue();
                        String name = e.getName();
                        if ("管道".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,19,value);
                        }
                        if ("井盖".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,20 ,value);
                        }
                        if ("沉沙井".equalsIgnoreCase(name)) {
                            CellStyle style = setColor(value,workbook,font);
                            createCell(row,style,21 ,value);
                        }
                    }
                }


                selectIndex = PatrolExportEnum.getWaterCondition(vo.getWaterSupport());
                if(selectIndex != null){
                    if (selectIndex.equals(1)) {
                        CellStyle style = colorRed(workbook,font);
                        createCell(row,style,22 + selectIndex,no);
                    }else {
                        createCell(row,cellStyle,22 + selectIndex,yes);
                    }
                    selectIndex = null;
                }

                createCell(row,cellStyle,24 ,vo.getAfforestCondition());
                createCell(row,cellStyle,25 ,vo.getPatrolPerson());
                createCell(row,cellStyle,26 ,vo.getContent());
                rowNum++;
                index ++;

            }
            if(startMergeCol < endMergeCol){
                sheet.addMergedRegion(new CellRangeAddress(startMergeCol,endMergeCol,1,1));
            }
            if(xendMergeCol > xStartMergeCol){
                sheet.addMergedRegion(new CellRangeAddress(xStartMergeCol,xendMergeCol,2,2));
            }
            if(zendMergeCol > zStartMergeCol){
                sheet.addMergedRegion(new CellRangeAddress(zStartMergeCol,zendMergeCol,3,3));
            }
        }
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        fileData  = new FileData();
        workbook.write(os);
        os.flush();
        fileData.setBytes(os.toByteArray());
        fileData.setFileName(fileName);

    } catch (IOException e) {
        log.error("partrol_report_export_error");
        e.printStackTrace();
    }
    return fileData;
}


@Override
public List<PatrolTaskExport> getExportData(Map<String, Object> param) {

    List<PatrolTaskExport> list = new ArrayList<>();
    for (int i = 0; i < 100 ; i++) {
        PatrolTaskExport pa = new PatrolTaskExport();
        if(i == 6) {
            pa.setStreet("公孙街道");
        }else{
            pa.setStreet("关山街道");
        }

        pa.setzVlillage("黄龙山村"+i);
        pa.setPatrolTime("2020-12-" + i);
        if(i%2 == 0){
            pa.setWaterInCondition("正常");
            pa.setWaterOutCondition("无水");
            pa.setIsSame("一致");
            pa.setPatrolPerson("张三" + i);
            pa.setxVillage("木槿村委会");
        }else{
            pa.setWaterInCondition("少");
            pa.setWaterOutCondition("正常");
            pa.setIsSame("不一致");
            pa.setPatrolPerson("张三" + i);
            pa.setxVillage("轰隆声村委会");
        }
        pa.setElectryCondition("故障");
        List<PatrolTaskExport.equCondition> conditions = new ArrayList<>();
        conditions.add(new PatrolTaskExport.equCondition("格栅","正常"));
        conditions.add(new PatrolTaskExport.equCondition("水泵","异常"));
        conditions.add(new PatrolTaskExport.equCondition("风机","正常"));
        conditions.add(new PatrolTaskExport.equCondition("液位计","异常"));
        pa.setEquConditionList(conditions);

        List<PatrolTaskExport.equCondition> pipeconditions = new ArrayList<>();
        pipeconditions.add(new PatrolTaskExport.equCondition("管道","正常"));
        pipeconditions.add(new PatrolTaskExport.equCondition("井盖","异常"));
        pipeconditions.add(new PatrolTaskExport.equCondition("沉沙井","正常"));

        pa.setPipeCondition(pipeconditions);
        pa.setWaterSupport("堵塞");
        pa.setAfforestCondition("除杂草");
        pa.setContent("这是备注信息");
        list.add(pa);
    }
    return list;
}

private  String getMonth(){
    Calendar date = Calendar.getInstance();
    String year = String.valueOf(date.get(Calendar.YEAR));
    String month = String.valueOf(date.get(Calendar.MONTH) + 1);
    return year + "年" + month + "月";
}

private void createCell(Row row,CellStyle cellStyle ,int rowNum,String value){
    Cell cell = row.getCell(rowNum);
    cell.setCellStyle(cellStyle);
    cell.setCellValue(value);
}

private CellStyle setColor(String  value ,Workbook workbook,Font font){
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
    if(value.equalsIgnoreCase("异常")){
        cellStyle.setFont(font);
        return cellStyle;
    }
    return  cellStyle;
}

private CellStyle colorRed(Workbook workbook,Font font){
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
    cellStyle.setFont(font);
    return cellStyle;
}

}

```

  1. 暴露接口并测试 controller层 ```java @Api(tags = "巡检任务报表导出") @RequestMapping("/api") @RestController public class PatrolTaskResource {

    @Autowired private ExcelExportService exportService;

    @ApiOperation(value = "巡检任务报表导出") @GetMapping("/partorl-task/export") public void patrolReportExport( @ApiParam(value = "查询条件") @RequestParam(value = "param",required = false) String param, HttpServletRequest request, HttpServletResponse response ){ long start =System.currentTimeMillis(); Map map = new HashMap<>(); if(StringUtils.isNotEmpty(param)){ map.put("param",param); } List list = exportService.getExportData(map); String rootPath = ImportTypeEnum.REPORT.getFilePath(); String fileName = ImportTypeEnum.REPORT.getFileName();

    FileData file = exportService.exportFile(fileName,rootPath,list);
    try {
        ExcelUtil.setResponse(request, response,file);
    } catch (Exception e) {
        e.printStackTrace();
    }

    } } ```

最终展示结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
若要在 Java导出 Excel 并合并特定单元格,可以使用 Apache POI 这个开源库。下面是一个简单的示例,将第一行第一列到第一行第四列的单元格合并,并将文本居中。 ```java import java.io.FileOutputStream; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelExportExample { public static void main(String[] args) { // 创建一个新的工作簿 Workbook workbook = new XSSFWorkbook(); // 创建一个新的工作表 Sheet sheet = workbook.createSheet("Sheet1"); // 创建一行,行号为 0 Row row = sheet.createRow(0); // 创建第一个单元格单元格位置为 (0, 0) Cell cell1 = row.createCell(0); cell1.setCellValue("合并单元格示例"); // 创建第一行第一列到第一行第四列的单元格,并合并它们 CellRangeAddress region = new CellRangeAddress(0, 0, 0, 3); sheet.addMergedRegion(region); // 设置合并后的单元格的样式 CellStyle style = workbook.createCellStyle(); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); cell1.setCellStyle(style); // 将工作簿写入文件 try { FileOutputStream outputStream = new FileOutputStream("example.xlsx"); workbook.write(outputStream); workbook.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 上面的代码首先创建了一个新的工作簿和工作表,然后创建了一行和第一个单元格,并将其设置为合并单元格。接着,创建了一个单元格样式,并将其应用于合并后的单元格。最后,将工作簿写入文件。 注意:上面的代码使用了 XSSFWorkbook 类,这是一个适用于 Excel 2007 及以上版本的类。如果要导出 Excel 2003 及以下版本的文件,要使用 HSSFWorkbook 类。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值