Poi 读写Excel 合并ExcelSheet Struts2实现
网上有许多人在找这样的例子,有多个Excel,要把他们合并到一个Excel里面,这里涉及无非是Excel的读取和Sheet的合并。
我做了这样一个实现,可以参考,当然更希望指点。使用Struts实现他的上传功能,在把多个Excel上传到Action后,进行合并,然后直接执行下载。也就是说,我们一个Action里要动用Struts2的上传和下载两个功能。
实现的步骤:
1.拷贝Struts的包到工程(估计都会吧,Ctrl+C 加 Ctrl + V)
2.在Web.xml里配置Struts2,也不难
Xml代码??
- <?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代码??
- <?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.写一个上传页面
Html代码??
- <%@?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的类
Java代码??
- 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;??
- ????}??
- ??
- }??
?
?这里要关注的地方太多,具体的代码里注释写的很清楚。
一定要注意的是要判断单元格的类型,特别是数字类型时,我根据自己的需求一定了一些处理。