IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> layui+poi-Java实现导入导出excel文件 -> 正文阅读

[JavaScript知识库]layui+poi-Java实现导入导出excel文件

目录

需求说明

一、实现思路

二、前端代码

1.引入layui

2.隐藏部分内容

1)静态页面代码:

2)js(/jquery)代码:点击【导入xx】按钮的js:弹出上面隐藏的内容

3)、效果如下

3、下载模板js

4、选择文件、上传js?

?三、后端代码

1、下载模板:

2、导入文件?

1)controller层

2)处理文件工具类

3)后端校验文件格式的方法

4)校验表格标题行方法

5)将excel格子中的内容转为java的string类型的方法?

6)判断列标题头是否正确

?7)校验数据是否为空

8)校验是否为纯数字?:心机boy的方法

9)做业务逻辑处理(保存数据)

总结


需求说明

项目背景:springmvc架构下,前端jsp(引入layui框架样式)需要实现导出excel文件(模板),用户填写内容后,再上传进系统,系统解析保存excel文件中的数据。


一、实现思路

1、【模板制作】提前做好一个excel文件,可以用Excel自带的功能限制单元格的格式:例如某列只允许填写纯数字,某列不允许为空等等,以便用户填写错误。

2、【导出模板】把模板放到项目中,前端请求后,后端直接下载模板。

3、【导入】使用layui框架实现前端,java后端读取excel文件,POI框架操作文件,验证数据正确性等。

二、前端代码

1.引入layui

<script src="${xxxx}/layui-v2.4.5/layui/layui.all.js" charset="utf-8"></script>

2.隐藏部分内容

有一弹窗,点击【导入xx】按钮之前不显示。点击【导入xx】按钮后弹出:

1)静态页面代码:

<body>
	<div style="display: none;padding: 5px" id="showUploadExcelDiv">
			<form action="" method="post" class="layui-form layui-form-pane" id="exportFrm" lay-filter="exportFrm">
				<div class="layui-upload" >
					<button type="button" style="margin-top: 20px;margin-left: 20px" class="layui-btn layui-btn-warm" 
						 onclick="downloadTemplate()">下载模板</button>
					<button type="button" style="margin-top: 20px;margin-left: 20px" class="layui-btn layui-btn-normal" 
						id="chooseFile">选择文件</button>
					<button type="button" style="margin-top: 20px" class="layui-btn"
						id="uploadFle">开始上传</button>
				</div>
			</form>
		</div>
		<table class="layui-hide" id="test" lay-filter="test"></table>
	<form>
		<div class="panel-body">
			<div class="row-fluid">
				<div class="span3">	
					<span class="label-none"> <br/></span>
					<button type="button" id="uploadFile" class="layui-btn layui-btn-sm"   onclick="upload();" >导入</button>
				</div> 
			</div>
		</div>
    </form>
<body>

2)js(/jquery)代码:点击【导入xx】按钮的js:弹出上面隐藏的内容

        function upload(){
			 layer.open({
	                type: 1,
	                area: ['800px','150px'],
	                fixed: false,
	                title: '导入数据',
	                content: $("#showUploadExcelDiv"),
	                end: function () {
	                    location.reload();
	                }
	            })
		}

3)、效果如下

?

3、下载模板js

function downloadTemplate(){
    //后端下载地址
    location.href="${xxx}/xxx/yyy/downloadTemplate";
}

