1. 程式人生 > >Cannot get a NUMERIC value from a STRING cell? 已解決

Cannot get a NUMERIC value from a STRING cell? 已解決

  最近在寫專案中用到了excel的匯入,遇到了Cannot get a NUMERIC value from a STRING cell的報錯。原因是無法從純數字的單元格用獲取String的方式獲取。跟了一下蛋碼,但是我明明做了處理了啊,看這裡

真是奇了個怪。。。。

網上百度了一堆,基本都指出了這個錯誤的原因,但。。。可能是我這個新手看不懂別人的蛋碼吧,其實我覺得他們的蛋碼沒有抽出來真的難看。

好了,看看我之前的程式碼:

再看看我修改之後的程式碼:

總結起來就是,我已經把讀取到的單元格內容的型別(NUMERIC)改為了STRING了,但我不知道為什麼switch還是走了NUMERIC(可能是我沒有轉換格式成功),然後我又用NUMERIC的取值方式 getNumericCellValue(),所以就報錯咯。

這是全部程式碼

Controller

    /**
     * 兌換碼匯入
     *
     * @return
     * @throws ParseException
     * @author lmh
     */
    @PostMapping(value = "/readExcel")
//    @ApiOperation(value = "兌換碼匯入")
    @Transactional
//    @RequiresPermissions("/lotteryPrize/readExcel")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "prizeId", value = "獎品id", required = true, dataType = "String"),
// @ApiImplicitParam(name = "prizeUrl", value = "兌換URI", required = true, dataType = "String")}) public ResponseEntity<Map<String, Object>> readExcel(/*String prizeId, String prizeUrl,*/ @RequestParam(value = "excelFile") MultipartFile excelFile) throws
ParseException { Map<String, Object> resultMap = new HashMap<>(); try { // 修改獎品表 // LotteryPrize prize = new LotteryPrize(); // prize.setId(prizeId); // prize.setPrizeUrl(prizeUrl); // prize.setUpdateTime(new Date(System.currentTimeMillis())); // boolean ret = this.prizeService.updateById(prize); // 匯入兌換碼 List<LotteryRedeemCode> redeemCodes = new ArrayList<LotteryRedeemCode>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); List<String[]> codeList = ReadExcelUtil.readExcel(excelFile); Map<String, Integer> titleMap = new HashMap<String, Integer>(); for (int i = 0; i < codeList.size(); i++) { String[] code = codeList.get(i); if (i == 0) { for (int j = 0; j < code.length; j++) { titleMap.put(code[j], j); } continue; } LotteryRedeemCode redeemCode = new LotteryRedeemCode(); redeemCode.setCreateTime(new Date(System.currentTimeMillis())); redeemCode.setRedeemCode(code[titleMap.get("兌換碼")]); // redeemCode.setPrizeId(prizeId); redeemCodes.add(redeemCode); } if (redeemCodes.size() > 0) {          // 批量新增(這裡是Mybatis-Plus框架),你們可以用for進行新增操作 this.redeemCodeService.insertBatch(redeemCodes); } if (!ret) { // 刪除失敗, 500 resultMap.put("status", 500); resultMap.put("message", "上傳失敗!"); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap); } resultMap.put("status", 201); resultMap.put("message", "上傳成功!"); return ResponseEntity.status(HttpStatus.CREATED).body(resultMap); } catch (IOException e) { logger.info("讀取excel檔案失敗", e); } return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); }
package 這裡自己寫;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

/**
 * 匯入excel工具類
 * 
 * @author lmh
 */
public class ReadExcelUtil {

    private static Logger logger = LoggerFactory.getLogger(ReadExcelUtil.class);
    private final static String xls = "xls";
    private final static String xlsx = "xlsx";

    /**
     * 讀入excel檔案,解析後返回
     * 
     * @param file
     * @throws IOException
     */
    public static List<String[]> readExcel(MultipartFile file) throws IOException {
        // 檢查檔案
        checkFile(file);
        // 獲得Workbook工作薄物件
        Workbook workbook = getWorkBook(file);
        // 建立返回物件,把每行中的值作為一個數組,所有行作為一個集合返回
        List<String[]> list = new ArrayList<String[]>();
        if (workbook != null) {
            for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
                // 獲得當前sheet工作表
                Sheet sheet = workbook.getSheetAt(sheetNum);
                if (sheet == null) {
                    continue;
                }
                // 獲得當前sheet的開始行
                int firstRowNum = sheet.getFirstRowNum();
                // 獲得當前sheet的結束行
                int lastRowNum = sheet.getLastRowNum();

                if (firstRowNum <= 0 && lastRowNum < 1) {
                    break;
                }
                // 獲取頭部的長度
                Row tiRow = sheet.getRow(firstRowNum);
                int totalClumNum = tiRow.getPhysicalNumberOfCells();

                // 迴圈所有行
                for (int rowNum = firstRowNum; rowNum <= lastRowNum; rowNum++) {
                    // 獲得當前行
                    Row row = sheet.getRow(rowNum);
                    if (row == null) {
                        continue;
                    }
                    int lastCellNum = row.getPhysicalNumberOfCells();
                    if (lastCellNum <= 0) {
                        continue;
                    }
                    // 獲得當前行的開始列
                    // int firstCellNum = row.getFirstCellNum(); 區第一個有值的列
                    // //獲得當前行的列數
                    // int lastCellNum = row.getPhysicalNumberOfCells();
                    String[] cells = new String[totalClumNum];
                    // 迴圈當前行
                    for (int cellNum = 0; cellNum < totalClumNum; cellNum++) {
                        Cell cell = row.getCell(cellNum);
                        cells[cellNum] = getCellValue(cell);
                    }
                    list.add(cells);
                }
            }
            workbook.close();
        }
        return list;
    }

    public static void checkFile(MultipartFile file) throws IOException {
        // 判斷檔案是否存在
        if (null == file) {
            logger.error("檔案不存在!");
            throw new FileNotFoundException("檔案不存在!");
        }
        // 獲得檔名
        String fileName = file.getOriginalFilename();
        // 判斷檔案是否是excel檔案
        if (!fileName.endsWith(xls) && !fileName.endsWith(xlsx)) {
            logger.error(fileName + "不是excel檔案");
            throw new IOException(fileName + "不是excel檔案");
        }
    }

    public static Workbook getWorkBook(MultipartFile file) {
        // 獲得檔名
        String fileName = file.getOriginalFilename();
        // 建立Workbook工作薄物件,表示整個excel
        Workbook workbook = null;
        try {
            // 獲取excel檔案的io流
            InputStream is = file.getInputStream();
            // 根據檔案字尾名不同(xls和xlsx)獲得不同的Workbook實現類物件
            if (fileName.endsWith(xls)) {
                // 2003
                workbook = new HSSFWorkbook(is);
            } else if (fileName.endsWith(xlsx)) {
                // 2007
                workbook = new XSSFWorkbook(is);
            }
        } catch (IOException e) {
            logger.info(e.getMessage());
        }
        return workbook;
    }

    public static String getCellValue(Cell cell) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        String cellValue = "";
        if (cell == null) {
            return cellValue;
        }

        CellType cellType = cell.getCellTypeEnum();
        // 把數字當成String來讀,避免出現1讀成1.0的情況
        if (cellType == CellType.NUMERIC) {
            cell.setCellType(CellType.STRING);
        }

        // 判斷資料的型別
        switch (cellType) {
        case NUMERIC: // 數字、日期
            if (DateUtil.isCellDateFormatted(cell)) {
                cellValue = fmt.format(cell.getDateCellValue()); // 日期型
            } else {
                cellValue = String.valueOf(cell.getStringCellValue());
//                cellValue = String.valueOf(cell.getNumericCellValue()); // 數字
                if (cellValue.contains("E")) {
                    cellValue = String.valueOf(new Double(cell.getNumericCellValue()).longValue()); // 數字
                }
            }
            break;
        case STRING: // 字串
            cellValue = String.valueOf(cell.getStringCellValue());
            break;
        case BOOLEAN: // Boolean
            cellValue = String.valueOf(cell.getBooleanCellValue());
            break;
        case FORMULA: // 公式
            cellValue = String.valueOf(cell.getCellFormula());
            break;
        case BLANK: // 空值
            cellValue = cell.getStringCellValue();
            break;
        case ERROR: // 故障
            cellValue = "非法字元";
            break;
        default:
            cellValue = "未知型別";
            break;
        }
        return cellValue;
    }

}

