java注解类-导入Excel文件到数据库中

实体类

java 复制代码
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@TableName("zhuzao_xiaohao_lingwai_daoru")
public class ZhuzaoLingWaiData implements Serializable {

    @Excel(name = "日期")
    private String date;
    @Excel(name = "批次号")
    private String batchno;
    @Excel(name = "第几周")
    private String weekday;
    @Excel(name = "生产线")
    private String productline;
    @Excel(name = "图号")
    private String produtname;
    @Excel(name = "物料编码")
    private String productdescription;
    @Excel(name = "产品名称")
    private String productweight;
    @Excel(name = "铸件毛重")
    private String box;
    @Excel(name = "件/箱")
    private String classes;
    @Excel(name = "班次")
    private String ronghualu;
    @Excel(name = "熔化(炉)")
    private String tieshuit;
    @Excel(name = "铁水(t)")
    private String zaoxing;
    @Excel(name = "造型\n" +
            "(箱)")
    private String jiaozhuxiang;
    @Excel(name = "浇注\n" +
            "(箱)")
    private String jiaozhujian;
    @Excel(name = "浇注\n" +
            "(件)")
    private String shizhi;
    @Excel(name = "试制")
    private String zhujiandongshu;
    @Excel(name = "铸件吨数")
    private String beizhu1;
    private String beizhu2;

}

注解类