4、选择文件、上传js?

	<script>
	/* 导入 */
	layui.use(['form', 'layedit','upload'], function(){
	    var form = layui.form,
	    $ = layui.jquery,
	    layer = layui.layer,
	    layedit = layui.layedit,
	    upload=layui.upload;

	    upload.render({
            elem: "#chooseFile",   //导入id
            //这里可以带一些页面上想传给后台的参数
            data:{
                id:function(){
                	var id = $("#id").val();
                    return id;
                },
                year:function(){
                	var year = $("#year").val();
                    return year;
                }
            },
            url: '${xx}/xxx/yyy/importExcel?year='+year+"&id="+id,
            // 与bindAction一起使用,不直接上传,当点击#uploadFle按钮时才上传
            auto: false,    
            bindAction: '#uploadFle',
            accept: "file",
            size: 10240,
            exts: 'xls|xlsx', 
            /* 上传完毕回调 */
            done: function (res) {
                /* 后端传code值:1代表成功,0代表失败 */
            	var code = res.code;
            	if(code == "1"){
            		top.$.jBox.tip("导入成功!");
            		//可以跳转到某页面
            		//location.href="${xxx}/xxx/yyy/form;
                    //可以刷新本页面
            		//window.location.reload()
            	}else{
                    //失败后弹出页面,上面附有失败原因(后端写好传来)
            		layer.confirm(res.msg, {title:'导入失败,系统提示'},function(index){
            			layer.close(index);
            			window.location.reload()
            		});
            	}
            },
            error: function(){
                //请求异常回调
                top.$.jBox.tip("服务器异常,请稍后再试");
                window.location.reload()
            }
        });
	 })
</script>

效果展示:


?三、后端代码

1、下载模板:


    /**
	 * 文件模板下载
	 * @param fileModleId
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "downloadTemplate")
	public void downloadTemplate(HttpServletResponse response) throws Exception {
        //获取项目中模板为输入流
		InputStream is=Thread.currentThread().getContextClassLoader().getResourceAsStream("templates/xxx/yyyy/DetailTemp.xlsx");
        //利用poi框架导出文件
        //org.apache.poi.xssf.usermodel.XSSFWorkbook;
		XSSFWorkbook wb0 = new XSSFWorkbook(is);
		try {
			OutputStream out = response.getOutputStream();
			response.setHeader("Content-disposition", "attachment;filename="+ new String( "导入成本明细清单模板.xlsx".getBytes("gb2312"), "ISO8859-1" ));
			response.setContentType("application/msexcel;charset=UTF-8");
			wb0.write(out);
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

2、导入文件?

1)controller层

	/**
	 * 导入excel文件
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "importExcel", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    public HashMap<String, Object> importData(@RequestPart(value = "file") MultipartFile file,HttpServletRequest request) {
		
		//获取导入时传来的参数:可做业务处理:略
		String year = request.getParameter("year");
		String id = request.getParameter("id");
		
        //构建返回前端值,此处使用HashMap<String, Object>
        //其中key为code value为1代表成功,value为0代表失败
        //   key为msg,value写入具体错误信息是什么
		HashMap<String, Object> resultMap = null;
		try {
    		InputStream inputStream = file.getInputStream();
            //写个工具类,处理excel 的校验、保存:返回值直接是可以对接前端的
            resultMap = util.readExcel(inputStream, file.getOriginalFilename(),new XXXEntity());
            inputStream.close();
            return resultMap;
		} catch (Exception e) {
			System.out.print("[导入异常]"+e.getMessage());
			resultMap.put("code", "0");
			resultMap.put("msg", "读取文件异常!");
			return resultMap;
	    }
    }

2)处理文件工具类

@Service
public class ExcelUtilForXXXImport {
	private static final Logger logger = LoggerFactory.getLogger(ExcelUtilForXXXImport.class);

	@Autowired
	private XXXEntityService xxxEntityService;
	
	/**
     * 处理上传的文件
     *
     * @param in
     * @param fileName
     * @return
     * @throws Exception
     */
    public HashMap<String, Object> readExcel(InputStream in, String fileName,XXXEntity xxxEntity) throws Exception {
        //构建返回值
    	HashMap<String, Object> hashMap=new HashMap<String, Object>();
        //创建Excel工作薄
        try {
        	//判断文件格式是否为excel,是否为空
            //详见:3)后端校验文件格式的方法
        	Workbook work = getWorkbook(in, fileName);
            if (null == work) {
                throw new Exception("创建Excel工作薄为空!");
            }

            //读第一页
            Sheet sheet = work.getSheetAt(0);

            //step1: 验证导入文件的标题头是否合法
    		String[] columnName = {"序号", "月份",...};
            //详见 : 4)校验表格标题行方法
    		String resultString=verificationExcelHeadLine(sheet, columnName);
            //有返回信息代表有错误,没有返回信息代表验证通过
    		if (!resultString.equals("")) {
    			hashMap.put("code", "0");
    			hashMap.put("msg", "请使用正确模板上传excel文件。"+resultString);
    			return hashMap;
    		}

    		//step2: 验证导入文件的标题 列 是否合法
    		String[] colName = {"第一月", "第二月",。。。};
            //详见: 6)判断列标题头是否正确
    		String resultStr = verificationExcelHeadLineTwo(sheet, colName);
            //有返回信息代表有错误,没有返回信息代表验证通过
    		if (!resultStr.equals("")) {
    			hashMap.put("code", "0");
    			hashMap.put("msg", "请使用正确模板上传excel文件。"+resultStr);
    			return hashMap;
    		}

    		//step3: 验证数据是否为空,长度是否过长,是否为纯数字。。。
            //?详见7)校验数据是否为空
    		String verificationDateResultString = verificationDate(sheet);
    		if (!verificationDateResultString.equals("")) {
    			hashMap.put("code", "0");
    			hashMap.put("msg", verificationDateResultString);
    			return hashMap;
    		}

    		//step4: 文件内容合法,做业务逻辑处理(保存)
            //?详见9)做业务逻辑处理(保存数据)
    		String saveResultString = insertData(sheet,xxxEntity);
    		if (!saveResultString.equals("")) {
    			hashMap.put("code", "0");
    			hashMap.put("msg", saveResultString);
    			return hashMap;
    		}

            //以上都顺利进行,返回前端:导入成功
    		hashMap.put("code", "1");
	        hashMap.put("msg", "导入成功!");
	        return hashMap;
		} catch (Exception e) {
			System.out.print("[读取excel异常]"+e.getMessage());
			hashMap.put("code", "0");
	        hashMap.put("msg", "读取excel异常");
	        return hashMap;
		}
        
    }

}