上面是工具類,下面是實體類:

@TableName("lottery_redeem_code")
public class LotteryRedeemCode extends Model<LotteryRedeemCode> {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.UUID)
    private String id;
    /**
     * 獎品ID
     */
    @ApiModelProperty(value = "獎品ID")
    @TableField("prize_id")
    private String prizeId;
    /**
     * 兌換碼
     */
    @ApiModelProperty(value = "兌換碼")
    @TableField("redeem_code")
    private String redeemCode;
    /**
     * 0-已抽中 1-未抽中
     */
    @ApiModelProperty(value = "0-已抽中 1-未抽中")
    private Integer status;
    /**
     * 建立時間
     */
    @ApiModelProperty(value = "建立時間")
    @TableField("create_time")
    private Date createTime;
    /**
     * 修改時間
     */
    @ApiModelProperty(value = "修改時間", hidden = true)
    @TableField("update_time")
    private Date updateTime;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPrizeId() {
        return prizeId;
    }

    public void setPrizeId(String prizeId) {
        this.prizeId = prizeId;
    }

    public String getRedeemCode() {
        return redeemCode;
    }

    public void setRedeemCode(String redeemCode) {
        this.redeemCode = redeemCode;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    @Override
    protected Serializable pkVal() {
        return this.id;
    }

    @Override
    public String toString() {
        return "LotteryRedeemCode{" +
                ", id=" + id +
                ", prizeId=" + prizeId +
                ", redeemCode=" + redeemCode +
                ", status=" + status +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                "}";
    }
}

MySQL:

CREATE TABLE `lottery_redeem_code` (
    `id` CHAR(32) NOT NULL,
    `redeem_code` VARCHAR(100) NOT NULL COMMENT '兌換碼',
    `status` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '0-已抽中 1-未抽中',
    `create_time` DATETIME NOT NULL COMMENT '建立時間',
    `update_time` DATETIME NULL DEFAULT NULL COMMENT '修改時間',
    PRIMARY KEY (`id`)
)
COMMENT='獎品兌換碼錶'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

 這是excel表的格式,格式要求不高,只要有一列的表頭是“兌換碼”就行了,可以隨意更改,只要和Controller中的

redeemCode.setRedeemCode(code[titleMap.get("兌換碼")]);對應起來就行了,假如我把”兌換碼“換成”牛逼“,excel的表頭也要換成”牛逼“。多個表頭的操作也一樣。