我看到网上并没有这种例子,前两天做了一个题库app项目,刚好研究出来,分享给大家
先看实例效果:
上传效果以及代码
excel表格:
功能示例
添加成功
接下来看代码 测试的代码
//批量添加
@RequestMapping("/addQuestions")
@ResponseBody
public ResponseBase addQuestions(@RequestParam("file") MultipartFile file,Integer cid) throws IOException {
try {
// 获取所有的内容
Map<String, Map<Integer, Map<Integer, String>>> sheets = excel.readExcelToMap(file);
Set<String> keys = sheets.keySet();
List<String> steetsNames = new ArrayList<>();
// 获取所有的key ==页名称
for (String steetsName : keys) {
steetsNames.add(steetsName);
}
// 遍历所有的列
List<question> questions = new ArrayList<>();
for (int i = 0; i < sheets.size(); i++) {
// 根据页名称获取页
Map<Integer, Map<Integer, String>> rows = sheets.get(steetsNames.get(i));
if(rows.size()>0){
//检验第一列是否达到9列
if(!(rows.get(0).size()==9)){
return setResultError("请检查表中列大小是否符合添加规范");
}
// 根据所有的行 遍历
for (int j = 1; j < rows.size(); j++) {
// 遍历当前行的所有列
Map<Integer, String> columns = rows.get(j);
question question = new question();
question.setCid(cid);
question.setQuestiontitle(columns.get(0));
question.setQuestion_img(columns.get(1));
question.setSelecta(columns.get(2));
question.setSelectb(columns.get(3));
question.setSelectc(columns.get(4));
question.setSelectd(columns.get(5));
question.setQuestiontrue(columns.get(6));
question.setQuestion_analysis(columns.get(7));
question.setQuestion_analysisImg(columns.get(8));
questions.add(question);
}
}
}
if(questions!=null && questions.size()>0){
Integer addQuestions = qserver.addQuestions(questions);
if(addQuestions>0){
return setResultSuccess(addQuestions);
}
return setResultError("添加时出现未知错误!错误码:10");
}
return setResultError("表中数据小于1,请检查后重试");
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
return setResultError("表格出现未知错误!错误码:20");
}
}
util代码
//读取上传的文件
public Map<String, Map<Integer, Map<Integer, String>>> readExcelToMap(MultipartFile file) throws IOException {
Workbook wb = null;
Sheet sheet = null;
Row row = null;
// 声明所有页的集合
Map<String, Map<Integer, Map<Integer, String>>> mapSheet = new LinkedHashMap<>();
wb = readExcel(file);
if (wb != null) {
// 获取总页数
int pageSize = wb.getNumberOfSheets();
for (int i = 0; i < pageSize; i++) {
// 声明当前页的行和列
Map<Integer, Map<Integer, String>> map = new HashMap<>();
// 获取当前页
sheet = wb.getSheetAt(i);
//声明当前页图片的集合
Map<String, PictureData> pMap = null;
//获取图片
if(file.getOriginalFilename().endsWith(".xls")){
pMap = getPictures1((HSSFSheet) sheet);
}else{
pMap = getPictures2((XSSFSheet) sheet);
}
String sheetName = sheet.getSheetName();
// System.out.println("获取当前页的最大行数");
int rowSize = sheet.getPhysicalNumberOfRows();
// System.out.println("总行数:"+rowSize);
// System.out.println("遍历所有行");
for (int j = 0; j < rowSize; j++) {
// System.out.println("获取第"+j+"行");
row = sheet.getRow(j);
// System.out.println("获取当前页的最大列数");
int columnSize = row.getPhysicalNumberOfCells();
// 声明当前列
Map<Integer, String> columnMap = new HashMap<>();
// System.out.println("列大小:"+columnSize);
for (int j2 = 0; j2 < columnSize; j2++) {
// System.out.println("获取第"+j2+"列的内容");
String value = (String)getCellFormatValue(row.getCell(j2));
// 添加当前列的内容 j2代表第几列 value是内容
columnMap.put(j2, value);
}
// 添加当前行的内容 j代表第几行 value是列的内容 意思是第几行第几列的内容
map.put(j, columnMap);
}
//解析图片并上传到服务器 并设置该字段的值为字符串类型添加到map中 进行数据库上传
Object key[] = pMap.keySet().toArray();
for (int v = 0; v < pMap.size(); v++) {
PictureData pic = pMap.get(key[v]);
String picName = key[v].toString();
String ext = pic.suggestFileExtension();
byte[] data = pic.getData();
try {
InputStream input = new ByteArrayInputStream(data);
FileUploadResponse fileUpload = uploads.excelImgUpload(input,ext);
if(fileUpload.getUrl()!=null){
//解析key 并根据key 设置 某一行的某一列的 图片链接
String[] split = picName.split("-");
Integer rowIndex = Integer.parseInt(split[0].toString()),columnIndex = Integer.parseInt(split[1].toString());
//根据行下标 获取所有的列
Map<Integer, String> columns = map.get(rowIndex);
//根据列下标 设置图片链接值
columns.put(columnIndex, fileUpload.getUrl());
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// 添加当前页的所有内容
mapSheet.put(sheetName, map);
}
}
return mapSheet;
}
// 读取excel
@SuppressWarnings("unused")
private static Workbook readExcel(MultipartFile file) {
Workbook wb = null;
if (file == null) {
return null;
}
String filename = file.getOriginalFilename();
InputStream is = null;
try {
is = file.getInputStream();
if (filename.endsWith(".xls")) {
return wb = new HSSFWorkbook(is);
} else if (filename.endsWith(".xlsx")) {
return wb = new XSSFWorkbook(is);
} else {
return wb = null;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return wb;
}
接下来看本地测试 参数改为string 的路径,在文件上传后,上传名字需要自己改为随机名 以防重复文件名
工具类代码
public static Map<String, Map<Integer, Map<Integer, String>>> readExcelToMap(String excelFilePath) throws IOException {
Workbook wb = null;
Sheet sheet = null;
Row row = null;
// 声明所有页的集合
Map<String, Map<Integer, Map<Integer, String>>> mapSheet = new LinkedHashMap<>();
wb = readExcel(excelFilePath);
if (wb != null) {
// 获取总页数
int pageSize = wb.getNumberOfSheets();
for (int i = 0; i < pageSize; i++) {
// 声明当前页的行和列
Map<Integer, Map<Integer, String>> map = new HashMap<>();
// 获取当前页
sheet = wb.getSheetAt(i);
//声明当前页图片的集合
Map<String, PictureData> pMap = null;
//获取当前页的所有图片
if(excelFilePath.endsWith(".xls")){
pMap = getPictures1((HSSFSheet) sheet); //用于区分 没写方法重载
}else{
pMap = getPictures2((XSSFSheet) sheet); //用于区分 没写方法重载
}
String sheetName = sheet.getSheetName(); //获取页名称
// System.out.println("获取当前页的最大行数");
int rowSize = sheet.getPhysicalNumberOfRows();
// System.out.println("总行数:"+rowSize);
// System.out.println("遍历所有行");
for (int j = 0; j < rowSize; j++) {
// System.out.println("获取第"+j+"行");
row = sheet.getRow(j);
// System.out.println("获取当前页的最大列数");
int columnSize = row.getPhysicalNumberOfCells();
// 声明当前列
Map<Integer, String> columnMap = new HashMap<>();
// System.out.println("列大小:"+columnSize);
for (int j2 = 0; j2 < columnSize; j2++) {
// System.out.println("获取第"+j2+"列的内容");
String value = (String)getCellFormatValue(row.getCell(j2));
// 添加当前列的内容 j2代表第几列 value是内容
columnMap.put(j2, value);
}
// 添加当前行的内容 j代表第几行 value是列的内容 意思是第几行第几列的内容
map.put(j, columnMap);
}
//解析图片并上传到服务器 进行上传后 返回上传地址 并根据图片所在的表格位置 赋值表格位置为 上传后的返回地址
Object key[] = pMap.keySet().toArray();
for (int v = 0; v < pMap.size(); v++) {
//获取图像数据对象
PictureData pic = pMap.get(key[v]);
//获取文件名称
String picName = key[v].toString();
//获取文件后缀名
String ext = pic.suggestFileExtension();
byte[] data = pic.getData();//图片数据
//本地测试图片上传开始
FileOutputStream out = new FileOutputStream("D:\\" + picName + "." + ext);
out.write(data);
out.flush();
out.close();
//服务器上传可更该代码
/*
* InputStream input = new ByteArrayInputStream(data);
* 此处书写文件上传调用的方法
* 正常上传为Multipartfile 类型的文件
* 但是上传时还是需要转换成Inputstream 此处直接转换成该类型 由于该类型没办法获取 后缀名 所以需要传一个后缀名参数
* FileUploadResponse fileUpload = uploads.excelImgUpload(input,ext);//这是我的,此工具类没有该方法 需要根据自己的需求书写
*
*/
//本地测试结束
//解析key 并根据key 设置 某一行的某一列的 图片链接
String[] split = picName.split("-");
Integer rowIndex = Integer.parseInt(split[0].toString()),columnIndex = Integer.parseInt(split[1].toString());
//根据行下标 获取所有的列
Map<Integer, String> columns = map.get(rowIndex);
//根据列下标 设置图片链接值
columns.put(columnIndex, "D:\\" + picName + "." + ext);//参数2为图片上传后的路径
}
// 添加当前页的所有内容
mapSheet.put(sheetName, map);
}
}
return mapSheet;
}