ExcelPublic.java,其中包含讀取Excel第一行(一般為標題行),讀取所有Excel中所有數據(包括標題行),讀取表頭字段在excel中的位置(列值)等方法。
poi版本為3.15,數據庫為MySQL
測試Excel和s數據庫結果如下:
ExcelPublic.java
package com.alphajuns.ssm.util; /** * ExcelPublic.java */ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; /** * <p> * ClassName: excelPublic * </p> * <p> * Description: 負責excel的公共類 * </p> * <p> * Author: Administrator * </p> * <p> * Date: 2015-6-28 * </p> */ public class ExcelPublic { /** * <p> * Description: 一個提取excel文件內cell內容的方法 * </p> * . * * @param cell * 一個單元格內的內容 * @return 把cell轉換成string */ @SuppressWarnings("deprecation") public static String getCellValue(Cell cell) { String cellStr = null; DecimalFormat DF = new DecimalFormat("0"); if (cell == null) { cellStr = ""; } else { switch (cell.getCellType()) { //case Cell.CELL_TYPE_BOOLEAN: case BOOLEAN: cellStr = String.valueOf(cell.getBooleanCellValue()); break; case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { // 日期 final DateFormat FORMATER = new SimpleDateFormat("dd.MM.yyyy"); cellStr = FORMATER.format(cell.getDateCellValue()); } else { String number = String.valueOf(cell.getNumericCellValue()); if(number.indexOf(".") != -1){ DF = new DecimalFormat("#.###"); } cellStr = DF.format(cell.getNumericCellValue()); } break; case BLANK: cellStr = ""; break; case ERROR: cellStr = String.valueOf(cell.getErrorCellValue()); break; case FORMULA: // 首先判斷一下是不是公式 cell.setCellType(CellType.NUMERIC); // 設置其單元格類型為數字 try { cellStr = DF.format(cell.getNumericCellValue()); // 獲取數字值 } catch (Exception e) { throw new RuntimeException("行:" + (cell.getRowIndex() + 1) + ",列:" + (cell.getColumnIndex() + 1) + " 獲取公式值失敗," + e.toString()); } break; default: cellStr = cell.getStringCellValue(); break; } } return cellStr; } /** * <p> * Description: 一個檢查excel的第一行是否有值的方法 * </p> * * @param path * path * @return boolean * @throws IOException * IO異常 */ public static boolean checkArray(String path) throws IOException { final FileInputStream FS = new FileInputStream(path); final String TYPE = path.substring(path.lastIndexOf(".") + 1).toLowerCase(); Workbook wb; if ("xlsx".equals(TYPE)) { wb = new XSSFWorkbook(FS); } else { wb = new HSSFWorkbook(FS); } Sheet sheet = wb.getSheetAt(0); boolean flag = sheet.getRow(0) != null ? true : false; // 添加一個檢查表格第一行是否為正常數據的方法 gary 2016.9.19 int cellNum = 0; if (sheet.getRow(0) != null) { // 檢查第一行是不是為空 cellNum = sheet.getRow(0).getPhysicalNumberOfCells(); } else { cellNum = 0; } Row row = null; Cell cell = null; final String[] STR = new String[cellNum]; if (flag) { row = sheet.getRow(0); for (int j = 1; j <= cellNum; j++) { cell = row.getCell(j - 1); if (cell == null) { STR[j - 1] = ""; } else { STR[j - 1] = getCellValue(cell); } } } sheet = null; wb.close(); wb = null; return flag; } public static String[][] dyadicArray(String path, int startNum, int endNum) throws IOException { String[][] str = null; FileInputStream fs = new FileInputStream(path); String type = path.substring(path.lastIndexOf(".") + 1).toLowerCase(); Workbook wb; if ("xlsx".equals(type)) { wb = new XSSFWorkbook(fs); } else { wb = new HSSFWorkbook(fs); } try { Sheet sheet = wb.getSheetAt(0); final int A = sheet.getPhysicalNumberOfRows(); // 行數 final int B; B = sheet.getRow(0).getPhysicalNumberOfCells(); // 列數 if (endNum == 0 && startNum == 1) { endNum = A; } else if (startNum == 0) { startNum = 1; } int rowNumber = endNum - startNum + 1; str = new String[rowNumber][B]; Row row = null; Cell cell = null; for (int i = 1; i <= rowNumber; i++) { row = sheet.getRow(startNum - 1); for (int j = 1; j <= B; j++) { cell = row.getCell(j - 1); if (cell == null) { str[i - 1][j - 1] = ""; } else { str[i - 1][j - 1] = getCellValue(cell); } cell = null; } startNum++; row = null; } sheet = null; } catch (Exception e) { throw new IOException(e); } finally { wb.close(); wb = null; fs = null; } return str; } /** * <p> * Description: 得到excel行數的方法 * </p> * * @param path * path * @return int * @throws IOException */ public static int getRowNumber(String path) throws IOException { final FileInputStream FS = new FileInputStream(path); final String TYPE = path.substring(path.lastIndexOf(".") + 1).toLowerCase(); Workbook wb; if ("xlsx".equals(TYPE)) { wb = new XSSFWorkbook(FS); } else { wb = new HSSFWorkbook(FS); } final Sheet SHEET = wb.getSheetAt(0); int firstRowNumber = SHEET.getFirstRowNum(); int lastRowNumber = SHEET.getLastRowNum(); int rowNumber = lastRowNumber - firstRowNumber + 1; // 行數 wb.close(); return rowNumber; } public static ArrayList<String> readExcelFirstline(String path) throws IOException { final ArrayList<String> FIRSTLINE = new ArrayList<String>(); if (checkArray(path)) { String[][] article = dyadicArray(path, 1, 1); final int LENGTH = article[0].length; for (int i = 0; i < LENGTH; i++) { FIRSTLINE.add(article[0][i]); } article = null; } return FIRSTLINE; } /** * <p> * Description: 將二維數組的每一行轉成ArrayList * </p> * . * * @param path * 帶文件名的路徑 * @param dyadic * 二維數組,也就是給定的原文,目前已經指定了行數范圍 * @return 返回該行 * @throws IOException * Signals that an I/O exception has occurred. */ public static HashMap<Integer, ArrayList<String>> readExcelLine(String path, String[][] dyadic) throws IOException { final HashMap<Integer, ArrayList<String>> READEXCEL = new HashMap<Integer, ArrayList<String>>(); final int LENGTH = dyadic.length; final int WIDTH = dyadic[0].length; String[][] article = null; article = dyadic; for (int i = 0; i < LENGTH; i++) { final ArrayList<String> ROW = new ArrayList<String>(); for (int j = 0; j < WIDTH; j++) { ROW.add(article[i][j]); } READEXCEL.put(i, ROW); } return READEXCEL; } public static Integer findTheWord(String path, String word) throws IOException { int wordLocation = 0; ArrayList<String> arr = null; arr = readExcelFirstline(path); if (arr.contains(word)) { wordLocation = arr.indexOf(word); } else { wordLocation = -1; } return wordLocation; } // /** // * <p> // * Description: 根據不同文本來適配不同字符編碼,針對txt文本使用 // * </p>. // * // * @param fileName 帶文件名的路徑 // * @return 文件編碼 // * @throws IOException Signals that an I/O exception has occurred. // */ // public static String getCharset(String fileName) throws IOException { // final BufferedInputStream BIN = new BufferedInputStream(new // FileInputStream(fileName)); // final int NUMBER = 8; // final int P = (BIN.read() << NUMBER) + BIN.read(); // final int UTF8 = 0xefbb; // final int UNICODE = 0xfffe; // final int UTF16BE = 0xfeff; // String code = null; // switch (P) { // case UTF8: // code = "UTF-8"; // break; // case UNICODE: // code = "Unicode"; // break; // case UTF16BE: // code = "UTF-16BE"; // break; // default: // code = "GBK"; // } // BIN.close(); // return code; // } /** * <p> * Description: 獲取當前時間戳,格式到分 * </p> * . * * @return 當前時間 */ public static String getTime() { final Date DATE = new Date(); // 創建一個時間對象,獲取到當前的時間 final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMddHHmm"); // 設置時間顯示格式 final String STR = SDF.format(DATE); // 將當前時間格式化為String return STR; // 輸出結果 } /** * <p> * Description: 在傳入為list時的插入方法 * </p> * . * * @param outList * 輸出的字段 * @param inList * 輸入的字段 * @param value * 值 * @return outlist */ public static List<String> addValueMethod(List<String> outList, List<String> inList, Integer value) { String word = null; if (value == -1) { outList.add(""); } else if (value > inList.size()) { outList.add(""); } else if (inList.get(value) != null) { if (inList.get(value).trim().length() > 250) { outList.add(""); } else { if (inList.get(value).trim().contains("\'")) { word = inList.get(value).trim().replace("\'", "’"); } else if (inList.get(value).trim().contains("\"")) { word = inList.get(value).trim().replace("\"", "”"); } else { word = inList.get(value).trim(); } outList.add(word); } } else { outList.add(""); } return outList; } /** * <p> * Description: 在插入值時去掉“.”的方法 * </p> * * @param outList * 輸出值 * @param inList * 輸出值 * @param value * 位置 * @return 輸出結果 */ public static List<String> addValueMethodHavePoint(List<String> outList, List<String> inList, Integer value) { if (value == -1) { outList.add(""); } else if (value > inList.size()) { outList.add(""); } else if (inList.get(value) != null) { String newList; newList = inList.get(value).replace(".", ""); outList.add(newList); } else { outList.add(""); } return outList; } /** * <p> * Description: 生成當前時間,精確到毫秒,格式為年月日小時分鍾秒毫秒,沒有空格 * </p> * . * * @return 時間string */ public static String haveCurrentTime() { final long CURRENTTIME = System.currentTimeMillis(); final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyyMMddHHmmssS"); final Date DATE = new Date(CURRENTTIME); final String TIME = FORMATTER.format(DATE); return TIME; } /** * <p> * Description: 在需要提取文件名並將之插入時的方法 * </p> * . * * @param outList * 輸出數據 * @param filepath * 帶文件名的路徑 * @return 輸出數據 * @throws IOException * Signals that an I/O exception has occurred. */ public static List<String> addValueFileName(List<String> outList, String filepath) throws IOException { final String PATH1 = filepath.substring(0, filepath.lastIndexOf("_")); // 根據“_”之前的位置來獲取文件名 final String PATH = PATH1.substring(PATH1.lastIndexOf(File.separator) + 1).toUpperCase(); outList.add(PATH); return outList; } /** * 根據文件路徑讀取列所在位置 * * @param tempPath * excel路徑 * @param columns * 列名數組 * @return Map<String,Integer> key為列名,value為列在excel中的第幾列 * @throws IOException */ public static Map<String, Integer> readLocation(String tempPath, String... columns) throws IOException { Map<String, Integer> locationMap = new HashMap<String, Integer>(); for (String column : columns) { int location = ExcelPublic.findTheWord(tempPath, column); locationMap.put(column, location); } return locationMap; } }
junit測試類
package com.alphajuns.junit; import com.alphajuns.ssm.util.ExcelPublic; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; /** * @ClassName ExcelTest * @Description TODO * @Author AlphaJunS * @Date 2020/4/18 22:24 * @Version 1.0 */ public class ExcelTest extends SuperJunitTest { @Autowired private JdbcTemplate jdbcTemplate; @Test public void readExcel() { String result = null; String filePath = "C:\\TempFile\\temp\\導入商品信息.xlsx"; File file = new File(filePath); try { // 判斷第一行是否有值 if (ExcelPublic.checkArray(filePath)) { // 讀取第一行 List<String> firstLine = new ArrayList<>(); firstLine = ExcelPublic.readExcelFirstline(filePath); // 讀取excel文件中的所有內容 String[][] content = ExcelPublic.dyadicArray(filePath, 1, 0); // 存放需要插入的數據的位置 Map<String, Integer> locationMap = new HashMap<String, Integer>(); // 存放需要插入的數據的位置 String[] finalFieldArr = { "商品ID", "商品標題", "商品賣點", "商品價格"}; // 讀取標題字段及其所在列位置 locationMap = readLocation(filePath, finalFieldArr); if (locationMap.containsValue(-1)) { result = "表頭不正確,正確表頭為:" + Arrays.asList(finalFieldArr); throw new Exception(result); } // 模擬調用service方法 result = serviceHandleMethod(firstLine, content, locationMap); } } catch (Exception e) { e.printStackTrace(); } } /** * @Description 模擬service層方法 * @param firstLine * @param content * @param locationMap * @return java.lang.String */ private String serviceHandleMethod(List<String> firstLine, String[][] content, Map<String, Integer> locationMap) { // 保存指定字段,可用於檢查數據庫中是否已經存在,檢驗導入數據該字段是否重復等 List<String> itemIdList = new ArrayList<>(); // map中保存了所有excel中的數據,不含表頭字段 Map<String, String[]> itemMap = new HashMap<>(); // excel中content下表從1開始到末尾 for (int i = 1; i < content.length; i++) { // 獲取指定列的的值 String itemId = content[i][locationMap.get("商品ID")]; // 以指定列為鍵,該行數據作為值保存在map中 itemMap.put(itemId, content[i]); itemIdList.add(itemId); } // 校驗數據庫是否已經存在,校驗重復等操作 // 批量操作,插入數據庫等,可采用spring JdbcTemplate的批量更新操作 // 生成時間 String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); // sql String sql = "insert into tb_item (id, title, sell_point, price, num , cid, status, created, updated) values(?, ?, ?, ?, 500, 560, 1, '" + date +"','" + date + "')"; List<Object[]> batchArgs = new ArrayList<Object[]>(); // 遍歷,封裝參數 /*for (int i = 0; i < itemIdList.size(); i++) { String itemId = itemIdList.get(i); String[] itemArray = itemMap.get(itemId); Object[] batchArg = new Object[]{}; for (int j = 0; j < itemArray.length; j++) { batchArg[j] = itemArray[j]; } batchArgs.add(batchArg); }*/ for (int i = 1; i < content.length; i++) { String[] itemArray = content[i]; Object[] batchArg = new Object[itemArray.length]; for (int j = 0; j < itemArray.length; j++) { batchArg[j] = itemArray[j]; } batchArgs.add(batchArg); } // 執行sql String result = ""; try { jdbcTemplate.batchUpdate(sql, batchArgs); result = "success"; } catch (DataAccessException e) { e.printStackTrace(); } return result; } /** * 讀取字段位置 * @param tempPath * @param columns * @return * @throws IOException */ private Map<String,Integer> readLocation(String tempPath,String... columns) throws IOException { Map<String,Integer> locationMap = new HashMap<String,Integer>(); for(String column : columns){ int location = ExcelPublic.findTheWord(tempPath, column); locationMap.put(column,location); } return locationMap; } }