一.POI 简介
Jakarta POI 是apache的子项目,目标是处理ole2对象。它提供了一组操纵Windows文档的Java API
目前比较成熟的是HSSF接口,处理MS Excel(97-2002)对象。它不象我们仅仅是用csv生成的没有格式的可以由Excel转换的东西,而是真正的Excel对象,你可以控制一些属性如sheet,cell等等。
二.HSSF概况
HSSF 是Horrible SpreadSheet Format的缩写,也即“讨厌的电子表格格式”。 也许HSSF的名字有点滑稽,就本质而言它是一个非常严肃、正规的API。通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。
HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”。前者很好理解,后者比较抽象,但操作效率要高得多。
三.开始编码
可以到 http://www.apache.org/dyn/closer.cgi/jakarta/poi / 最新的POI 工具包
HSSFWorkbook excell 文档对象介绍
HSSFSheet excell的表单
HSSFRow excell的行
HSSFCell excell的格子单元
HSSFFont excell字体
HSSFName 名称
HSSFDataFormat 日期格式
在poi1.7中才有以下2项:
HSSFHeader sheet头
HSSFFooter sheet尾
和这个样式
HSSFCellStyle cell样式
辅助操作包括
HSSFDateUtil 日期
HSSFPrintSetup 打印
HSSFErrorConstants 错误信息表
(以上部分转自http://ltc603.iteye.com/blog/30184)
在我们在Service编写操作如下:
package com.mengya.service.imple;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.commons.lang.RandomStringUtils;
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 com.mengya.dao.UsersDaoInter;
import com.mengya.entity.Users;
import com.mengya.service.UsersServiceInter;
public class UsersService implements UsersServiceInter {
private UsersDaoInter usersdao = null;
public void setUsersdao(UsersDaoInter usersdao) {
this.usersdao = usersdao;
}
@SuppressWarnings("unchecked")
public InputStream exportUsers() {
// 创建一个HSSFWorkbook
HSSFWorkbook wb = new HSSFWorkbook();
// 由HSSFWorkbook创建一个HSSFSheet
HSSFSheet sheet = wb.createSheet();
// 由HSSFSheet创建HSSFRow
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("序号");
cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("姓");
cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("名字");
cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("年龄");
List<Users> userList = this.findAll();
for (int i = 0; i < userList.size(); i++) {
Users user = userList.get(i);
row = sheet.createRow(i + 1);
cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(i+1);
cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getUfristName());
cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getUlastName());
cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getUage());
}
//方法一:生成xls文件到硬盘上,然后再删除该文件(启动一个线程或Servlet启动时删除)
//自己的方法产生随机的字符串作为文件名
//参见(http://zmx.iteye.com/admin/blogs/477460)
//String fileName=RandomFileName2.getRandomString(10);
//使用apache的commons-lang.jar产生随机的字符串作为文件名
String fileName=RandomStringUtils.randomAlphanumeric(10);
//生成xls文件名必须要是随机的,确保每个线程访问都产生不同的文件
StringBuffer sb=new StringBuffer(fileName);
final File file = new File(sb.append(".xls").toString());
try {
OutputStream os=new FileOutputStream(file);
try {
wb.write(os);
os.close();
} catch (IOException e) {
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
InputStream is=null;
try {
is=new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//生成一个线程,splee15秒删除该文件
new Thread(new Runnable(){
public void run() {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
file.delete();
}
}).start();
return is;
}
}
对于上面的方法如果服务器停止可能导致有些文件没有删除可能会越来越多,对于tomcat该文件放在tomcat的bin目录中。故我们可以用一个Servlet在服务器启动时删除这些垃圾文件。Servlet如下:
/**
* 服务器启动时清除服务器中的垃圾文件
*
* @author 张明学
*
*/
@SuppressWarnings("serial")
public class DeleteExlFileServlet extends HttpServlet {
public void destroy() {
super.destroy();
}
public void init() throws ServletException {
/**第一种方式删除
* File file = new File(".");对于tomcat得到的是bin目录
File file = new File(".");
File[] subFiles = file.listFiles();
for (File f : subFiles) {
if (f.getName().endsWith(".xls")) {
f.delete();
}
}
**/
File file = new File(".");
File[] subFiles = file.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".xls")) {
return true;
}
return false;
}
});
for (File f : subFiles) {
f.delete();
}
}
}
该Servlet在web.xml中配置如下:
<!-- 该serlvet不需用户访问服务启时执行init就可以了-->
<servlet>
<description>服务器启动时删除服务器中的垃圾文件</description>
<servlet-name>DeleteExlFileServlet</servlet-name>
<servlet-class>
com.mengya.servlet.DeleteExlFileServlet
</servlet-class>
<!-- 指定服务器启动时执行的次序 -->
<load-on-startup>10</load-on-startup>
</servlet>
action中调用该service:
@SuppressWarnings("serial")
public class ExportUsersAction extends ActionSupport {
private UsersServiceInter userService;
public void setUserService(UsersServiceInter userService) {
this.userService = userService;
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
public InputStream getDownloadFile
() {
return userService.exportUsers();
}
}
struts.xml中的配置如下:
<!-- 将用户信息用Excel导出 -->
<action name="exportUsers" class="exportUsersAction">
<result name="success" type="stream">
<!-- 指定文件下载类型 -->
<param name="contentType">application/vnd.ms-excel</param>
<!-- 对于第一个参数默认值为inline这样的话若在线打开的话会生成两个xls文件 -->
<param name="contentDisposition">attachment;filename="allUsers.xls"</param>
<param name="inputName">downloadFile
</param>
</result>
</action>
到些第一种方法就写完了,还有一种方法可以不生成Excel文件而是返回一个该xls文件的InputStream
Service中的方法如下:
import java.util.List;
import org.apache.commons.io.output.ByteArrayOutputStream;
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 com.mengya.dao.UsersDaoInter;
import com.mengya.entity.Users;
import com.mengya.service.UsersServiceInter;
public class UsersService implements UsersServiceInter {
private UsersDaoInter usersdao = null;
public void setUsersdao(UsersDaoInter usersdao) {
this.usersdao = usersdao;
}
@SuppressWarnings("unchecked")
public InputStream exportUsers() {
// 创建一个HSSFWorkbook
HSSFWorkbook wb = new HSSFWorkbook();
// 由HSSFWorkbook创建一个HSSFSheet
HSSFSheet sheet = wb.createSheet();
// 由HSSFSheet创建HSSFRow
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("序号");
cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("姓");
cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("名字");
cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("年龄");
List<Users> userList = this.findAll();
for (int i = 0; i < userList.size(); i++) {
Users user = userList.get(i);
row = sheet.createRow(i + 1);
cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(i+1);
cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getUfristName());
cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getUlastName());
cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getUage());
}
/**
* 方法二:在内存中返回该InputStream,不生成文件到硬盘上
*/
ByteArrayOutputStream os=new ByteArrayOutputStream();
try {
wb.write(os);
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes=os.toByteArray();
InputStream is=new ByteArrayInputStream(bytes);
return is;
}
}
action中的调用和struts.xml中配置同上面的一样。