1038 2023-05-30 2023-05-30

前言:日常工作中,经常会遇到excel文件内容需要转成sql的数据形式,虽然之前写过一个小工具,但一直以来没有抽时间好好优化代码,基本上是能用就行。这次特地抽出一点时间,对之前的代码做下重构,这里也分享给大家。

一、pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.9-rc</version>
        </dependency>

        <dependency>
            <groupId>com.ibeetl</groupId>
            <artifactId>beetlsql</artifactId>
            <version>2.13.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.71</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.7</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
</project>

二、源代码

package zj;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Date;

/**
 * 可以通过本工具,快速将excel转换为相应的插入sql(csv也大同小异)
 * 1.带密码的excel result_20230529_151402.xlsx/dpvixyp5  测试通过
 * 2.无密码的excel result_20230228_113125.xlsx 测试通过
 * 3.isMysqlOrHive true/false 测试通过
 * @author hk
 * @date 2023-05-30 21:00
 */
public class GenerateSqlByExcel {

    /** 是否开启debug模式 */
    private static boolean isDebug = false;

    /** true-匹配mysql或hive,false-匹配phoenix */
    private static boolean isMysqlOrHive = false;

    /** 批量插入条数 */
    private static int batchInsertCount = 100;

    /** excel 根目录 */
    private static String rootDir = "/Users/huangkui/local_git/demo";

    /** 默认sql命名为 日期+excel文件名.sql */
    private static String sqlDir = "/Users/huangkui/local_git/demo/sql";

    /** excel文件路径 */
    private static String[] files = new String[] {
            rootDir + "/result_20230529_151402.xlsx"
    };

    /** excel密码,如果有的话 */
    private static String[] pwds = new String[] {
            "dpvixyp5"
    };

    /** 需要写入的表 */
    private static String[] tables = new String[] {
            "hk.t_test"
    };

    private static String[] sqlFile = new String[files.length];


    public static void main(String[] args) throws Exception {
        FileUtil.mkdir(new File(sqlDir));
        for (int i = 0; i < files.length ; i++) {
            // yyyy-MM-dd HH:mm:ss
            String suffix = DateUtil.format(new Date(), "MM-dd HH:mm:SS");
            String path = files[i].substring(rootDir.length())
                    .replace(".", "&" +suffix +".")
                    .replace(".xlsx", ".sql")
                    .replace(".xls", ".sql");
            sqlFile[i] = sqlDir + path;
            dealExcel(i);
            System.out.println("处理文件索引" + i + "成功");
        }
    }

    private static void dealExcel(int fileIndex) throws Exception {
        File file = new File(files[fileIndex]);
        System.out.println("文件索引" + fileIndex + ": 是否存在=" + file.exists() + " 绝对路径=" + file.getAbsolutePath());
        System.out.println("sqlFile:" + sqlFile[fileIndex]);
        // 输出至sql文件
        FileWriter fw = new FileWriter(sqlFile[fileIndex], false);
        Workbook workbook;
        if (pwds.length != 0 && pwds.length - 1 >= fileIndex) {
            // 需要解密
            POIFSFileSystem pfs = new POIFSFileSystem(new File(files[fileIndex]));
            EncryptionInfo encInfo = new EncryptionInfo(pfs);
            Decryptor decryptor = Decryptor.getInstance(encInfo);
            decryptor.verifyPassword(pwds[fileIndex]);
            workbook = new XSSFWorkbook(decryptor.getDataStream(pfs));
        } else {
            workbook = new XSSFWorkbook(files[fileIndex]);
        }
        Sheet sheet = workbook.getSheetAt(0);
        // 第一行 获取表头
        Row firstRow = sheet.getRow(0);
        int rowNos = sheet.getLastRowNum();
        int columnNum = firstRow.getLastCellNum();
        StringBuilder fixedStr;
        if (isMysqlOrHive) {
            fixedStr = new StringBuilder("insert into " + tables[fileIndex] + "(");
        } else {
            fixedStr = new StringBuilder("upsert into " + tables[fileIndex] + "(");
        }
        for (int j = 0; j < columnNum; j++) {
            Cell cell = firstRow.getCell(j);
            if (cell != null) {
                if (isMysqlOrHive) {
                    if (j != columnNum - 1) {
                        fixedStr.append("`").append(cell.getStringCellValue()).append("`").append(",");
                    } else {
                        fixedStr.append("`").append(cell.getStringCellValue()).append("`");
                    }
                } else {
                    if (j != columnNum - 1) {
                        fixedStr.append(cell.getStringCellValue()).append(",");
                    } else {
                        fixedStr.append(cell.getStringCellValue());
                    }
                }
            }
        }
        fixedStr.append(") values");
        writeFile(fixedStr, fw);

        for (int i = 1; i <= rowNos; i++) {
            StringBuilder str = new StringBuilder("    (");
            for (int j = 0; j < columnNum; j++) {
                Cell cell = sheet.getRow(i).getCell(j);
                if (isDebug) {
                    printCellInfo(cell, firstRow);
                }
                if (cell != null) {
                    if (j != columnNum - 1) {
                        if (cell.getCellType().equals(CellType.NUMERIC)) {
                            if (!needFormat(cell.getNumericCellValue())) {
                                str.append(cell.getNumericCellValue()).append(",");
                            } else {
                                str.append(formatBigNumber(cell.getNumericCellValue())).append(",");
                            }
                        } else {
                            str.append("'").append(cell.getStringCellValue()).append("',");
                        }
                    } else {
                        if (cell.getCellType().equals(CellType.NUMERIC)) {
                            if (!needFormat(cell.getNumericCellValue())) {
                                str.append(cell.getNumericCellValue());
                            } else {
                                str.append(formatBigNumber(cell.getNumericCellValue()));
                            }
                        } else {
                            str.append("'").append(cell.getStringCellValue()).append("'");
                        }
                    }
                }
            }
            // 这里可对每一行生成的sql做具体处理
            String exactStr = str.toString();
            if (i % batchInsertCount == 0 || i == rowNos) {
                writeFile(exactStr + ");\n", fw);
                if (i != rowNos) {
                    writeFile(fixedStr, fw);
                }
            } else {
                writeFile(exactStr + "),", fw);
            }
        }
        fw.flush();
        fw.close();
    }


    private static boolean needFormat(double number) {
        return number > 1501738894 || number < -1501738894;
    }

    private static String formatBigNumber(double bigNumber) {
        // 数字超过15亿,一般为日期类型
        if (bigNumber > 1501738894 || bigNumber < -1501738894) {
            DecimalFormat df = new DecimalFormat("0");
            String s = df.format(bigNumber);
            return s.substring(0, s.length() - 1);
        }
        return "'" + bigNumber + "'";
    }

    private static void writeFile(CharSequence str, FileWriter fw) throws IOException {
        if (isDebug) {
            System.out.print(str);
        }
        fw.append(str);
    }

    private static void printCellInfo(Cell cell, Row firstRow) {
        System.out.println(cell.getRowIndex() + "行" + cell.getColumnIndex() + "列 key=" + firstRow.getCell(cell.getColumnIndex()) + ",value=" + cell + ",type=" + cell.getCellType());
    }
}
总访问次数: 51次, 一般般帅 创建于 2023-05-30, 最后更新于 2023-05-30

进大厂! 欢迎关注微信公众号,第一时间掌握最新动态!