java 复制代码
/**
 * 自定义导出Excel数据注解
 *
 * @author ruoyi
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
    /**
     * 导出时在excel中排序
     */
    public int sort() default Integer.MAX_VALUE;

    /**
     * 导出到Excel中的名字.
     */
    public String name() default "";

    /**
     * 日期格式, 如: yyyy-MM-dd
     */
    public String dateFormat() default "";

    /**
     * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
     */
    public String dictType() default "";

    /**
     * 读取内容转表达式 (如: 0=男,1=女,2=未知)
     */
    public String readConverterExp() default "";

    /**
     * 分隔符,读取字符串组内容
     */
    public String separator() default ",";

    /**
     * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
     */
    public int scale() default -1;

    /**
     * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
     */
    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;

    /**
     * 导出时在excel中每个列的高度
     */
    public double height() default 14;

    /**
     * 导出时在excel中每个列的宽度
     */
    public double width() default 16;

    /**
     * 文字后缀,如% 90 变成90%
     */
    public String suffix() default "";

    /**
     * 当值为空时,字段的默认值
     */
    public String defaultValue() default "";

    /**
     * 提示信息
     */
    public String prompt() default "";

    /**
     * 设置只能选择不能输入的列内容.
     */
    public String[] combo() default {};

    /**
     * 是否需要纵向合并单元格,应对需求:含有list集合单元格)
     */
    public boolean needMerge() default false;

    /**
     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
     */
    public boolean isExport() default true;

    /**
     * 另一个类中的属性名称,支持多级获取,以小数点隔开
     */
    public String targetAttr() default "";

    /**
     * 是否自动统计数据,在最后追加一行统计数据总和
     */
    public boolean isStatistics() default false;

    /**
     * 导出类型(0数字 1字符串 2图片)
     */
    public ColumnType cellType() default ColumnType.STRING;

    /**
     * 导出列头背景颜色
     */
    public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;

    /**
     * 导出列头字体颜色
     */
    public IndexedColors headerColor() default IndexedColors.WHITE;

    /**
     * 导出单元格背景颜色
     */
    public IndexedColors backgroundColor() default IndexedColors.WHITE;

    /**
     * 导出单元格字体颜色
     */
    public IndexedColors color() default IndexedColors.BLACK;

    /**
     * 导出字段对齐方式
     */
    public HorizontalAlignment align() default HorizontalAlignment.CENTER;

    /**
     * 自定义数据处理器
     */
    public Class<?> handler() default ExcelHandlerAdapter.class;

    /**
     * 自定义数据处理器参数
     */
    public String[] args() default {};

    /**
     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
     */
    Type type() default Type.ALL;

    public enum Type
    {
        ALL(0), EXPORT(1), IMPORT(2);
        private final int value;

        Type(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }

    public enum ColumnType
    {
        NUMERIC(0), STRING(1), IMAGE(2);
        private final int value;

        ColumnType(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }
}

控制类

java 复制代码
/**
 * 描述:
 *
 * @author 石加伟
 * @date 2024/3/18
 */
@RestController
@RequestMapping("/api/excel")
@Slf4j
public class ZhuzaoLingWaiDataController {
    @Autowired
    private ZhuzaoLingWaiDataService zhuzaoLingWaiDataService;

    @GetMapping("/importExceHTest")
//    public Result importExcel111(@RequestParam("file") MultipartFile file) {
    public String importExceHTest(String saveDirectory) throws IOException, IllegalAccessException {
//        String saveDirectory = "D:\\phoneAuto\\demo2-新副本\\铸造一厂24年3月17日报表 -  - (1).xlsx";
        Optional<ZhuzaoLingWaiData> maxDateItem = zhuzaoLingWaiDataService.list().stream()
                .filter(item -> item.getProductline().equals("灰铁线"))
                .max(Comparator.comparing(ZhuzaoLingWaiData::getDate));

        ZhuzaoLingWaiData dataWithMaxDate = maxDateItem.get() ;

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
        LocalDateTime date = LocalDateTime.parse(dataWithMaxDate.getDate(), formatter);

        System.out.println("最大日期的时间对象: " + date.toString());

//        for (ZhuzaoLingWaiData zhuzaoLingWaiData : list)
//            System.out.println(zhuzaoLingWaiData.toString());
        List<ZhuzaoLingWaiData> zhuzaoLingWaiData = getimportJobsFromExcel(saveDirectory)
                .stream().filter(item -> item.getProductline().equals("灰铁线"))
                .collect(Collectors.toList());
//       for (ZhuzaoLingWaiData zhuzaoLingWaiData1 : zhuzaoLingWaiData)
//           System.out.println("--------------------"+zhuzaoLingWaiData1.toString());
        // 假设ZhuzaoLingWaiData类已正确覆盖equals和hashCode方法
        // 找出存在于Excel数据中但不在服务数据中的项
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<ZhuzaoLingWaiData> notInService = zhuzaoLingWaiData.stream()
                .filter(excelItem -> LocalDateTime.parse(excelItem.getDate(), formatter1).isAfter(date))
                .collect(Collectors.toList());
        // 输出这些数据
        boolean b = zhuzaoLingWaiDataService.saveBatch(notInService);
        if (b) {
            System.out.println("导入成功");
            return "导入成功";
        } else {
            System.out.println("导入失败");
            return "导入失败";
        }
    }

    @GetMapping("/importExceQTest")
//    public Result importExcel111(@RequestParam("file") MultipartFile file) {
    public String importExceQTest(String saveDirectory) throws IOException, IllegalAccessException {
//       String saveDirectory = "D:\\phoneAuto\\demo2-新副本\\铸造一厂24年3月17日报表 -  - (1).xlsx";
        System.out.println(saveDirectory);
        Optional<ZhuzaoLingWaiData> maxDateItem = zhuzaoLingWaiDataService.list().stream()
                .filter(item -> item.getProductline().equals("球铁线"))
                .max(Comparator.comparing(ZhuzaoLingWaiData::getDate));
        ZhuzaoLingWaiData dataWithMaxDate = maxDateItem.get();

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
        LocalDateTime date = LocalDateTime.parse(dataWithMaxDate.getDate(), formatter);

        System.out.println("最大日期的时间对象: " + date.toString());

//        for (ZhuzaoLingWaiData zhuzaoLingWaiData : list)
//            System.out.println(zhuzaoLingWaiData.toString());
        List<ZhuzaoLingWaiData> zhuzaoLingWaiData = getimportJobsFromExcel(saveDirectory).stream()
                .filter(item -> item.getProductline().equals("球铁线"))
                .collect(Collectors.toList());

//       for (ZhuzaoLingWaiData zhuzaoLingWaiData1 : zhuzaoLingWaiData)
//           System.out.println("--------------------"+zhuzaoLingWaiData1.toString());
        // 假设ZhuzaoLingWaiData类已正确覆盖equals和hashCode方法
        // 找出存在于Excel数据中但不在服务数据中的项
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<ZhuzaoLingWaiData> notInService = zhuzaoLingWaiData.stream()
                .filter(excelItem -> LocalDateTime.parse(excelItem.getDate(), formatter1).isAfter(date))
                .collect(Collectors.toList());
        // 输出这些数据
        boolean b = zhuzaoLingWaiDataService.saveBatch(notInService);
        if (b) {
            System.out.println("导入成功");
            return "导入成功";
        } else {
            System.out.println("导入失败");
            return "导入失败";
        }
    }

    public List<ZhuzaoLingWaiData> getimportJobsFromExcel(String saveDirectory) throws IOException, IllegalAccessException {
//        String saveDirectory = "D:\\phoneAuto\\demo2-新副本\\铸造一厂24年3月17日报表 -  - (1).xlsx";
        File file = new File(saveDirectory);
        if (!file.exists() || !file.canRead()) {
            System.err.println("指定的文件无法读取。请确保文件路径正确且文件可读。");
            return null;
        }
        List<ZhuzaoLingWaiData> zhuzaoLingWaiData = null;
        try {
            //已经查询到数据
            //需要过滤已经有的数据
            //然后把最后数据进行导入
            zhuzaoLingWaiData = importJobsFromExcel(file);
        } catch (IOException | IllegalAccessException e) {
            // 增加了日志记录异常信息,给出了用户友好的错误提示
            e.printStackTrace();
            System.err.println("导入Excel时发生错误:" + e.getMessage());
        }
        return zhuzaoLingWaiData;

    }

    // 在实际导入逻辑中
    public static List<ZhuzaoLingWaiData> importJobsFromExcel(File file) throws IOException, IllegalAccessException {
        List<ZhuzaoLingWaiData> jobs = new ArrayList<>();
        try (InputStream excelFileInputStream = new FileInputStream(file)) {
            // 使用try-with-resources确保输入流被关闭
            Workbook workbook = null;
            try {
                workbook = WorkbookFactory.create(excelFileInputStream);
// 假设目标工作表的名称为 "Sheet2"
                List<Sheet> matchingSheets = new ArrayList<>();
                for (Sheet sheet : workbook) {
                    String sheetName = sheet.getSheetName();
                    if (sheetName.contains("铸造部")) {
                        matchingSheets.add(sheet);
                    }
                }
// 根据名称获取工作表
                Sheet sheet = workbook.getSheet(matchingSheets.get(0).getSheetName()); // 获取第一个工作表
                Map<String, Integer> columnHeaders = new HashMap<>(); // 初始化一个列名到索引的映射

                // 遍历第一行(通常是标题行)收集列名及其索引
                Row headerRow = sheet.getRow(1);
                for (Cell headerCell : headerRow) {
                    String columnName = headerCell.getStringCellValue().trim(); // 假设标题单元格内容是字符串
                    int columnIndex = headerCell.getColumnIndex();
                    //限制在左边10列
                    if (columnIndex < 20)
                        columnHeaders.put(columnName, columnIndex);
                }
                for (Row row : sheet) {
//                    System.out.println("第" + (row.getRowNum() + 1) + "行:" );
                    if (row.getRowNum() == 0) continue; // 跳过标题行
                    if (row.getRowNum() == 1) continue; // 跳过标题行

                    ZhuzaoLingWaiData job = new ZhuzaoLingWaiData();

                    // 根据注解获取字段名与Excel列名的映射关系
                    Field[] fields = ZhuzaoLingWaiData.class.getDeclaredFields();
                    for (Field field : fields) {
                        Excel annotation = field.getAnnotation(Excel.class);
                        if (annotation != null) {
                            String columnName = annotation.name();
                            // 使用之前收集的映射表查找列索引
                            Cell cell = row.getCell(columnHeaders.get(columnName));
                            // 将单元格内容转换为对应类型并赋值给实体类属性
                            if (cell != null) {
                                Object value = convertCellValue(cell, field.getType());
                                field.setAccessible(true);
                                field.set(job, value);
                            }
                        }
                    }

                    // 现在job对象已经被填充了从Excel读取的数据,可以将其保存到数据库
                    if (job.getDate() != null && job.getDate() != "")
                        jobs.add(job);

//            saveJobToDatabase(job);
                }
            } finally {
                if (workbook != null) {
                    workbook.close();
                }
            }
        } catch (IllegalArgumentException e) {
            // 特定异常的处理,比如Excel文件格式不正确
            System.err.println("无法识别的Excel文件格式。");
            e.printStackTrace();
        }
//        for(ZhuzaoLingWaiData job:jobs){
//            System.out.println(job);
//        }
        return jobs;
    }


    private static Object convertCellValue(Cell cell, Class<?> targetType) {
        // 获取单元格原始类型
        CellType cellType = cell.getCellType();

        switch (cellType) {
            case STRING:
                // 将所有非日期类型的值都转换为字符串
                return cell.getStringCellValue();

            case NUMERIC:
                // 检查是否为日期格式
                if (DateUtil.isCellDateFormatted(cell)) {
                    Date cellDate = cell.getDateCellValue();
                    // 使用SimpleDateFormat来格式化日期
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    return dateFormat.format(cellDate);
                } else {
                    // 处理纯数字情况,保留之前逻辑
                    return String.valueOf(cell.getNumericCellValue());
//                try {
//                    DecimalFormat formatter = new DecimalFormat("#.##");
//                    double numericValue = cell.getNumericCellValue();
//                    return formatter.format(numericValue);
//                } catch (IllegalStateException e) {
//                    e.printStackTrace();
//                    return "Error processing numeric cell";
//                }
                }


            case BOOLEAN:
                // 布尔类型转换为字符串
                return String.valueOf(cell.getBooleanCellValue());

            case FORMULA:
                switch (cell.getCachedFormulaResultType()) {
                    case NUMERIC:
                        return String.valueOf(cell.getNumericCellValue());
                    case BOOLEAN:
                        return String.valueOf(cell.getBooleanCellValue());
                    case STRING:
                        return cell.getStringCellValue();
                    case BLANK:
                        return cell.getCellFormula() + " (BLANK)";
                    case ERROR:
                        return cell.getCellFormula() + " (ERROR)";
                    default:
                        throw new IllegalArgumentException("Unexpected cell type after formula evaluation: " + cell.getCachedFormulaResultType());
                }
            case BLANK:
                // 空单元格返回空字符串
                return "";
            case ERROR:
                // 处理 #N/A 或其他错误类型,可以返回自定义错误信息或默认值
                return "";
            // CELL_TYPE_ERROR 等其他类型处理...

            default:
                throw new IllegalArgumentException(cellType.toString() + "不支持的单元格类型转换到" + targetType.getName());
        }

    }

其他类

java 复制代码
public interface ZhuzaoLingWaiDataService extends IService<ZhuzaoLingWaiData> {
}

@Service
public class ZhuzaoLingWaiDataServiceImpl extends ServiceImpl<ZhuzaoLingWaiDataMapper, ZhuzaoLingWaiData> implements ZhuzaoLingWaiDataService {

}

@Mapper
public interface ZhuzaoLingWaiDataMapper extends BaseMapper<ZhuzaoLingWaiData> {
}

总结

实现了从excel快捷的导入到文件中,文件有重复的列名,限制了列数

java 复制代码
 //限制在左边20列
                    if (columnIndex < 20)
                        columnHeaders.put(columnName, columnIndex);
相关推荐
xiaoyaolangwj2 分钟前
高翔【自动驾驶与机器人中的SLAM技术】学习笔记(十三)图优化SLAM的本质
学习·机器人·自动驾驶
巨大八爪鱼5 分钟前
XP系统下用mod_jk 1.2.40整合apache2.2.16和tomcat 6.0.29,让apache可以同时访问php和jsp页面
java·tomcat·apache·mod_jk
静止了所有花开1 小时前
SpringMVC学习笔记(二)
笔记·学习
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田2 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
L_cl3 小时前
Python学习从0到1 day26 第三阶段 Spark ④ 数据输出
学习
Mephisto.java3 小时前
【大数据学习 | HBASE】hbase的读数据流程与hbase读取数据
大数据·学习·hbase
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言