项目开发经验分享—导入Excel

    上一篇博客我们分享了UI设计经验漂亮的弹出框效果》。今天我们来分享一下数据上传经验:导入Excel

引言

    作为一个信息管理类系统,我们需要录入很多数据,比如学生管理系统,我们就需要添加很多学生的信息,如下图所示:
                 
    这个时候如果我们一条一条去添加则会太麻烦,有没有简便一点的方法,一下子就把数据添加进去呢?答案是有,而且很多系统都设计了——添加Excel导入功能,方便把信息通过Excel直接导入到数据库,减轻了用户的工作量。这么人性化的功能,我们在做类似的系统时也应该借鉴进去,给用户更高的体验度!下面我们来看看具体的实现吧:

思路

1、引入commons-fileupload.jar包,添加相关依赖

2、添加ExcelUtility工具类

3、配置SpringMVC

4、上传Excel文件将并存入数据库

实现

1、引入commons-fileupload.jar包,在web的pom文件里添加相关依赖:

<pre name="code" class="html"><dependency>  
    <groupId>commons-fileupload</groupId>  
    <artifactId>commons-fileupload</artifactId>  
    <version>1.3.1</version>   
</dependency>  

2、添加ExcelUtility工具类

(1)ExcelUtility工具类中Excel导入代码:

	/**
	 * excel表导入
	 * @param in  承载着Excel的输入流
	 * @param sheetName  要输入的工作表名称集合,如String[] sheetName={"sheet1","sheet2","sheet3","sheet4"}
	 * @param entityClass  List中对象的类型
	 * @param fieldMap   Excel中的中文列头和类的英文属性的对应关系Map
	 * @param uniqueFields  指定业务主键组合(即复合主键),这些列的组合不能重复
	 * @return
	 */
	public <T>  List excelToList(InputStream in, String[] sheetName,
			LinkedHashMap<String, Class<?>> entityClass,

			LinkedHashMap<String, LinkedHashMap<String, String>> fieldMap,
			LinkedHashMap<String, String[]> uniqueFields)  {

		// 定义要返回的List列表
		List<T> resultList = new ArrayList<T>();
		try {
			// 根据Excel数据源创建WorkBook
			Workbook wb = Workbook.getWorkbook(in);
			// 获取工作表
			for (int k = 0; k < sheetName.length; k++) {
				resultList.clear();
				Sheet sheet = wb.getSheet(sheetName[k]);
				String singleSheetName = sheetName[k]; // 获取sheet名为
				Class<?> enClassName = null;
				// 给对象中的sheet所对应的实体
				for (Entry<String, Class<?>> entry : entityClass.entrySet()) {
					// 获取中文字段名
					String enSheetName = entry.getKey();
					// 获取英文字段名
					if (enSheetName.equals(singleSheetName)) {
						enClassName = entry.getValue();
					}
				}
				// 获取工作表的有效行数
				int realRows = 0;
				for (int i = 0; i < sheet.getRows(); i++) {
					int nullCols = 0;
					for (int j = 0; j < sheet.getColumns(); j++) {
						Cell currentCell = sheet.getCell(j, i);
						if (currentCell == null
								|| "".equals(currentCell.getContents()
										.toString())) {
							nullCols++;
						}
					}
					if (nullCols == sheet.getColumns()) {
						break;
					} else {
						realRows++;
					}					
				}
				// 如果Excel中没有数据则提示错误
				if (realRows <= 1) {
					throw new ExcelException("Excel文件中的" + sheetName[k]
							+ "没有任何数据");
				}
				Cell[] firstRow = sheet.getRow(0);
				String[] excelFieldNames = new String[firstRow.length];
				// 获取Excel中的列名
				for (int i = 0; i < firstRow.length; i++) {
					excelFieldNames[i] = firstRow[i].getContents().toString()
							.trim();
				}
				// 判断需要的字段在Excel中是否都存在
				boolean isExist = true;
				List<String> excelFieldList = Arrays.asList(excelFieldNames);
				LinkedHashMap<String, String> enfiledMap = new LinkedHashMap<String, String>();
				// 给对象中的sheet所对应的普通字段
				for (Entry<String, LinkedHashMap<String, String>> entry : fieldMap
						.entrySet()) {
					// 获取中文字段名
					String enSheetName = entry.getKey();
					// 获取英文字段名
					if (enSheetName.equals(singleSheetName)) {
						enfiledMap = entry.getValue();
						for (String cnName : enfiledMap.keySet()) {
							if (!excelFieldList.contains(cnName)) {
								isExist = false;
								break;
							}
						}
					}
				}
				// 如果有列名不存在,则抛出异常,提示错误
				if (!isExist) {
					throw new ExcelException("Excel中缺少必要的字段,或字段名称有误");
				}
				// 将列名和列号放入Map中,这样通过列名就可以拿到列号
				LinkedHashMap<String, Integer> colMap = new LinkedHashMap<String, Integer>();
				for (int i = 0; i < excelFieldNames.length; i++) {
					colMap.put(excelFieldNames[i], firstRow[i].getColumn());
				}				
				// 给对象中的sheet所对应的确定重复字段
				for (Entry<String, String[]> fields : uniqueFields.entrySet()) {
					// 获取中文字段名
					String enSheetName = fields.getKey();
					String[] enuniqueFile=null;
					// 获取英文字段名
					if (enSheetName.equals(singleSheetName)) {
						enuniqueFile = fields.getValue();
						// 判断是否有重复行
						// 1.获取uniqueFields指定的列
						Cell[][] uniqueCells = new Cell[enuniqueFile.length][];
						for (int i = 0; i < enuniqueFile.length; i++) {
							int col = colMap.get(enuniqueFile[i]);
							uniqueCells[i] = sheet.getColumn(col);
						}
						// 2.从指定列中寻找重复行
						for (int i = 1; i < realRows; i++) {
							int nullCols = 0;
							for (int j = 0; j < enuniqueFile.length; j++) {
								String currentContent = uniqueCells[j][i].getContents();
								Cell sameCell = sheet.findCell(currentContent,
										uniqueCells[j][i].getColumn(),
										uniqueCells[j][i].getRow() + 1,
										uniqueCells[j][i].getColumn(),
										uniqueCells[j][realRows - 1].getRow(), true);
								if (sameCell != null) {
									nullCols++;
								}
							}
							if (nullCols == enuniqueFile.length) {
								throw new ExcelException("Excel中有重复行,请检查");
							}
						}
					}
				}				
				// 将sheet转换为list
				for (int i = 1; i < realRows; i++) {
					
					if (enClassName!=null) {
						// 新建要转换的对象
						T entity = (T) enClassName.newInstance();

						// 给对象中的字段赋值
						for (Entry<String, String> entry : enfiledMap.entrySet()) {
							// 获取中文字段名
							String cnNormalName = entry.getKey();
							// 获取英文字段名
							String enNormalName = entry.getValue();
							// 根据中文字段名获取列号
							int col = colMap.get(cnNormalName);

							// 获取当前单元格中的内容
							String content = sheet.getCell(col, i).getContents()
									.toString().trim();

							// 给对象赋值
							setFieldValueByName(enNormalName, content, entity);
						}
						resultList.add(entity);
					}
				}
			}			
		} catch (Exception e) {
			e.printStackTrace();
		}	
		return resultList;
	}
