当前位置: 首页 > article >正文

将Excel文件的两个表格经过验证后分别读取到Excel表和数据库

 遍历读取数据,建两个表,负责人和业主表,业主表有外键,负责人表添加手机号正则验证负责人和业主的正确数据添加到数据库,错误的添加到Excel表负责人错误信息,业主错误信息


package excel;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ExcelDataProcessorDemo2 {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        try {
            // 读取并处理所有表的数据
            Map<String, List<Map<String, String>>> sheetDataMap = readAndProcessAllSheets("D:\\javaIO\\demo.xlsx");

            // 获取并打印所有表的数据
            processAndPrintSheetData(sheetDataMap);

            // 验证数据
            //有效负责人
            List<Map<String, String>> validResponsibleData = new ArrayList<>();
            //无效负责人
            List<Map<String, String>> invalidResponsibleData = new ArrayList<>();
            //有效业主
            List<Map<String, String>> validOwnerData = new ArrayList<>();
            //无效业主
            List<Map<String, String>> invalidOwnerData = new ArrayList<>();


            validateData(sheetDataMap.get("负责人"), validResponsibleData, invalidResponsibleData,validResponsibleData,true);

            //数据 有效 无效 如果这个地方有效负责人为空了,还需要进行业主信息判断么? 肯定四不需要啊 所以进行非空判断
            if (CollectionUtils.isNotEmpty(validResponsibleData)){
                validateData(sheetDataMap.get("业主信息"), validOwnerData, invalidOwnerData,validResponsibleData,false);

            } else {
                //负责人为空了 业主信息应该时全部为错误信息啊 找不到负责人
                ///。。。。。。。。。。。。。
                log.error("找不到负责人");
            }

            // 插入数据库
            insertIntoDatabase(validResponsibleData, validOwnerData);

            // 写入错误数据到新的Excel文件
            writeInvalidDataToExcel(invalidResponsibleData, invalidOwnerData);

            long endTime = System.currentTimeMillis();
            log.info("Total time taken: {} ms", (endTime - startTime));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取并处理所有表的数据
     *
     * @param filePath Excel文件路径
     * @return 包含所有表数据的Map
     */
    public static Map<String, List<Map<String, String>>> readAndProcessAllSheets(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath);
             Workbook workbook = new XSSFWorkbook(fis)) {

            Map<String, List<Map<String, String>>> sheetDataMap = new HashMap<>();
            //遍历所有表
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                //获取表对象
                Sheet sheet = workbook.getSheetAt(i);
                //获取表名
                String sheetName = sheet.getSheetName();
                //读取数据
                List<Map<String, String>> sheetData = readSheet(sheet);
                //将数据放入Map中
                sheetDataMap.put(sheetName, sheetData);
            }
            //最后返回map集合
            return sheetDataMap;
        } catch (IOException e) {
            log.error("Error reading sheets: {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 读取单个表的数据
     * @param sheet 表对象
     * @return 包含表数据的List
     */
    public static List<Map<String, String>> readSheet(Sheet sheet) {
        List<Map<String, String>> data = new ArrayList<>();
        // 获取表头行
        Row headerRow = sheet.getRow(0);
        if (headerRow == null) {
            throw new IllegalStateException("Header row is null");
        }
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row == null) {
                continue; // 跳过空行
            }
            Map<String, String> rowMap = new HashMap<>();
            // 增强for得到每一列的值
            for (Cell cell : row) {
                if (cell == null) {
                    continue; // 跳过空单元格
                }
                // 获取表头
                Cell headerCell = headerRow.getCell(cell.getColumnIndex());
                if (headerCell == null) {
                    continue; // 跳过不存在的表头
                }
                String columnName = headerCell.getStringCellValue();
                String cellValue = getCellValue(cell);
                rowMap.put(columnName, cellValue);
            }

            data.add(rowMap);
        }

        return data;
    }

    /**
     * 打印所有表的数据
     *
     * @param sheetDataMap 包含所有表数据的Map
     */
    public static void processAndPrintSheetData(Map<String, List<Map<String, String>>> sheetDataMap) {
        for (Map.Entry<String, List<Map<String, String>>> entry : sheetDataMap.entrySet()) {
            String sheetName = entry.getKey();
            List<Map<String, String>> sheetData = entry.getValue();
            log.info("{} 表大小: {}", sheetName, sheetData.size());
            sheetData.forEach(row -> log.info("Row: {}", row));
        }
    }

    /**
     * 获取单元格的值
     *
     * @param cell 单元格对象
     * @return 单元格的值
     */
    private static String getCellValue(Cell cell) {
        if (cell == null) {
            return ""; // 或者返回其他默认值
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf(cell.getNumericCellValue());
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }

    /**
     * 验证数据
     *
     * @param sheetData 表数据
     * @param validData 有效数据列表
     * @param invalidData 无效数据列表
     * @param validResponsibleData 有效负责人数据列表
     */
    private static void validateData(List<Map<String, String>> sheetData, List<Map<String, String>> validData,
                                     List<Map<String, String>> invalidData, List<Map<String, String>> validResponsibleData,
                                     boolean isResponsibleData) {
        // 遍历表数据,如果是有效数据,则添加到有效数据列表中,否则添加到无效数据列表中
        for (Map<String, String> row : sheetData) {
            if (isResponsibleData) {
                // 处理负责人数据
                if (isValidResponsiblePerson(row)) {
                    validData.add(row);
                } else {
                    invalidData.add(row);
                }
            } else {
                // 处理业主数据
                if (CollectionUtils.isEmpty(validResponsibleData)) {
                    // 如果没有有效负责人数据,直接判断为无效
                    invalidData.add(row);
                } else {
                    // 使用有效负责人信息集合和遍历中的业主信息进行判断
                    if (isValidOwner(validResponsibleData, row)) {
                        validData.add(row);
                    } else {
                        invalidData.add(row);
                    }
                }
            }
        }
    }

    /**
     * 验证负责人信息是否有效
     *
     * @param row 单行数据
     * @return 是否有效
     */
    private static boolean isValidResponsiblePerson(Map<String, String> row) {
        // 验证手机号
        String phoneNumber = row.get("联系方式");
        if (!isValidPhoneNumber(phoneNumber)) {
            return false;
        }

//        // 验证邮箱
//        String email = row.get("邮箱");
//        if (!isValidEmail(email)) {
//            return false;
//        }
//
//        // 验证时间
//        String time = row.get("时间");
//        if (!isValidTime(time)) {
//            return false;
//        }

        return true;
    }

    /**
     * 验证业主信息是否有效
     *
     * @param row 单行数据
     * @return 是否有效
     */
    private static boolean isValidOwner(  List<Map<String, String>> validResponsibleData,Map<String, String> row) {
        for (Map<String, String> firstSheetRow : validResponsibleData) {
            //比较当前行与第一张表的每一行,如果匹配,则将当前行的负责人信息添加到 row 中,并返回 true。
            if (firstSheetRow.get("项目").equals(row.get("项目")) &&
                    firstSheetRow.get("楼栋").equals(row.get("楼栋")) &&
                    firstSheetRow.get("单元").equals(row.get("单元"))) {
                row.put("负责人", firstSheetRow.get("负责人"));
                return true;
            }
        }
        return false;
    }

    /**
     * 验证手机号是否有效
     *
     * @param phoneNumber 手机号
     * @return 是否有效
     */
    private static boolean isValidPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.isEmpty()) {
            return false;
        }
        //以1开头,第二位为3-9,后面是9位数
        String phoneRegex = "^1[3-9]\\d{9}$";
        // 使用正则表达式验证
        return phoneNumber.matches(phoneRegex);
    }

    /**
     * 验证邮箱是否有效
     *
     * @param email 邮箱
     * @return 是否有效
     */
    private static boolean isValidEmail(String email) {
        if (email == null || email.isEmpty()) {
            return false;
        }
        //[A-Za-z0-9+_.-]+ 匹配一个或多个字母、数字、加号、点号、下划线或减号。
        // @ 匹配一个字符,后面是域名,域名可以是多个字母、数字、点号或减号。
        String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
        return email.matches(emailRegex);
    }

    /**
     * 验证时间格式是否有效
     *
     * @param time 时间
     * @return 是否有效
     */
    private static boolean isValidTime(String time) {
        if (time == null || time.isEmpty()) {
            return false;
        }
        // yyyy-MM-dd HH:mm:ss
        String timeRegex = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$";
        return time.matches(timeRegex);
    }


    /**
     * 将有效数据插入数据库
     * @param validResponsibleData 有效的负责人数据
     * @param validOwnerData 有效的业主数据
     */
    private static void insertIntoDatabase(List<Map<String, String>> validResponsibleData, List<Map<String, String>> validOwnerData) {
        String url = "jdbc:mysql://localhost:3306/excel?serverTimezone=UTC";
        String user = "root";
        String password = "root";
        // 加载驱动
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            insertResponsibleData(conn, validResponsibleData);
            insertOwnerData(conn,validOwnerData);
        } catch (SQLException e) {
            log.error("Error inserting data into database: {}", e.getMessage());
        }
    }

    /**
     * 插入负责人数据到数据库
     *
     * @param conn 数据库连接
     * @param validResponsibleData 有效的负责人数据
     * @throws SQLException SQL异常
     */
    private static void insertResponsibleData(Connection conn, List<Map<String, String>> validResponsibleData) throws SQLException {
        String sql = "INSERT INTO responsible (responsible_name, phone, email, create_time) VALUES (?, ?, ?, ?)";
        // 使用 PreparedStatement 执行批量插入
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            for (Map<String, String> row : validResponsibleData) {
                pstmt.setString(1, row.get("负责人"));
                pstmt.setString(2, row.get("联系方式"));
                pstmt.setString(3, row.get("邮箱"));
                pstmt.setString(4, row.get("时间"));
                //将当前设置的参数添加到批处理命令中,添加到批处理队列中,以便后续一次性执行所有批处理命令。
                pstmt.addBatch();
            }
            pstmt.executeBatch();
        }
    }

    /**
     * 插入业主数据到数据库
     *
     * @param conn 数据库连接
     * @param validOwnerData 有效的业主数据
     * @throws SQLException SQL异常
     */
    private static void insertOwnerData(Connection conn, List<Map<String, String>> validOwnerData) throws SQLException {
        String sql = "INSERT INTO owner (owner_name,project, building, unit,floor,room_number,owner_id,responsible_id) VALUES (?, ?, ?, ?,?,?,?,?)";
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            for (Map<String, String> row : validOwnerData) {
                pstmt.setString(1, row.get("业主姓名"));
                pstmt.setString(2, row.get("项目"));
                pstmt.setString(3, row.get("楼栋"));
                pstmt.setString(4, row.get("单元"));
                pstmt.setString(5, row.get("楼层"));
                pstmt.setString(6, row.get("房号"));
                pstmt.setString(7,row.get("编号"));
                // 获取或插入负责人的 ID 那个地方加过之后 这个就有值了
                int responsibleId = getOrCreateResponsibleId(conn, row.get("负责人"));
                //如果这个地方返回值为0了,代表你业主验证的时候没有验证对

                pstmt.setInt(8, responsibleId);
                pstmt.addBatch();
            }
            pstmt.executeBatch();
        }
    }
    private static int getOrCreateResponsibleId(Connection conn, String responsibleName) throws SQLException {
        //那个地方有值 这个地方就一定会有值 不会返回0
        String selectSql = "SELECT responsible_id FROM responsible WHERE responsible_name = ?";
        try (PreparedStatement selectStmt = conn.prepareStatement(selectSql)) {
            selectStmt.setString(1, responsibleName);
            try (ResultSet rs = selectStmt.executeQuery()) {
                if (rs.next()) {
                    return rs.getInt("responsible_id");
                }
            }
        }
        return 0;
    }
    /**
     * 将无效数据写入新的Excel文件
     *
     * @param invalidResponsibleData 无效的负责人数据
     * @param invalidOwnerData 无效的业主数据
     */
    private static void writeInvalidDataToExcel(List<Map<String, String>> invalidResponsibleData, List<Map<String, String>> invalidOwnerData) {
        try (Workbook workbook = new XSSFWorkbook()) {
            // 创建负责人表
            Sheet responsibleSheet = workbook.createSheet("无效负责人数据");
            createSheetWithHeader(responsibleSheet, invalidResponsibleData);

            // 创建业主表
            Sheet ownerSheet = workbook.createSheet("无效业主数据");
            createSheetWithHeader(ownerSheet, invalidOwnerData);

            try (FileOutputStream fos = new FileOutputStream("D:\\javaIO\\invalidData.xlsx")) {
                workbook.write(fos);
            } catch (IOException e) {
                e.printStackTrace();
                System.err.println("写入文件时发生错误: " + e.getMessage());
            }
        } catch (IOException e) {
            log.error("Error writing results to Excel: {}", e.getMessage());
        }
    }

    /**
     * 创建带有表头的表
     *
     * @param sheet 表对象
     * @param data 表数据
     */
    private static void createSheetWithHeader(Sheet sheet, List<Map<String, String>> data) {
        if (data.isEmpty()) {
            return;
        }

        Row headerRow = sheet.createRow(0);
        int columnIndex = 0;
        for (String key : data.get(0).keySet()) {
            headerRow.createCell(columnIndex++).setCellValue(key);
        }

        int rowIndex = 1;
        for (Map<String, String> row : data) {
            Row dataRow = sheet.createRow(rowIndex++);
            columnIndex = 0;
            for (String key : row.keySet()) {
                dataRow.createCell(columnIndex++).setCellValue(row.get(key));
            }
        }
    }
}


