package UnitTest.ImportExcel; import UnitTest.ImportExcel.Bean.CellBean; import com.dsideal.QingLong.Util.ChineseCharacterUtil; import com.jfinal.kit.Kv; import com.jfinal.kit.PropKit; import com.jfinal.kit.StrKit; import com.jfinal.plugin.activerecord.ActiveRecordPlugin; import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory; import com.jfinal.plugin.activerecord.Db; import com.jfinal.plugin.activerecord.Record; import com.jfinal.plugin.activerecord.dialect.PostgreSqlDialect; import com.jfinal.plugin.hikaricp.HikariCpPlugin; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.usermodel.*; import org.apache.poi.util.LocaleUtil; import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; public class createTable { /** * 功能:移除小括号,以及小括号内的文字内容 * * @param input * @return */ public static String removeKuoHao(String input) { String output = input.replaceAll("\\(.*?\\)", ""); output = output.replaceAll("\\(.*?\\)", ""); return output; } /** * 功能:移除字符串中的数字 * * @param input * @return */ public static String removeNumbers(String input) { String regex = "\\d+"; // 匹配数字的正则表达式 String result = input.replaceAll(regex, ""); // 使用replaceAll方法将匹配到的数字替换为空字符串 return result; } /** * ) * 获取单元格vo * * @param cell 单元格 * @return */ private static CellBean getCellBean(Cell cell) { CellBean dto = new CellBean();//创建单元格对象 if (cell != null) { //值 switch (cell.getCellType()) { case NUMERIC://导入数据,没有支持到时间的,一般都是到日期为止 if (DateUtil.isCellDateFormatted(cell)) { DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", LocaleUtil.getUserLocale()); sdf.setTimeZone(LocaleUtil.getUserTimeZone()); dto.setValue(sdf.format(cell.getDateCellValue())); dto.setType("date"); } else { String type; Long longVal = Math.round(cell.getNumericCellValue()); Double doubleVal = cell.getNumericCellValue(); if (Double.parseDouble(longVal + ".0") == doubleVal) { //判断是否含有小数位.0 type = "int"; } else { type = "float8"; } DataFormatter formatter = new DataFormatter(); dto.setValue(formatter.formatCellValue(cell)); dto.setType(type); } break; case STRING: dto.setValue(cell.getStringCellValue()); dto.setType("varchar(1024)"); break; case BOOLEAN: dto.setValue(String.valueOf(cell.getBooleanCellValue())); dto.setType("bool"); break; case FORMULA: dto.setValue(cell.getCellFormula()); dto.setType("varchar(1024)"); break; case BLANK: dto.setValue(""); dto.setType("varchar(1024)"); break; case ERROR: dto.setValue(ErrorEval.getText(cell.getErrorCellValue())); dto.setType("varchar(1024)"); break; default: { dto.setValue("Unknown Cell Type: " + cell.getCellType()); dto.setType("varchar(1024)"); } } // xlsx 07版 //背景颜色 CellStyle cellStyle = cell.getCellStyle(); XSSFColor xssfColor = (XSSFColor) cellStyle.getFillForegroundColorColor(); byte[] bytes; if (xssfColor != null) { bytes = xssfColor.getRGB(); dto.setBackgroundColor(String.format("#%02X%02X%02X", bytes[0], bytes[1], bytes[2])); } } return dto; } /** * 功能:查找指定Sheet中的表头开始位置与结束位置,目前只支持一个Sheet一个导入模板,并且,只支持单行或双行表头 * * @param sheet * @return */ public static List getHead(XSSFSheet sheet) { List _list = new ArrayList<>(); //整行都是同一种颜色的,视为表头 // 遍历行 for (int i = 0; i <= sheet.getLastRowNum(); i++) { //获得行 Row row = sheet.getRow(i); //遍历列 if (row != null) { Map _map = new HashMap<>(); for (int j = 0; j < row.getLastCellNum(); j++) { //获取单元格 Cell cell = row.getCell(j); if (cell == null) continue; CellBean eo = getCellBean(cell); if (_map.containsKey(eo.getBackgroundColor())) _map.put(eo.getBackgroundColor(), _map.get(eo.getBackgroundColor()) + 1); else _map.put(eo.getBackgroundColor(), 1); } if (_map.size() == 1 && _map.entrySet().iterator().next().getKey().startsWith("#")) { _list.add(i + 1); } } } return _list; } /** * 功能:根据样例数据,获取生成物理表的字段类型 * * @param sheet * @param st * @param ed * @return */ public static List> getStruct(XSSFSheet sheet, int st, int ed) { List> list = new ArrayList<>(); // 遍历行 for (int i = st; i <= ed; i++) { //获得行 Row row = sheet.getRow(i); List r = new ArrayList<>(); //遍历列 if (row != null) { for (int j = 0; j < row.getLastCellNum(); j++) { Cell cell = row.getCell(j); if (cell == null) continue; CellBean eo = getCellBean(cell); r.add(eo.getType()); } } list.add(r); } return list; } /** * 功能:判断表是不是存在 * * @param tableName * @return */ public static boolean isTableExist(String tableName) { String sql = "select count(*) as c from pg_class where relname = ?"; return Db.findFirst(sql, tableName).getInt("c") == 1; } /** * 功能:检查两个EXCEL文件的指定行+指定列是不是内容一致,返回值是不一致的位置集合,位置用数对 Map.Entry描述 * * @param f1 模板文件 * @param f2 上传文件 * @param startRow 开始行 * @param endRow 结束行 * @param startCol 开始列 * @param endCol 结束列 * @return 不一样的位置集合 * @throws IOException */ public static List> checkYiZhi(String f1, String f2, int startRow, int endRow, int startCol, int endCol) throws IOException { FileInputStream file1 = new FileInputStream(f1); FileInputStream file2 = new FileInputStream(f2); List> errList = new ArrayList<>(); Workbook wb1 = WorkbookFactory.create(file1); Workbook wb2 = WorkbookFactory.create(file2); Sheet sheet1 = wb1.getSheetAt(0); Sheet sheet2 = wb2.getSheetAt(0); for (int i = startRow; i <= endRow; i++) { Row row1 = sheet1.getRow(i); Row row2 = sheet2.getRow(i); for (int j = startCol; j <= endCol; j++) { Cell cell1 = row1.getCell(j); Cell cell2 = row2.getCell(j); if (cell1 != null && cell2 != null) { if (!cell1.getStringCellValue().equals(cell2.getStringCellValue())) { Map.Entry pair = new AbstractMap.SimpleEntry<>((i + 1), (j + 1)); errList.add(pair); } } } } file1.close(); file2.close(); return errList; } /** * 功能:创建表 * * @param tableName 表名 * @param filePath excel文件位置 * @throws IOException */ public static Kv createTable(String tableName, String filePath) throws IOException { Kv kv = Kv.create(); if (isTableExist(tableName)) { kv.set("success", false); kv.set("message", "表名:" + tableName + "已存在,不能创建,请手动更换!"); return kv; } String colSql = "", commentSql = ""; InputStream is = new FileInputStream(filePath); XSSFWorkbook wb = new XSSFWorkbook(is); //读取sheet页 XSSFSheet sheet = wb.getSheetAt(0); //找到表头 List _list = getHead(sheet); //遍历每一列,获取列信息,数据类型 List> a = getStruct(sheet, _list.get(_list.size() - 1) + 1, sheet.getLastRowNum() + 1); List b = a.get(0); // 输出表头的文字 Row ed = sheet.getRow(_list.get(_list.size() - 1) - 1);//下标从0开始 Row st = sheet.getRow(_list.get(0) - 1);//下标从0开始 //非空列有哪些 Set notNullSet = new HashSet<>(); // 首行数据 Row dataFirstRow = sheet.getRow(_list.get(_list.size() - 1)); for (int i = 0; i < dataFirstRow.getLastCellNum(); i++) { Cell cell = dataFirstRow.getCell(i); CellBean eo = getCellBean(cell); if (eo.getBackgroundColor().equals("#FF0000")) { notNullSet.add(i + 1); } } //需要记录此模板编号的第几列对应哪个字段,方便以后的数据写入 Record _map[] = new Record[ed.getLastCellNum()]; String column_name, memo; for (int colNum = 0; colNum < ed.getLastCellNum(); colNum++) { if (StrKit.isBlank(ed.getCell(colNum).toString())) { memo = removeKuoHao(st.getCell(colNum).toString()); column_name = ChineseCharacterUtil.getColumnNameByMemo(removeKuoHao(st.getCell(colNum).toString())); } else { int k = colNum; while (StrKit.isBlank(st.getCell(k).toString())) k--; memo = removeKuoHao(st.getCell(k).toString()) + "_" + removeKuoHao(ed.getCell(colNum).toString()); column_name = ChineseCharacterUtil.getColumnNameByMemo(removeKuoHao(st.getCell(k).toString())) + "_" + ChineseCharacterUtil.getColumnNameByMemo(removeKuoHao(ed.getCell(colNum).toString())); } Record r = new Record(); r.set("memo", memo); r.set("column_name", column_name); r.set("column_type", b.get(colNum)); _map[colNum] = r; colSql += "\"" + column_name + "\" " + b.get(colNum); if (notNullSet.contains(colNum + 1)) colSql += " NOT NULL"; colSql += ","; commentSql += "COMMENT ON COLUMN \"public\".\"" + tableName + "\".\"" + column_name + "\" IS '" + memo + "';\n"; } String finalSql = "CREATE TABLE \"public\".\"" + tableName + "\" ("; finalSql += "\"id\" serial4,"; finalSql += colSql; finalSql += "PRIMARY KEY (\"id\")"; finalSql += ");\n"; finalSql += "COMMENT ON COLUMN \"public\".\"" + tableName + "\".\"id\" IS '主键,自增长ID';\n"; finalSql += commentSql; Db.update(finalSql); //写入模板与表结构的关系t_importexcel_mapping String sql = "delete from t_importexcel_mapping where table_name=?"; Db.update(sql, tableName); List list = new ArrayList<>(); for (int i = 0; i < _map.length; i++) { Record record = new Record(); record.set("table_name", tableName); record.set("column_name", _map[i].getStr("column_name")); record.set("excel_column_idx", i + 1); record.set("memo", _map[i].getStr("memo")); record.set("column_type", removeNumbers(removeKuoHao(_map[i].getStr("column_type")))); list.add(record); } Db.batchSave("t_importexcel_mapping", list, 100); //写入t_importexcel_config sql = "delete from t_importexcel_config where table_name=?"; Db.update(sql, tableName); Record record = new Record(); record.set("table_name", tableName); record.set("excel_module_filename", "先不写上去"); record.set("data_start_row", _list.get(_list.size() - 1) + 1); record.set("column_num", ed.getLastCellNum()); Db.save("t_importexcel_config", "table_name", record); wb.close(); kv.set("success", true); kv.set("message", "恭喜,表结构创建成功!"); return kv; } /** * 功能:删除表 * * @param tableName */ public static void dropTable(String tableName) { String sql = "drop table if exists " + tableName; Db.update(sql); } /** * 功能:导入数据 * * @param table_name * @param filePath * @throws IOException * @throws ParseException */ public static void importData(String table_name, String filePath) throws IOException, ParseException { InputStream is = new FileInputStream(filePath); XSSFWorkbook wb = new XSSFWorkbook(is); //读取sheet页 XSSFSheet sheet = wb.getSheetAt(0); //通过表名获取到它的读取起始行,终止列 String sql = "select * from t_importexcel_config where table_name=?"; Record record = Db.findFirst(sql, table_name); int data_start_row = record.getInt("data_start_row"); int column_num = record.getInt("column_num"); //获取字段与EXCEL列的映射信息 sql = "select * from t_importexcel_mapping where table_name=?"; List list = Db.find(sql, table_name); Map _map = new HashMap<>(); for (Record r : list) { int excel_column_idx = r.getInt("excel_column_idx"); String column_name = r.getStr("column_name"); String column_type = r.getStr("column_type"); Record rt = new Record(); rt.set("column_name", column_name); rt.set("column_type", column_type); _map.put(excel_column_idx, rt); } //开始读取数据 List writeList = new ArrayList<>(); for (int i = data_start_row - 1; i <= sheet.getLastRowNum(); i++) { //获得行 Row row = sheet.getRow(i); //遍历列 if (row != null) { Record writeRecord = new Record(); for (int j = 0; j < column_num; j++) { Cell cell = row.getCell(j); CellBean bean = getCellBean(cell); String colType = _map.get(j + 1).getStr("column_type"); String colName = _map.get(j + 1).getStr("column_name"); if (colType.equals("int")) writeRecord.set(colName, Integer.parseInt(bean.getValue())); else if (colType.equals("varchar")) writeRecord.set(colName, bean.getValue()); else if (colType.equals("float")) writeRecord.set(colName, Float.parseFloat(bean.getValue().toString())); else if (colType.equals("date")) { String dateString = bean.getValue(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = dateFormat.parse(dateString); writeRecord.set(colName, date); } } writeList.add(writeRecord); } } // 写入数据 Db.batchSave(table_name, writeList, 100); //关闭excel wb.close(); } public static void main(String[] args) throws Exception { //告之配置文件位置 PropKit.use("application.properties"); HikariCpPlugin hp = new HikariCpPlugin(PropKit.get("jdbcUrl"), PropKit.get("user"), PropKit.get("password").trim(), PropKit.get("driverClassName")); hp.start(); // 配置ActiveRecord插件 ActiveRecordPlugin arp = new ActiveRecordPlugin(hp); //配置默认小写 arp.setContainerFactory(new CaseInsensitiveContainerFactory(true)); arp.setDialect(new PostgreSqlDialect()); arp.start(); //测试两个导入模板 String workingPath = "D:\\dsWork\\QingLong\\src\\main\\java\\UnitTest\\ImportExcel\\"; String filePath = workingPath + "测试1.xlsx"; String tableName = "ds_gtzz_t_bmwj";//表名,研发人员在界面上录入,程序需要检查此表名是不是存在,如果存在返回错误信息,不存在,则可以生成创建表的SQL语句 dropTable(tableName); createTable(tableName, filePath); importData(tableName, filePath); filePath = workingPath + "测试2.xlsx"; tableName = "ds_gtzz_t_zc";//表名,研发人员在界面上录入,程序需要检查此表名是不是存在,如果存在返回错误信息,不存在,则可以生成创建表的SQL语句 dropTable(tableName); createTable(tableName, filePath); importData(tableName, filePath); System.out.println("恭喜,所有操作成功完成!"); } }