(2)在web的pom文件里添加相关依赖:

<dependency>  
    <groupId>com.tgb</groupId>  
    <artifactId>itoo-assess-tool</artifactId>  
    <version>0.0.1-SNAPSHOT</version>  
</dependency> 


3、配置SpringMVC

<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
<span style="white-space:pre">	</span><bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="defaultEncoding" value="UTF-8" />
		<!-- 指定所上传文件的总大小不能超过10485760000B。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
		<property name="maxUploadSize" value="10485760000"></property>
		<property name="maxInMemorySize" value="40960"></property>
	</bean>

4、上传Excel文件将并存入数据库

(1)前台Jsp代码

<a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-remove"
			plain="true" οnclick="importStudent();">导入</a>	
	<div id="studentImport" class="easyui-window" title="批量导入学生" data-options="modal:true,closed:true,"
		style="width: 700px; height: 350px; padding: 10px;">
		<form id="Manage"  method="post" enctype="multipart/form-data" action=""  novalidate>
		<a  href="${pageContext.request.contextPath}/student/leadToExcelTemplet" class="easyui-linkbutton" style="width:120px"  >点击下载模板</a>
		<br>
		 <input id="uploadExcel" name="uploadExcel" class="easyui-filebox" style="width:60%" data-options="prompt:'选择文件...'">
		  <a href="#" class="easyui-linkbutton" style="width:10%" οnclick="uploadExcel()" >导入学生</a> 
	</form>
	</div>

