zhou zhou
16 小时以前 44ac1c9a2a6ee6ac9f618f4a63510f8f94d1b1a9
rsf-server/src/main/java/com/vincent/rsf/server/common/utils/ExcelUtil.java
@@ -2,40 +2,38 @@
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHandlerResult;
import cn.afterturn.easypoi.handler.inter.IExcelDataHandler;
import com.google.common.collect.Lists;
import com.vincent.rsf.common.domain.BeanValidators;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.server.common.handler.AggregationDataHandler;
import com.vincent.rsf.server.common.handler.ExcelDictHandlerImpl;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.manager.entity.excel.MatnrsTemplate;
import com.vincent.rsf.server.manager.entity.excel.annotation.ExcelComment;
import com.vincent.rsf.server.system.entity.Fields;
import com.vincent.rsf.server.system.service.FieldsService;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import org.apache.poi.ss.util.CellRangeAddress;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Created by vincent on 2/17/2024
 */
@Slf4j
public class ExcelUtil {
    private static final Pattern EXTEND_FIELD_SOURCE_PATTERN = Pattern.compile("^extendFields\\.\\[(.+)]$");
    public static void build(Workbook workbook, HttpServletResponse response) {
        response.reset();
        Http.cors(response);
@@ -43,20 +41,27 @@
        try {
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("export", "UTF-8"));
            workbook.write(response.getOutputStream());
        } catch (IOException ignore) {}
        } catch (IOException ignore) {
        }
    }
    public static <T> Workbook create(List<T> list, Class<T> clz) {
        return  create(list, clz, false);
        return create(list, clz, false);
    }
    public static <T> Workbook create(List<T> list, Class<T> clz, boolean flagTemplate) {
        HSSFWorkbook workbook = new HSSFWorkbook();
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(clz.getSimpleName());
        Row header = sheet.createRow(0);
        Field[] fields = Cools.getAllFields(clz);
        int headerIdx = 0;
        FieldsService itemService = SpringUtils.getBean(FieldsService.class);
        List<Fields> sysFields = itemService.list(new LambdaQueryWrapper<Fields>()
                .eq(Fields::getStatus, 1)
                .eq(Fields::getFlagEnable, 1));
        for (Field field : fields) {
            if (Modifier.isFinal(field.getModifiers())
                    || Modifier.isStatic(field.getModifiers())
@@ -65,9 +70,7 @@
            }
            String memo = "Undefined";
            if (flagTemplate) {
                if (field.isAnnotationPresent(ExcelComment.class)) {
                    memo = field.getAnnotation(ExcelComment.class).value();
                }
                memo = field.getName();
            } else {
                if (field.isAnnotationPresent(Excel.class)) {
                    memo = field.getAnnotation(Excel.class).name();
@@ -79,39 +82,46 @@
            header.createCell(headerIdx).setCellValue(memo);
            headerIdx++;
        }
        int rowIndex = 1;
        for (T t : list) {
            Row row = sheet.createRow(rowIndex++);
            int cellIndex = 0;
            for (Field field : fields) {
                if (Modifier.isFinal(field.getModifiers())
                        || Modifier.isStatic(field.getModifiers())
                        || Modifier.isTransient(field.getModifiers())) {
                    continue;
                }
                // 此行很重要,特别是字段为private时
                field.setAccessible(true);
                Object value = null;
                try {
                    value = field.get(t);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                if (value != null) {
                    if (value instanceof Date) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        row.createCell(cellIndex).setCellValue(sdf.format((Date) value));
        if (clz.equals(MatnrsTemplate.class)) {
            //添加扩展字段别名
            if (!sysFields.isEmpty()) {
                for (Fields field : sysFields) {
                    if (flagTemplate) {
                        header.createCell(headerIdx).setCellValue(field.getFields());
                    } else {
                        row.createCell(cellIndex).setCellValue(value.toString());
                        header.createCell(headerIdx).setCellValue(field.getFieldsAlise());
                    }
                    headerIdx++;
                }
                cellIndex++;
            }
        }
        int rowIndex = 1;
        if (!Objects.isNull(list)) {
            for (T t : list) {
                Row row = sheet.createRow(rowIndex++);
                int cellIndex = 0;
                for (Field field : fields) {
                    if (Modifier.isFinal(field.getModifiers())
                            || Modifier.isStatic(field.getModifiers())
                            || Modifier.isTransient(field.getModifiers())) {
                        continue;
                    }
                    // 此行很重要,特别是字段为private时
                    field.setAccessible(true);
                    Object value = null;
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    writeCellValue(row, cellIndex, value);
                    cellIndex++;
                }
            }
        }
        for (int i = 0; i <= fields.length; i++) {
            sheet.autoSizeColumn(i);
        }
@@ -119,14 +129,218 @@
        return workbook;
    }
    public static Workbook create(List<Map<String, Object>> rows, List<ExportColumn> columns) {
        return create(rows, columns, null);
    }
    public static Workbook create(List<Map<String, Object>> rows, List<ExportColumn> columns, ExportMeta exportMeta) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("export");
        int titleColumnCount = Math.max(columns.size(), 4);
        int currentRowIndex = 0;
        CellStyle titleStyle = createTitleStyle(workbook);
        CellStyle subHeaderStyle = createSubHeaderStyle(workbook);
        CellStyle headerStyle = createHeaderStyle(workbook);
        CellStyle bodyStyle = createBodyStyle(workbook);
        if (exportMeta != null && StringUtils.isNotBlank(exportMeta.getReportTitle())) {
            Row titleRow = sheet.createRow(currentRowIndex++);
            titleRow.setHeightInPoints(24);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellValue(exportMeta.getReportTitle());
            titleCell.setCellStyle(titleStyle);
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, titleColumnCount - 1));
            Row subHeaderRow = sheet.createRow(currentRowIndex++);
            writeSubHeaderCell(subHeaderRow, 0, getSubHeaderText("报表日期", exportMeta.getReportDate()), subHeaderStyle);
            writeSubHeaderCell(subHeaderRow, 1, getSubHeaderText("打印人", exportMeta.getOperator()), subHeaderStyle);
            writeSubHeaderCell(subHeaderRow, 2, getSubHeaderText("打印时间", exportMeta.getPrintedAt()), subHeaderStyle);
            writeSubHeaderCell(subHeaderRow, 3, getSubHeaderText("记录数", String.valueOf(exportMeta.getCount())), subHeaderStyle);
            currentRowIndex++;
        }
        Row header = sheet.createRow(currentRowIndex++);
        for (int index = 0; index < columns.size(); index++) {
            Cell headerCell = header.createCell(index);
            headerCell.setCellValue(columns.get(index).getLabel());
            headerCell.setCellStyle(headerStyle);
        }
        int rowIndex = currentRowIndex;
        for (Map<String, Object> rowData : rows) {
            Row row = sheet.createRow(rowIndex++);
            for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                Object value = getRowValue(rowData, columns.get(columnIndex).getSource());
                writeCellValue(row, columnIndex, value, bodyStyle);
            }
        }
        for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
            sheet.autoSizeColumn(columnIndex);
        }
        return workbook;
    }
    private static Object getRowValue(Map<String, Object> rowData, String source) {
        if (rowData == null || StringUtils.isBlank(source)) {
            return null;
        }
        if (rowData.containsKey(source)) {
            return rowData.get(source);
        }
        Matcher matcher = EXTEND_FIELD_SOURCE_PATTERN.matcher(source);
        if (matcher.matches()) {
            Object extendFields = rowData.get("extendFields");
            if (extendFields instanceof Map<?, ?> extendFieldMap) {
                return extendFieldMap.get(matcher.group(1));
            }
        }
        return rowData.get(source);
    }
    private static void writeCellValue(Row row, int cellIndex, Object value) {
        writeCellValue(row, cellIndex, value, null);
    }
    private static void writeCellValue(Row row, int cellIndex, Object value, CellStyle cellStyle) {
        Cell cell = row.createCell(cellIndex);
        if (cellStyle != null) {
            cell.setCellStyle(cellStyle);
        }
        if (value == null) {
            return;
        }
        if (value instanceof Date) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            cell.setCellValue(sdf.format((Date) value));
            return;
        }
        cell.setCellValue(value.toString());
    }
    private static void writeSubHeaderCell(Row row, int cellIndex, String value, CellStyle cellStyle) {
        Cell cell = row.createCell(cellIndex);
        cell.setCellValue(value);
        cell.setCellStyle(cellStyle);
    }
    private static String getSubHeaderText(String label, String value) {
        return label + ": " + StringUtils.defaultString(value);
    }
    private static CellStyle createTitleStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 14);
        cellStyle.setFont(font);
        return cellStyle;
    }
    private static CellStyle createSubHeaderStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.LEFT);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 10);
        cellStyle.setFont(font);
        return cellStyle;
    }
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 10);
        cellStyle.setFont(font);
        return cellStyle;
    }
    private static CellStyle createBodyStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.LEFT);
        cellStyle.setVerticalAlignment(VerticalAlignment.TOP);
        cellStyle.setWrapText(true);
        return cellStyle;
    }
    public static class ExportColumn {
        private final String source;
        private final String label;
        public ExportColumn(String source, String label) {
            this.source = source;
            this.label = label;
        }
        public String getSource() {
            return source;
        }
        public String getLabel() {
            return label;
        }
    }
    public static class ExportMeta {
        private final String reportTitle;
        private final String reportDate;
        private final String printedAt;
        private final String operator;
        private final int count;
        public ExportMeta(String reportTitle, String reportDate, String printedAt, String operator, int count) {
            this.reportTitle = reportTitle;
            this.reportDate = reportDate;
            this.printedAt = printedAt;
            this.operator = operator;
            this.count = count;
        }
        public String getReportTitle() {
            return reportTitle;
        }
        public String getReportDate() {
            return reportDate;
        }
        public String getPrintedAt() {
            return printedAt;
        }
        public String getOperator() {
            return operator;
        }
        public int getCount() {
            return count;
        }
    }
    /**
     * 添加导入excel配置参数
     * 注:默认配置可满足当前需求
     *
     * @return
     */
    public static ImportParams getDefaultImportParams() {
        ImportParams importParams = new ImportParams();
        importParams.setTitleRows(0);
//        importParams.setNeedVerify(true);
        importParams.setHeadRows(1);
        importParams.setSheetNum(1);
        return importParams;
@@ -134,6 +348,7 @@
    /**
     * 根据 {@code tClass} 相关成员变量的 {@link ExcelComment#example()} 字段创建模拟数据,暂不支持 复杂类型
     *
     * @param tClass
     * @return
     */
@@ -210,3 +425,4 @@
}