3)后端校验文件格式的方法

	/**
     * 后端判断文件格式方式
     *
     * @param inStr
     * @param fileName
     * @return
     * @throws Exception
     */
    public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
        Workbook workbook = null;
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        if (".xls".equals(fileType)) {
            workbook = new HSSFWorkbook(inStr);
        } else if (".xlsx".equals(fileType)) {
            workbook = new XSSFWorkbook(inStr);
        } else {
            throw new Exception("请上传excel文件!");
        }
        return workbook;
    }

4)校验表格标题行方法

    /***
     * 校验导入的列表Excel文件标题行是否为标准行
     */
    public static String verificationExcelHeadLine(Sheet sheet, String[] columnName) throws Exception {
    	String result = "";
    	try {
            //获取第一行:标题行
    		Row row = sheet.getRow(0);
            
    		if (row != null && row.getLastCellNum() >= columnName.length) {
    			int lastCellNum = row.getLastCellNum();
                //循环遍历指定的数组内容与文件中内容一一对比
    			for (int idx = 0; idx < lastCellNum; idx++) {
                    //将格子中的内容转为java的string类型的方法
                    //详见5)将excel格子中的内容转为java的string类型的方法
    				String value = getStringCellValue(row.getCell(idx));
    				if (idx < 4) {
    					if (value == null || !columnName[idx].equals(value)) {
    						result = result+"标题行第" + (idx + 1) + "列名称错误!";
    					}
    				} else {
    					if (idx == 4) {
    						if (value == null) {
    							result = result+"标题标准表格表头不一致";
    						}
    					}
    				}
    			}
    		} else {
    			result = "上传文件首行不能为空或与标准表格表头不一致!";
    		}
    	} catch (Exception ex) {
    		logger.info("【导入成本】校验数据异常");
    	}
    	return result;
    }

5)将excel格子中的内容转为java的string类型的方法?

    /**
     * 获取单元格数据内容为字符串类型的数据
     * 
     * @param cell Excel单元格
     * @return String 单元格数据内容
     */
    private static String getStringCellValue(Cell cell) {
        String strCell = "";
        switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            strCell = cell.getStringCellValue();
            break;
        case Cell.CELL_TYPE_NUMERIC:
            strCell = String.valueOf(cell.getNumericCellValue());
            break;
        case Cell.CELL_TYPE_BOOLEAN:
            strCell = String.valueOf(cell.getBooleanCellValue());
            break;
        case Cell.CELL_TYPE_BLANK:
            strCell = "";
            break;
        default:
            strCell = "";
            break;
        }
        if (strCell.equals("") || strCell == null) {
            return "";
        }
        if (cell == null) {
            return "";
        }
        return strCell;
    }
    