(2)前台js代码

	   function uploadExcel(){   
	 //得到上传文件的全路径
		 var fileName= $('#uploadExcel').filebox('getValue')		 
		 //进行基本校验
		 if(fileName==""){
			 alert("请选择上传文件!");
		 }else{
			 //对文件格式进行校验
			 var d1=/\.[^\.]+$/.exec(fileName); 
			 if(d1==".xls"){
				 $('#Manage').form('submit', {
						url : "${pageContext.request.contextPath}/student/import",
						onSubmit : function() {
							return $(this).form('validate');
						},
						success : function(result) {
							var result = eval('(' + result + ')');
							if (result.errorMsg) {
								$.messager.show({
									title : 'Error',
									msg : result.errorMsg
								});
							} else {
								$.messager
								.alert(
										"提示",
										"导入成功!",
										"info");
								$('#studentImport').dialog('close'); // close the dialog
								$('#dg').datagrid('reload'); // reload the Student data
							}
						}
					});
					
		    }else{
		    	alert("请选择xls格式文件!");
		    	$('#uploadExcel').filebox('setValue',''); 
		    }
		 }  
	  }
	//导入学生
		function importTeacehr(){
			$('#studentImport').dialog('open').dialog('setTitle', '批量导入');
			}
(3)后台Controller代码
	private ExcelUtil excelUtil;
	public ExcelUtil getExcelUtil() {
		return excelUtil;
	}
	public void setExcelUtil(ExcelUtil excelUtil) {
		this.excelUtil = excelUtil;
	}
         /**
	 * 导出excel模板
	 * @param request请求
	 * @param resposne 响应
	 * @throws UnsupportedEncodingException编码异常
	 */
	@RequestMapping("/student/leadToExcelTemplet")
	public void leadToExcelQuestionBankTemplet(HttpServletRequest request,
			HttpServletResponse response) throws UnsupportedEncodingException {
		excelUtil=new ExcelUtil();
		try {

			// excel表格的表头,map
			LinkedHashMap<String, String> fieldMap = new LinkedHashMap<String, String>();
			fieldMap.put("code","学号");
			fieldMap.put("name","姓名");
			fieldMap.put("sex","性别");
			fieldMap.put("institution", "学院");
			……
			fieldMap.put("class", "班级");
			// excel的sheetName
			String sheetName = 学生信息";

			// 导出
			excelUtil.leadToExcel(fieldMap, sheetName,
					response);
			System.out.println("导出模板成功~~~~");

		} catch (ExcelException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @MethodName : importTeacher
	 * @Description : 导入
	 * @throws Exception
	 */
	@RequestMapping("/student/import")
	public void importTeacher(
			@RequestParam("uploadExcel") CommonsMultipartFile uploadExcel,
			HttpServletResponse response, HttpServletRequest request) throws Exception {
		String result="error";
		jacksonJsonUntil =new JacksonJsonUntil();
		InputStream in;
		excelUtil=new ExcelUtil();
		boolean flag = false;
		try {
			in = uploadExcel.getInputStream();
			String sheetName = null;

			// 导入Excel前的准备工作
			LinkedHashMap<String, String> normalFieldMap = new LinkedHashMap<String, String>();
			// 1.设置Excel中字段名和类的普通属性名的对应关系,如:用户的用户名等
<pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 18px; line-height: 26px;">			fieldMap.put("code","学号");
			fieldMap.put("name","姓名");
			fieldMap.put("sex","性别");
			fieldMap.put("institution", "学院");
			……
			fieldMap.put("class", "班级");
			sheetName = "学生信息";
			String[] uniqueFields = { "学号", "姓名", "班级" };
			int error=excelUtil.importExcel(in, Teacher.class, normalFieldMap, referFieldMap,thirdFieldMap, uniqueFields, response);
		if (error==0) {
			result="success";
		}
		} catch (Exception e) {
			e.printStackTrace();
		}
		jacksonJsonUntil.beanToJson(response, result);

	}

    数据上传经验--导入Excel就分享到这里,下篇博客继续分享数据下载经验--《导出Excel》。

总结         

    从用户角度出发,以用户为主,越靠近用户的使用习惯,软件亲和力越高,开发的软件越受欢迎!


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值