POI根据XML模版读取Excel
2015-11-02 20:52
330 查看
实际开发中,总会有一些让人想象不到的需求。最近一个月都在开发这样一个需求,用户只需要excel指定单元格的数据,其他数据不做保留。至于用户用什么样的情况下才用这些数据,不是很明白(组长说你先开发出来再说,最后需要结合到别人开发的功能中去)。就这样,我就和阿瑾着手开发开发。
主要思路:
设置XML模版(指定单元格)
读取XML设置的单元格信息
POI解析指定单元格数据
将数据存入数据库
选择指定模版,然后点击上传,数据直接存入数据库中
一、XML模版
要求:
1、可以灵活的读取指定的sheet页
2、可以随意设置想要获取的单元格信息
<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?> <Excel> <sheet> <column sheet="0"> <name>column1</name> <value>14,6</value> </column> <column sheet="0"> <name>column2</name> <value>15,7</value> </column> </sheet> <sheet> <column sheet="1"> <name>column3</name> <value>28,6</value> </column> <column sheet="1"> <name>column4</name> <value>34,11</value> </column> </sheet> <sheet> <column sheet="2"> <name>column5</name> <value>8,3</value> </column> <column sheet="2"> <name>column6</name> <value>12,5</value> </column> </sheet> <sheet> <column sheet="3"> <name>column7</name> <value>8,7</value> </column> <column sheet="3"> <name>column8</name> <value>11,8</value> </column> </sheet> </Excel></span>
二、Service
注:将单元格数据保存在库中
<span style="font-size:18px;">public class ExcelUploadDaoImpl extends HibernateDaoSupport implements ExcelUploadDao { @Override public int saveExcel(String content,String tableName) { String column=""; //根据conten中有多少类生成相应的列数 String[] columnNames=content.split(","); for(int i=1;i<=columnNames.length;i++){ if(i==columnNames.length){ column+="column"+i; }else{ column+="column"+i+","; } } String sqlString="insert into "+tableName+"("+column+")values("+content+");"; int i= getSession().createSQLQuery(sqlString).executeUpdate(); System.out.println(i); return i; } }</span>
三、action
<span style="font-size:14px;">package cn.itcast.s2sh.struts2.action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import java.util.logging.Logger; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; import org.apache.commons.io.FileUtils; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.struts2.ServletActionContext; import org.apache.xmlbeans.impl.xb.xsdschema.Public; import org.aspectj.util.FileUtil; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import cn.itcast.s2sh.struts2.service.ExcelUploadService; import com.opensymphony.xwork2.ActionSupport; public class ExcelUploadAction extends ActionSupport { private ExcelUploadService excelUploadService; public ExcelUploadService getExcelUploadService() { return excelUploadService; } public void setExcelUploadService(ExcelUploadService excelUploadService) { this.excelUploadService = excelUploadService; } public String check() { return "check"; } // myFile属性用来封装上传的文件 private File myFile; // myFileContentType属性用来封装上传文件的类型 private String myFileContentType; // myFileFileName属性用来封装上传文件的文件名 private String myFileFileName; //定义表名 private String tableName; //返回回传信息 private String msgString; /** *选择自己的模版 * 0是推进表 * 1是日记录表 * 2是日记录 */ private int myTemplate; public int getMyTemplate() { return myTemplate; } public void setMyTemplate(int myTemplate) { this.myTemplate = myTemplate; } /** * 上传文件 * @return * @throws Exception */ public void add() throws Exception { HttpServletResponse response=ServletActionContext.getResponse(); response.setContentType("application/json;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); try { // ================================1、将上传的excel保存在服务器上一份======================== // 设置服务器的上传文件目录 String uploadPath = ServletActionContext.getServletContext() .getRealPath("/upload"); // 写到指定路径 File fileExcel = new File(uploadPath); // 如果指定路径不存在就创建 if (!fileExcel.exists()) { fileExcel.mkdir(); } //会将文件上传到upload外面 if (myFile != null) { File out = new File(uploadPath + myFileFileName); myFile.renameTo(out); } //基于myFile创建一个文件输入流 InputStream is = new FileInputStream(myFile); //设置上传文件名称 Date nowDate=new Date(); SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss"); String date=""; date=dateFormat.format(nowDate); String fileNameString=date+this.getMyFileFileName(); //将上传文件复制到服务器指定位置 File toFile = new File(uploadPath,fileNameString); FileUtils.copyFile(myFile,toFile); // 创建一个输出流 OutputStream os = new FileOutputStream(toFile); // ================================2、读取xml配置文件======================== // 读取XML文件 SAXReader reader = new SAXReader(); // 设置模版路径 String rootPath = ServletActionContext.getServletContext() .getRealPath("/"); String config =""; if(0==myTemplate){ tableName="advancetable"; config = rootPath + "WEB-INF\\jsp\\advanceTemplate.xml"; }else if(1==myTemplate){ tableName="dayrecordtable"; config = rootPath + "WEB-INF\\jsp\\dayRecordTableTemplate.xml"; }else{ tableName="dayrecord"; config=rootPath+"WEB-INF\\jsp\\dayRecordTemplate.xml"; } File file = new File(config); //读取服务器上的模版 Document document = reader.read(file); Element root = document.getRootElement(); List<String> contentList = new ArrayList<String>(); String value = null; String nameString = null; String valueString = null; String sheetString = null; // 读取sheet节点 List<Element> nodes = root.elements("sheet"); for (Iterator it = nodes.iterator(); it.hasNext();) { Element elm = (Element) it.next(); // 读取column节点 List<Element> elmChild = elm.elements("column"); //遍历column节点下的内容 for (Iterator childIterator = elmChild.iterator(); childIterator .hasNext();) { Element element = (Element) childIterator.next(); //column节点属性为sheet Attribute attribute = element.attribute("sheet"); //column节点下的子节点 Element nameElement = element.element("name"); Element valueElement = element.element("value"); //获取column下的节点信息 nameString = nameElement.getText(); valueString = valueElement.getText(); sheetString = attribute.getText(); value = sheetString + "," + nameString + "," + valueString; //将页名、字段列名、单元格行与列信息存储 contentList.add(value); } } // ==============================3、根据配置文件设置的模版获取Excel单元格的数据(2003和2007版)============================ //获取后缀名.xls-2003 .xlsx-2007 String fileName=myFileFileName.substring(myFileFileName.lastIndexOf(".")+1,myFileFileName.length()); int row = 0; int column = 0; String cellContentString=""; //如果上传文件为2003Excel和WPS if("xls".equals(fileName) ||"et".equals(fileName)){ HSSFWorkbook hssfWorkbook = new HSSFWorkbook(new FileInputStream( myFile)); for (int i = 0; i < contentList.size(); i++) { //获取单元格的行列信息 String valueLiString = contentList.get(i); List<String> list = new ArrayList<String>(); StringTokenizer stringTokenizer = new StringTokenizer( valueLiString, ","); while (stringTokenizer.hasMoreTokens()) { list.add(stringTokenizer.nextToken()); } //获取页的信息 int sheetIndex = Integer.parseInt(list.get(0)); HSSFSheet sheet = hssfWorkbook.getSheetAt(sheetIndex); //获取行与列的信息 row = Integer.parseInt(list.get(list.size() - 2)); column = Integer.parseInt(list.get(list.size() - 1)); //POI根据行与列获取单元格数据 HSSFRow rowValue = sheet.getRow(row); HSSFCell cellValue = rowValue.getCell((short) column); String cellContent = getStringCellValue(cellValue); //拼接获得的单元格数据 if(i==contentList.size()-1){ cellContentString+=cellContent; }else{ cellContentString=cellContentString+cellContent+","; } } }else{ //上传文件为excel-2007 XSSFWorkbook hssfWorkbook = new XSSFWorkbook(new FileInputStream( myFile)); for (int i = 0; i < contentList.size(); i++) { //获取单元格的行列信息 String valueLiString = contentList.get(i); List<String> list = new ArrayList<String>(); StringTokenizer stringTokenizer = new StringTokenizer( valueLiString, ","); while (stringTokenizer.hasMoreTokens()) { list.add(stringTokenizer.nextToken()); } //获取页的信息 int sheetIndex = Integer.parseInt(list.get(0)); XSSFSheet sheet = hssfWorkbook.getSheetAt(sheetIndex); //获取行与列的信息 row = Integer.parseInt(list.get(list.size() - 2)); column = Integer.parseInt(list.get(list.size() - 1)); //POI根据行与列获取单元格数据 XSSFRow rowValue = sheet.getRow(row); XSSFCell cellValue = rowValue.getCell((short) column); String cellContent = getStringCellValuexlxs(cellValue); //拼接获得的单元格数据 if(i==contentList.size()-1){ cellContentString+=cellContent; }else{ cellContentString=cellContentString+cellContent+","; } } } is.close(); os.close(); // ==============================4、将单元格数据写入到数据库============================ int result=excelUploadService.saveExcel(cellContentString,tableName); //判断是否成功 if(result==0){ renderText("fail"); }else{ renderText("success"); } } catch (DocumentException e) { e.printStackTrace(); } } /** * 直接输出文本,默认编码为UTF-8. */ protected void renderText(final String text) { render(text, "text/plain;charset=UTF-8"); } protected void render(final String text, final String contentType) { try { HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType(contentType); response.getWriter().write(text); } catch (IOException e) { System.out.println("出错了"); } } /** * 获取单元格数据内容为字符串类型的数据 * * @param cell * Excel单元格 * @return String 单元格数据内容 */ private String getStringCellValue(HSSFCell cell) { String strCell = ""; switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_STRING: strCell = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_NUMERIC: strCell = String.valueOf(cell.getNumericCellValue()); break; case HSSFCell.CELL_TYPE_BOOLEAN: strCell = String.valueOf(cell.getBooleanCellValue()); break; case HSSFCell.CELL_TYPE_BLANK: strCell = ""; break; default: strCell = ""; break; } if (strCell.equals("") || strCell == null) { return ""; } if (cell == null) { return ""; } return strCell; } /** * 获取单元格数据内容为字符串类型的数据 * * @param cell * Excel单元格 * @return String 单元格数据内容 */ private String getStringCellValuexlxs(XSSFCell cell) { String strCell = ""; switch (cell.getCellType()) { case XSSFCell.CELL_TYPE_STRING: strCell = cell.getStringCellValue(); break; case XSSFCell.CELL_TYPE_NUMERIC: strCell = String.valueOf(cell.getNumericCellValue()); break; case XSSFCell.CELL_TYPE_BOOLEAN: strCell = String.valueOf(cell.getBooleanCellValue()); break; case XSSFCell.CELL_TYPE_BLANK: strCell = ""; break; default: strCell = ""; break; } if (strCell.equals("") || strCell == null) { return ""; } if (cell == null) { return ""; } return strCell; } public File getMyFile() { return myFile; } public void setMyFile(File myFile) { this.myFile = myFile; } public String getMyFileContentType() { return myFileContentType; } public void setMyFileContentType(String myFileContentType) { this.myFileContentType = myFileContentType; } public String getMyFileFileName() { return myFileFileName; } public void setMyFileFileName(String myFileFileName) { this.myFileFileName = myFileFileName; } public String getMsgString() { return msgString; } public void setMsgString(String msgString) { this.msgString = msgString; } }</span>
四、Jsp
<span style="font-size:18px;"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="${pageContext.request.contextPath}/jquery/jquery-2.1.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/jquery/jquery-form.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/jquery/jquery-2.1.1.min.js"></script> </head> <body> <form name="frmfile" id="frmfile" enctype="multipart/form-data" action="excelUpload_add.action" method="post"> <input type="hidden" name="result" value=""> <div style="margin: 0px 40px; width: 550px;"> <div> <label>选择模版:</label> <s:select name="myTemplate" list="#{0:'推进表',1:'日报表',2:'日报'}"> </s:select> </div> <fieldset style="margin: 0px auto; width: 500px;"> <legend>上传文件</legend> <table border="0" cellpadding="0" cellspacing="0" style="width: 100%;"> <tr> <td valign="bottom"><input type="file" id="files" name="myFile" class="files"> <input type="hidden" name="fileNames" value=""> <input id="buttionUpload" name="buttionUpload" value="上传" type="button" style="float: right; _padding: 2px 4px;" onClick="doUpload()" /></br> <label id="showInfo" name="showInfo"><font color="red"></font> </label> </td> </tr> </table> </fieldset> </div> <!-- <iframe name='hidden_frame' id="hidden_frame" style='display: none'></iframe> --> </form> </body> </html> <script type="text/javascript"> function doUpload() { document.getElementById("showInfo").style.color="red"; document.getElementById("showInfo").innerHTML="正在上传!!!!"; //调用后台,将excel传到action $('#frmfile').ajaxSubmit( function(msg) { if (msg == "success") { submitFlag = false; submitFlag2 = false; document.getElementById("showInfo").innerHTML="成功上传文件!!"; }else{ document.getElementById("showInfo").innerHTML="上传文件失败,请联系管理员!!"; } }); } </script></span>
注:使用$ajax无法实现对上传文件的回调,建议使用ajaxSubmint或者ajaxFrom,两种都可以实现
总结:
虽然这个Demo比较粗糙,但是核心功能都已经开发完了,POI根据解析的XML读取Excel。开发前组长说了一下这个需求,但是实际应用中没有清晰的告诉我们,导致后面继续开发时,出现很多不合理的地方。比如说,用户不是取几个单元的数据,而是好几十个,到现在的200来个。更无奈的是,用户还想再加几百个单元格,当时我就果断回绝了,这种思路根本不适合取大量的单元格数据。一是取的时候太浪费人力物力;二是,存入数据库也会出现混乱。做什么事情的时候还是要好好考虑这个东西是不是合理,是否具有可行性,否则后果不堪设想。
相关文章推荐
- java面试题总结
- java char基本数据类型
- 关于SQL Server 2014的数据库连接问题
- 事务四大特征:原子性,一致性,隔离性和持久性(ACID)
- win7系统IE浏览器重置的操作方法
- Mysql
- zf-删除重复数据只保留一条(转)
- C/C++中的内存补齐机制(2)
- Objective-C中的Protocol
- 阶乘之和
- 装饰者模式输入
- java学习笔记(1)-----关于interface
- C++学习——构造函数初始化列表
- 内存管理文章(1)
- 股神的十个境界 你达到了第几级?
- eclipse scm url下拉为空
- 《大道至简》第五章读后感
- 随机数数组 框图输出
- Objective-C之Category的使用
- HTTP长连接和短连接原理浅析