6)判断列标题头是否正确

    public String verificationExcelHeadLineTwo(Sheet sheet, String[] columnName) {
    	String result = "";
    	try {
    		int allRowNum = sheet.getLastRowNum();
    		for(int i = 1; i <= allRowNum; i++) {
    			Row row = sheet.getRow(i);
    			if (row != null && row.getCell(1) != null) {
    				String value = getStringCellValue(row.getCell(1));
    				if (value == null || !columnName[i-1].equals(value)) {
						result = result+"第" +i+"行第2列名称错误!";
					}
        		} else {
        			result = "请选择正确模板!";
        		}
    		}
    	} catch (Exception ex) {
    		logger.info("【导入成本】校验数据异常");
    	}
    	return result;
    }

?7)校验数据是否为空

	/**
     * 校验数据是否为纯数字,是否为空
     * @param sheet
     * @return
     */
	
	private String verificationDate(Sheet sheet) {
		String result = "";
		int allRowNum = sheet.getLastRowNum();
		if(allRowNum != 12) {
			result = "数据行数不为12行,请检查模板;";
			return result;
		}
    	try {
    		//循环行
    		for(int i = 1; i <= sheet.getLastRowNum(); i++) {
    			Row row = sheet.getRow(i);
    			int allCellNum = row.getLastCellNum();
        		if (row != null &&  allCellNum == 9) {
        			//循环列
        			for (int idx = 0; idx < allCellNum; idx++) {
        				String value = getStringCellValue(row.getCell(idx));
        				if(!StringUtils.isNotEmpty(value)) {
        					result = result+"第"+i+"行"+"第"+idx+"列为空;";
        				}else {
        					//第二列以后为纯数字
        					if(idx>=2) {
                                //isNumeric为校验是否为数字的方法
                                //详见:8)校验是否为纯数字
        						if(!isNumeric(value)) {
        							result = result+"第"+i+"行"+"第"+idx+"列不是数字格式;";
        						}
        					}
        				}
        			}
        		} else {
        			result = "数据列数不为8列,请检查模板;";
        			return result;
        		}
    		}
    	} catch (Exception ex) {
    		 logger.info("【导入成本】校验数据异常");
    	}
    	return result;
	}
	 

8)校验是否为纯数字?:心机boy的方法

    /**
     * 判断是否为数字:直接去创建BigDecimal,失败就是非数字,BigDecimal校验的比我们厉害
     * @param str
     * @return 
     */
    public static boolean isNumeric(String str) {
        String bigStr;
        try {
            bigStr = new BigDecimal(str).toString();
        } catch (Exception e) {
            return false;//异常 说明包含非数字。
        }
        return true;
    }

9)做业务逻辑处理(保存数据)



    private String insertData(Sheet sheet,XXXEntity xxxEntity) {
    	String result = "";
    	
    	//构建子表数据
    	List<XXXEntity> xxxEntityList = new ArrayList<XXXEntity>();
    	Row row = null;
    	try {
    		for (int i =1; i <= sheet.getLastRowNum(); i++) {
                row = sheet.getRow(i);
                XXXEntity entity = new XXXEntity();
                
                entity.setMonth(getStringCellValue(row.getCell(0)));
                entity.setXXX(
                    new BigDecimal(
                        getStringCellValue(row.getCell(1))));
                //...
                xxxEntityList.add(entity);
            }
   
        	xxxEntityService.save(jCCostManager);
    	}catch(Exception e) {
    		result = "数据格式异常无法保存。";
    		return result;
    	}
    	
    	return result;
    }
    

总结

? ? ? ? 以上可以实现简单导入导出excel,如有错误,请指正!

????????希望广大网友有更简便的方法或框架可以提供~

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-03 15:59:25  更:2022-01-03 16:01:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:29:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码