Poi 读写Excel 合并ExcelSheet Struts2实现
网上有许多人在找这样的例子,有多个Excel,要把他们合并到一个Excel里面,这里涉及无非是Excel的读取和Sheet的合并。
我做了这样一个实现,可以参考,当然更希望指点。使用Struts实现他的上传功能,在把多个Excel上传到Action后,进行合并,然后直接执行下载。也就是说,我们一个Action里要动用Struts2的上传和下载两个功能。
实现的步骤:
1.拷贝Struts的包到工程(估计都会吧,Ctrl+C 加 Ctrl + V)
2.在Web.xml里配置Struts2,也不难
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
3.定义Struts2的配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!-- 一些基本配置,自己看着办 --> <constant name="struts.devMode" value="false"></constant> <constant name="struts.i18n.reload" value="true"></constant> <constant name="struts.i18n.encoding" value="UTF-8"></constant> <constant name="struts.multipart.saveDir" value="C:\\"></constant> <constant name="struts.multipart.maxSize" value="20971520"></constant> <package name="default" namespace="/" extends="struts-default"> <action name="doUpload" class="com.golden.action.StrutsFileUpload"> <result name="success" type="stream"> <param name="contentType"> application/vnd.ms-excel </param> <param name="contentDisposition"> attachment;filename="TEST.xls" </param> <param name="inputName">downLoadStream</param> <param name="bufferSize">4096</param> </result> </action> </package> </struts>
注意:
contentType:要设置为下载类型为Excel,当然这些可以在Actoin里动态定义,想实现的具体再说。
contentDisposition:里面千万不要忘了attachment;不然可能会出一些问题,当然也许有的人不写。后面是下载的文件名,也可以在Action里定义。
inputName:真正执行下载的方法
bufferSize:缓冲区大小
3.写一个上传页面
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>多文件Excel分析</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <center> <s:form action="doUpload" method="POST" enctype="multipart/form-data"> <s:file name="upload" label="上传的文件1" /> <s:file name="upload" label="上传的文件2" /> <s:file name="upload" label="上传的文件3" /> <s:file name="upload" label="上传的文件4" /> <s:file name="upload" label="上传的文件5" /> <s:file name="upload" label="上传的文件6" /> <s:submit value="上 传"/> </s:form> </center> </body> </html>
注意:
里面使用了Struts2的标签,也可以直接使用Html标签
4.最关键的部分,写Action的类
package com.golden.action; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import com.opensymphony.xwork2.ActionSupport; import java.math.*; import java.text.NumberFormat; @SuppressWarnings("serial") public class StrutsFileUpload extends ActionSupport { private File[] upload;// 实际上传文件 private String[] uploadContentType; // 文件的内容类型 private String[] uploadFileName; // 上传文件名 /** * 请求的Action */ @Override public String execute() throws Exception { return "success"; } /** * 真正的下载方法 * * @return * @throws Exception */ @SuppressWarnings("deprecation") public InputStream getDownLoadStream() throws Exception { HSSFWorkbook wb = new HSSFWorkbook(); // 设置一个靠右排放样式,如果需要其他样式自可以再定义一些 HSSFCellStyle style = wb.createCellStyle(); // style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); style.setAlignment(HSSFCellStyle.ALIGN_RIGHT); // 在单元格中右排放 try { for (int i = 0; i < upload.length; i++) { File f = upload[i]; // 取得一个文件 FileInputStream is = new FileInputStream(f); HSSFWorkbook wbs = new HSSFWorkbook(is); // 根据读出的Excel,创建Sheet HSSFSheet sheet = wb.createSheet(uploadFileName[i]); // 一直取的是第一个Sheet,一定要注意,如果你要读取所有的Sheet,循环读取即可 HSSFSheet childSheet = wbs.getSheetAt(0); // 循环读取Excel的行 for (int j = 0; j < childSheet.getLastRowNum(); j++) { // 根据读取的行,创建要合并Sheet的行 HSSFRow r = sheet.createRow(j); HSSFRow row = childSheet.getRow(j); // 判断是否为空,因为可能出现空行的情况 if (null != row) { // 循环读取列 for (int k = 0; k < row.getLastCellNum(); k++) { // 根据读取的列,创建列 HSSFCell c = r.createCell(k); HSSFCell cell = row.getCell(k); // 将值和样式一同赋值给单元格 String value = ""; if (null != cell) { switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 数值型 if (HSSFDateUtil.isCellDateFormatted(cell)) { // 如果是Date类型则 ,获取该Cell的Date值 value = HSSFDateUtil.getJavaDate( cell.getNumericCellValue()) .toString(); } else {// 纯数字,这里要判断是否为小数的情况,因为整数在写入时会被加上小数点 String t = cell.getNumericCellValue() + ""; BigDecimal n = new BigDecimal(cell .getNumericCellValue()); // 判断是否有小数点 if (t.indexOf(".") < 0) { value = n.intValue() + ""; } else { // 数字格式化对象 NumberFormat nf = NumberFormat .getInstance(); // 小数点最大两位 nf.setMaximumFractionDigits(2); // 执行格式化 value = nf.format(n.doubleValue()); } } break; case HSSFCell.CELL_TYPE_STRING: // 字符串型 value = cell.getRichStringCellValue() .toString(); break; case HSSFCell.CELL_TYPE_FORMULA:// 公式型 // 读公式计算值 value = String.valueOf(cell .getNumericCellValue()); break; case HSSFCell.CELL_TYPE_BOOLEAN:// 布尔 value = " " + cell.getBooleanCellValue(); break; /* 此行表示该单元格值为空 */ case HSSFCell.CELL_TYPE_BLANK: // 空值 value = " "; break; case HSSFCell.CELL_TYPE_ERROR: // 故障 value = " "; break; default: value = cell.getRichStringCellValue() .toString(); } } else { value = " "; } c.setCellValue(value); c.setCellStyle(style); } } else { HSSFCell c = r.createCell(0); c.setCellValue(" "); } } } } catch (Exception e) { e.printStackTrace(); } // 这种写法不会产生临时文件,因为这里使用字节数组作为介质 ByteArrayOutputStream os = new ByteArrayOutputStream(); wb.write(os); byte[] content = os.toByteArray(); InputStream is = new ByteArrayInputStream(content); return is; } public File[] getUpload() { return upload; } public void setUpload(File[] upload) { this.upload = upload; } public String[] getUploadContentType() { return uploadContentType; } public void setUploadContentType(String[] uploadContentType) { this.uploadContentType = uploadContentType; } public String[] getUploadFileName() { return uploadFileName; } public void setUploadFileName(String[] uploadFileName) { this.uploadFileName = uploadFileName; } }
这里要关注的地方太多,具体的代码里注释写的很清楚。
一定要注意的是要判断单元格的类型,特别是数字类型时,我根据自己的需求一定了一些处理。
请您到ITEYE看我的原创:http://cuisuqiang.iteye.com
或支持我的个人博客,地址:http://www.javacui.com
上一篇: ios之导航渐变---/导航透明
下一篇: JavaScript睡眠函数代码实例讲解