zouyu
2026-04-13 8cbb4e01b9226b32797a48489c5e1b30da3e2110
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.ruoyi.inspect.excel.handler;
 
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import com.ruoyi.inspect.excel.StaffAttendanceAnnotationTextExcelData;
import com.ruoyi.inspect.excel.StaffAttendanceExcelData;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
 
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * 人员考勤导出写入处理器
 * 1. 补齐模板中不存在的班次明细单元格
 * 2. 在对应单元格上写入批注
 */
public class CommentWriteHandler implements RowWriteHandler {
 
    /**
     * 模板数据起始行为第 5 行
     */
    private static final int DATA_START_ROW_INDEX = 4;
 
    /**
     * 模板班次起始列为 C 列
     */
    private static final int DATA_START_COLUMN_INDEX = 2;
 
    private final List<StaffAttendanceExcelData> excelDataList;
 
    private final Map<String, String> annotationTextMap = new HashMap<>();
 
    public CommentWriteHandler(List<StaffAttendanceExcelData> excelDataList,
            List<StaffAttendanceAnnotationTextExcelData> annotationTextList) {
        this.excelDataList = excelDataList == null ? Collections.emptyList() : excelDataList;
        if (annotationTextList == null) {
            return;
        }
        annotationTextList.stream()
                .filter(item -> item != null && StringUtils.isNotBlank(item.getAnnotationText()))
                .forEach(item -> annotationTextMap.put(buildKey(item.getRowIndex(), item.getCellIndex()),
                        item.getAnnotationText()));
    }
 
    @Override
    public void afterRowDispose(RowWriteHandlerContext context) {
        if (BooleanUtils.isTrue(context.getHead())) {
            return;
        }
        Row row = context.getRow();
        if (row == null || row.getRowNum() < DATA_START_ROW_INDEX) {
            return;
        }
        int dataIndex = row.getRowNum() - DATA_START_ROW_INDEX;
        if (dataIndex < 0 || dataIndex >= excelDataList.size()) {
            return;
        }
        StaffAttendanceExcelData excelData = excelDataList.get(dataIndex);
        if (excelData == null || excelData.getShiftList() == null) {
            return;
        }
 
        Sheet sheet = row.getSheet();
        CellStyle cellStyle = sheet.getColumnStyle(DATA_START_COLUMN_INDEX);
        Drawing<?> drawingPatriarch = null;
        List<String> shiftList = excelData.getShiftList();
        for (int i = 0; i < shiftList.size(); i++) {
            int cellIndex = DATA_START_COLUMN_INDEX + i;
            Cell cell = row.getCell(cellIndex);
            if (cell == null) {
                cell = row.createCell(cellIndex);
            }
            if (cellStyle != null) {
                cell.setCellStyle(cellStyle);
            }
            String cellValue = shiftList.get(i);
            if (StringUtils.isNotBlank(cellValue)) {
                cell.setCellValue(cellValue);
            }
 
            String annotationText = annotationTextMap.get(buildKey(dataIndex, i));
            if (StringUtils.isBlank(annotationText) || cell.getCellComment() != null) {
                continue;
            }
            if (drawingPatriarch == null) {
                drawingPatriarch = sheet.createDrawingPatriarch();
            }
            Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(
                    0, 0, 0, 0,
                    cellIndex, row.getRowNum(),
                    cellIndex + 2, row.getRowNum() + 3));
            comment.setString(new XSSFRichTextString(annotationText));
            comment.setAuthor("NS-LIMS");
            cell.setCellComment(comment);
        }
    }
 
    private String buildKey(int rowIndex, int cellIndex) {
        return rowIndex + "_" + cellIndex;
    }
}