最近在写项目中用到了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的表头也要换成”牛逼“。多个表头的操作也一样。

Cannot get a NUMERIC value from a STRING cell? 已解决的更多相关文章

  1. c#npoi 报错Cannot get a numeric value from a text cell 的解决

    一般是因为cell里边的值为数字导致,有时变成文本格式还是解决不了这个问题. 下边的代码是c# 改变设置cell类型的方法 是用这个参数 CellType.String Row.GetCell((in ...

  2. string.erase()--已解决

    在代码中需要实现这样一个功能,需要将[00000001]这个存储在string中的字符串的中括号去掉,首先想到的就是string.erase()这个函数.结果... 代码: #include < ...

  3. SyntaxError: EOL while scanning string literal的解决

    2281 python中字符串的最后一个字符是斜杠会导致出错:SyntaxError: EOL while scanning string literal [背景] Python 2.7.2 中想要通 ...

  4. SpringBoot整合Swagger2案例,以及报错:java.lang.NumberFormatException: For input string: ""原因和解决办法

    原文链接:https://blog.csdn.net/weixin_43724369/article/details/89341949 SpringBoot整合Swagger2案例 先说SpringB ...

  5. ASP.NET - Web API,从简单类型到复杂类型的参数传递用例,以及传递简单string类型的解决办法

    一,简单类型的传值 比如 public Users Get(int id) ,它可以使用两种方式获取: api/default/ $.get("/api/default",{id: ...

  6. Incorrect string value异常解决

    mysql数据库的一个问题 1366-Incorrect string value:'\xE5\x8D\xA1\xE5......' for column 'filename' at row 1 问题 ...

  7. Spring @ResponseBody只能返回String类型数据解决办法

    今天自己搭Spring MVC框架玩,使用AJAX调用Spring controller 并返回map对象,突然发现,哎,怎么@Response中只能返回String, 我用的Spring 3的版本也 ...

  8. spring mvc绑定对象String转Date解决入参不能是Date的问题

    使用spring的mvc,直接将页面参数绑定到对象中,对象中有属性为Date时会报错,此时需要处理下. 同样的,其他的需要处理的类型也可以用这种方法. 在controller中加入代码 @InitBi ...

  9. mybatis invalid comparison: java.sql.Timestamp and java.lang.String报错解决方法

    这个错的意思是:java.sql.Timestamp和java.lang.String无效的比较 错误的原因是:拿传入的时间类型参数与空字符串进行比较就会报这个异常 解决方法:只保留非null判断就可 ...

随机推荐

  1. 编译gpu集群版caffe

    在这个版本安装之前,要先装好opencv,openmpi等. 下载地址:https://github.com/yjxiong/caffe.git 我的opencv是2.4.12版本 编译是用了: cm ...

  2. java+根据多个url批量下载文件

    1.基本流程 当我们想要下载网站上的某个资源时,我们会获取一个url,它是服务器定位资源的一个描述,下载的过程有如下几步: (1)客户端发起一个url请求,获取连接对象. (2)服务器解析url,并且 ...

  3. flask框架(七): flask模板

    1.模板的使用 Flask使用的是Jinja2模板,所以其语法和Django无差别 2.自定义模板方法 Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render ...

  4. WPF之Treeview实现MVVM双向绑定

    Treeview分别有两个数据模板HierarchicalDataTemplate(层级数据模板)和DataTemplate(数据模板),分别应用于生成子数据项和普通数据项. 在使用过程中,如果对两个 ...

  5. Jmeter(十二)常用插件

    一.下载及安装 下载地址:https://jmeter-plugins.org/install/Install/ 下载后文件为一个jar包,将其放入jmeter安装目录下的lib/ext目录,然后重启 ...

  6. Centos7下设置MySql自动启动

    原文链接:http://www.cnblogs.com/Sungeek/p/9687565.html 1.将服务文件拷贝到init.d下,并重命名为mysql cp /usr/local/mysql/ ...

  7. Linux-配置共享目录

    找到相关rpm包 运行以及错误解决** rpm -ivh tcp_wrappers-7.6-34.i386.rpm rpm -ivh portmap-4.0-54.i386.rpm rpm -ivh ...

  8. Error:java: 错误: 不支持发行版本 5

    本文链接:https://blog.csdn.net/wo541075754/article/details/70154604 在Intellij idea中新建了一个Maven项目,运行时报错如下: ...

  9. import 和 require 的 区别

    node编程中最重要的思想就是模块化,import和require都是被模块化所使用. 遵循规范 require 是 AMD规范引入方式 import是es6的一个语法标准,如果要兼容浏览器的话必须转 ...

  10. 用Java实现一个二叉树

    介绍 使用Java实现一个int值类型的排序二叉树 二叉树 二叉树是一个递归的数据结构,每个节点最多有两个子节点. 通常二叉树是二分查找树,每个节点它的值大于或者等于在它左子树节点上的值,小于或者等于 ...