我无力抗拒 2023-11-09 16:49 采纳率: 33.3%
浏览 14
已结题

如何使用eazyexcel填充对象中的list

需要效果如图

img


目前的占位符,生成的签到次数{d3.visitshow}只能生成第一行

img


 @ApiOperation("员工考勤-导出excel")
    @PostMapping("empAttendance/export")
    @SneakyThrows
    public void empAttendanceExport(@RequestBody CustomerVisitPageQuery query, HttpServletResponse response) {
        TableDataInfo tableDataInfo = customerVisitService.empAttendance(getLoginUser().getUser(), query);
        List<EmpAttendanceVO> rows = (List<EmpAttendanceVO>) tableDataInfo.getRows();
        int id = 0;
        for (EmpAttendanceVO row : rows) {
            id++;
            row.setId(id);
        }
        //第二页表格数据填充
        List<EmpAttendanceVO> rowForTwo = new ArrayList<>();
        for (EmpAttendanceVO empAttendanceVO : rows) {
            EmpAttendanceVO clonedEmpAttendanceVO = new EmpAttendanceVO();
            BeanUtils.copyProperties(empAttendanceVO, clonedEmpAttendanceVO);
            rowForTwo.add(clonedEmpAttendanceVO);
        }

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.ms.excel");
        String fileName = URLEncoder.encode("考勤表", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + "xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        InputStream resourceAsStream = MmmCrmApplication.class.getClassLoader().getResourceAsStream("visitDetail.xlsx");
        // 第一次填充
        String tempFilePath = "temp.xlsx";
        try {
            // 创建 ExcelWriter 对象
            ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(resourceAsStream).build();

            // 创建 WriteSheet 对象
            WriteSheet writeSheet1 = EasyExcel.writerSheet("出勤汇总").build(); // 第一页
            WriteSheet writeSheet2 = EasyExcel.writerSheet("出勤详情").build(); // 第二页
            // 进行填充操作
            excelWriter.fill(rows,  writeSheet1);
            // 创建 FillConfig 对象
            FillConfig build = FillConfig.builder()
                    //设置填充方向为水平
                    .direction(WriteDirectionEnum.HORIZONTAL)
                    .build();
            //获取当月天数,并遍历填充
            int dayCount = query.getDayCount();
            List<DayCount> dayCounts = new ArrayList<>();
            for (int i = 1; i <= dayCount; i++) {
                DayCount dayC = new DayCount();
                dayC.setDay(i);
                dayCounts.add(dayC);
            }
            excelWriter.fill(new FillWrapper("d1",rowForTwo),writeSheet2);
            excelWriter.fill(new FillWrapper("d2",dayCounts),build,writeSheet2);

            for (EmpAttendanceVO empAttendanceVO : rowForTwo) {
                List<VisitCalendar> visitCalendarByMonth = customerVisitService.getVisitCalendarByMonth(query);
                for (VisitCalendar visitCalendar : visitCalendarByMonth) {
                    String visitType = visitCalendar.getVisitType();
                    if ("正常".equals(visitType)){
                        visitCalendar.setVisitShow("√");
                    }
                    if ("缺勤".equals(visitType)){
                        visitCalendar.setVisitShow("0");
                    }
                    if ("休息".equals(visitType)){
                        visitCalendar.setVisitShow("休");
                    }
                    if ("迟到/早退".equals(visitType)){
                        visitCalendar.setVisitShow(visitCalendar.getVisitCount()+"");
                    }
                    if ("无效出勤".equals(visitType)){
                        visitCalendar.setVisitShow(visitCalendar.getVisitCount()+"");
                    }
                    if ("未出数据".equals(visitType)){
                        visitCalendar.setVisitShow("\\");
                    }
                }
                excelWriter.fill(new FillWrapper("d3",visitCalendarByMonth),build,writeSheet2);
            }
            // 关闭 ExcelWriter 对象,释放资源
            excelWriter.finish();
        } finally {
            // 删除临时文件
            File tempFile = new File(tempFilePath);
            tempFile.delete();
        }
    }


```java
package mmm.crm.business.vo;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: XGY
 * @Date: 2023/10/26 10:48
 * 员工考勤vo
 */
@Data
public class EmpAttendanceVO {
    private int id;
    @ApiModelProperty("员工编号")
    private Long userId;
    @ApiModelProperty("员工姓名")
    private String empName;
    @ApiModelProperty("员工手机号")
    private String phoneNum;
    @ApiModelProperty("所属大区")
    private String bigRegion;
    @ApiModelProperty("本月应出勤天数")
    private int requiredDays;
    @ApiModelProperty("有效出勤天数")
    private int effectiveDays;
    @ApiModelProperty("无效出勤天数")
    private int invalidDays;
    @ApiModelProperty("缺勤天数")
    private int absenteeismDays;
    @ApiModelProperty("迟到早退天数")
    private int lateDays;
    @ApiModelProperty("签到次数")
    private int visitCount;
    @ApiModelProperty("签到情况")
    private List<VisitCalendar> visitCalendar;

}


```java


package mmm.crm.business.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Date;

/**
 * @Author: XGY
 * @Date: 2023/10/31 18:01
 * 签到日历格式
 */
@Data
public class VisitCalendar {
    //日期
    @ApiModelProperty("对应日期")
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-M-d")
    private Date date;
    //签到数量
    private int visitCount;
    //当日签到类型(正常,无效,缺勤,迟到/早退)
    private String visitType;
    //excel表签到情况展示
    private String visitShow;
}

还需要给每一行根据VisitShow字段的值设置不同的颜色
  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-11-10 06:30
    关注

    【以下回答由 GPT 生成】

    您好!根据您给出的代码和问题描述,我了解到您目前的问题有两个方面:

    1. 占位符生成的签到次数只能生成第一行,无法在每一行中正确填充。
    2. 您希望优化代码以填充第二页的表格数据。

    针对这两个问题,我将分别给出解决方案:

    问题一:占位符生成的签到次数只能生成第一行

    根据您提供的代码,我看到您遍历rows时,在每次循环中逐一给row对象的id属性赋值,但在模板中使用的占位符{d3.visitshow}是没有参考row对象id属性的。

    要解决这个问题,您可以通过在模板中使用foreach标签,并结合占位符来动态生成多行,实现在每一行中正确填充签到次数。下面是具体的解决方案:

    1. 首先,在模板中添加foreach标签和占位符,示例代码如下:

    ```html ...

    {d3.visitshow}

    ...

    ...
    {d3.visitshow}
    ...

    ... ```

    1. 在代码中,您需要修改表格数据的填充逻辑。将第一次填充和第二页的表格数据填充逻辑合并为一个逻辑,分为以下几个步骤:

    a. 创建一个ExcelWriter对象,并指定模板文件路径:

    ```java // 设置第一次填充的数据 List data = new ArrayList<>(); // 填充第一次的数据 ...

    // 创建 ExcelWriter 对象 ExcelWriter excelWriter = new ExcelWriter(tempFilePath, resourceAsStream, ExcelTypeEnum.XLSX); ```

    b. 分别根据模板中的“表1”和“表2”获取对应的Sheet对象:

    ```java // 获取“表1”的Sheet对象 Sheet sheet1 = excelWriter.getSheet("表1");

    // 获取“表2”的Sheet对象 Sheet sheet2 = excelWriter.getSheet("表2"); ```

    c. 将填充第一次的数据写入“表1”的指定位置:

    ```java // 写入“表1”的数据 for (int i = 0; i < data.size(); i++) { // 插入行前移动行号 sheet1.shiftRows(i + 1, sheet1.getLastRowNum(), 1, true, false);

       Row row = sheet1.createRow(i + 1);
       EmpAttendanceVO empAttendanceVO = data.get(i);
    
       // 设置第一列的id值
       Cell cell1 = row.createCell(0, CellType.NUMERIC);
       cell1.setCellValue(empAttendanceVO.getId());
    
       // 设置第二列的name值
       Cell cell2 = row.createCell(1, CellType.STRING);
       cell2.setCellValue(empAttendanceVO.getName());
    
       // 设置第三列的visitshow值(使用占位符,会在后面填充)
       Cell cell3 = row.createCell(2, CellType.STRING);
       cell3.setCellValue("{d3.visitshow}");
    
       ...
    

    } ```

    d. 将填充第二页的数据写入“表2”的指定位置:

    ```java // 写入“表2”的数据 List rowForTwo = new ArrayList<>(); for (EmpAttendanceVO empAttendanceVO : rows) { EmpAttendanceVO clonedEmpAttendanceVO = new EmpAttendanceVO(); BeanUtils.copyProperties(empAttendanceVO, clonedEmpAttendanceVO); rowForTwo.add(clonedEmpAttendanceVO); }

    for (int i = 0; i < rowForTwo.size(); i++) { Row row = sheet2.createRow(i + 1); EmpAttendanceVO empAttendanceVO = rowForTwo.get(i);

       // 设置第一列的id值
       Cell cell1 = row.createCell(0, CellType.NUMERIC);
       cell1.setCellValue(empAttendanceVO.getId());
    
       // 设置第二列的name值
       Cell cell2 = row.createCell(1, CellType.STRING);
       cell2.setCellValue(empAttendanceVO.getName());
    
       // 设置第三列的visitshow值(使用占位符,会在后面填充)
       Cell cell3 = row.createCell(2, CellType.STRING);
       cell3.setCellValue("{d3.visitshow}");
    
       ...
    

    } ```

    e. 在数据填充完毕后,将Excel写入输出流:

    java excelWriter.write(outputStream);

    f. 最后,关闭资源:

    java excelWriter.finish();

    完整的代码如下所示:

    ```java // 设置第一次填充的数据 List data = new ArrayList<>(); // 填充第一次的数据 ...

    // 创建 ExcelWriter 对象 ExcelWriter excelWriter = new ExcelWriter(tempFilePath, resourceAsStream, ExcelTypeEnum.XLSX);

    // 获取“表1”的Sheet对象 Sheet sheet1 = excelWriter.getSheet("表1");

    // 获取“表2”的Sheet对象 Sheet sheet2 = excelWriter.getSheet("表2");

    // 写入“表1”的数据 for (int i = 0; i < data.size(); i++) { // 插入行前移动行号 sheet1.shiftRows(i + 1, sheet1.getLastRowNum(), 1, true, false);

       Row row = sheet1.createRow(i + 1);
       EmpAttendanceVO empAttendanceVO = data.get(i);
    
       // 设置第一列的id值
       Cell cell1 = row.createCell(0, CellType.NUMERIC);
       cell1.setCellValue(empAttendanceVO.getId());
    
       // 设置第二列的name值
       Cell cell2 = row.createCell(1, CellType.STRING);
       cell2.setCellValue(empAttendanceVO.getName());
    
       // 设置第三列的visitshow值(使用占位符,会在后面填充)
       Cell cell3 = row.createCell(2, CellType.STRING);
       cell3.setCellValue("{d3.visitshow}");
    
       ...
    

    }

    // 写入“表2”的数据 List rowForTwo = new ArrayList<>(); for (EmpAttendanceVO empAttendanceVO : rows) { EmpAttendanceVO clonedEmpAttendanceVO = new EmpAttendanceVO(); BeanUtils.copyProperties(empAttendanceVO, clonedEmpAttendanceVO); rowForTwo.add(clonedEmpAttendanceVO); }

    for (int i = 0; i < rowForTwo.size(); i++) { Row row = sheet2.createRow(i + 1); EmpAttendanceVO empAttendanceVO = rowForTwo.get(i);

       // 设置第一列的id值
       Cell cell1 = row.createCell(0, CellType.NUMERIC);
       cell1.setCellValue(empAttendanceVO.getId());
    
       // 设置第二列的name值
       Cell cell2 = row.createCell(1, CellType.STRING);
       cell2.setCellValue(empAttendanceVO.getName());
    
       // 设置第三列的visitshow值(使用占位符,会在后面填充)
       Cell cell3 = row.createCell(2, CellType.STRING);
       cell3.setCellValue("{d3.visitshow}");
    
       ...
    

    }

    // 将Excel写入输出流 excelWriter.write(outputStream);

    // 关闭资源 excelWriter.finish(); ```

    问题二:优化代码以填充第二页的表格数据

    根据您的描述,您希望优化代码以填充第二页的表格数据。根据上面给出的解决方案,在代码中已经包含了填充第二页表格数据的逻辑。您只需要按照上面的方法修改并执行代码即可。

    希望这些解决方案能够帮到您!如果您有任何问题,请随时向我提问!


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月14日
  • 修改了问题 11月14日
  • 赞助了问题酬金15元 11月13日
  • 创建了问题 11月9日

悬赏问题

  • ¥18 关于#贝叶斯概率#的问题:这篇文章中利用em算法求出了对数似然值作为概率表参数,然后进行概率表计算,这个概率表是怎样计算的呀
  • ¥15 Android Navigation: 某XDirections类不能自动生成
  • ¥20 C#上传XML格式数据
  • ¥15 elementui上传结合oss接口断点续传,现在只差停止上传和继续上传,各大精英看下
  • ¥100 单片机hardfaulr
  • ¥20 手机截图相片分辨率降低一半
  • ¥50 求一段sql语句,遇到小难题了,可以50米解决
  • ¥15 速求,对多种商品的购买力优化问题(用遗传算法、枚举法、粒子群算法、模拟退火算法等方法求解)
  • ¥100 速求!商品购买力最优化问题(用遗传算法求解,给出python代码)
  • ¥15 虚拟机检测,可以是封装好的DLL,可付费