http://www.kler.cn/a/396787.html

相关文章:

  • 金融领域先锋!海云安成功入选2024年人工智能先锋案例集
  • Java中的集合类与线程安全的讨论
  • 自由学习记录(22)
  • Python习题 251:修改文件名称
  • 深度学习的多主机多GPU协同训练
  • Vue3 -- 项目配置之stylelint【企业级项目配置保姆级教程3】
  • HTML之图片和超链接的学习记录
  • 124. 二叉树中的最大路径和【 力扣(LeetCode) 】
  • go debug日记:protoc -I . helloworld.proto --go_out=plugins=grpc:.错误debug
  • 【个人笔记】如何将 Linux 文件系统扩容
  • C++__day1
  • redis7.x源码分析:(2) adlist双向链表
  • 高防服务器的费用受到哪些原因影响?
  • Java重点--多线程
  • 241114.学习日志——[CSDIY] [CS]数据结构与算法 [00]
  • C++基础 抽象类 类模板 STL库 QT环境
  • OPEN - Linux手册页
  • apipost下载安装教程、脚本详细使用教程
  • 微积分第五版课后习题答案详解PDF电子版 赵树嫄
  • leetCode——二进制手表
  • 【数据结构 | C++】字符串关键字的散列映射
  • 算法——长度最小的子数组(leetcode209)
  • 新版Apache Tomcat ⽬目录文件讲解(笔记)
  • git 常用命令大全
  • datawhale11月组队学习 模型压缩技术3:2:4结构稀疏化BERT模型
  • 【时间之外】IT人求职和创业应知【34】-人和机器人,机器人更可靠