Jakarta POI 是一套用于访问微软格式文档的Java API。
Jakarta POI有很多组件组成,其中有用于操作Excel格式文件的HSSF和用于早在Word的HWPF,在各种组件中目前只有用于操作Excel的HSSF相对成熟。它的官方首页是:http://jakarta.apache.org/poi/hssf/index.html,这里可以下载到它的最新版本和文档。
下面就来看看如何通过Jakarta POI的HSSF操作Excel文件。
操作Excel文件的步骤同JXL类似(关于如何用JXL操作Excel可以看我的另外两篇文章)。
HSSF对Excel的操作主要是通过下面几个对象实现:
HSSFWorkbook 工作簿对象对应于Excel文件
HSSFSheet Sheet对象对应于Excel中的Sheet
HSSFRow 行对象表示Sheet中的一行(这个对象在JXL中并没有提供)
HSSFCell 单元格对象
操作步骤就是用HSSFWorkbook打开或者创建“Excel文件对象”,用HSSFWorkbook 对象返回或者创建Sheet对象,用Sheet对象返回行对象,用行对象得到Cell对象,有了Cell对象就随你读写了。下面来看一个动态生成 Excel文件的例子:
//创建HSSFWorkbook对象
HSSFWorkbook wb = new HSSFWorkbook();
//创建HSSFSheet对象
HSSFSheet sheet = wb.createSheet("sheet0");
//创建HSSFRow对象
HSSFRow row = sheet.createRow((short)0);
//创建HSSFCell对象
HSSFCell cell=row.createCell((short)0);
//用来处理中文问题
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
//设置单元格的值
cell.setCellValue("单元格中的中文");
//定义你需要的输出流
OutputStream out = new FileOutputStream("viwo.xls");
//输出Excel
wb.write(out);
out.flush();
HSSF读取文件同样还是使用这几个对象,只是把相应的createXXX方法变成了getXXX方法即可。
只要理解了其中原理,不管是读还是写亦或是特定格式都可以轻松实现,正所谓知其然更要知其所以然。
最后附上HSSF官方的QuickGuide:《Busy Developers' Guide to HSSF Features》,虽然是英文的但还是很容易理解的。
http://jakarta.apache.org/poi/hssf/quick-guide.html
到此Java操作Excel文章系列就结束了,下一篇会介绍如何使用JFreeChart生成各种图。
poi来创建excel的小例子:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page import="org.apache.poi.hssf.usermodel.*,java.io.*" %>
<%
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>My JSP 'poiExcel.jsp' starting page</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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page. <br>
<%
//创建新的Excel工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
//在excel中新建一个工作表,起名字为jsp
HSSFSheet sheet = workbook.createSheet("JSP");
//创建第一行
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("编辑");
//文件存放位置
String filename = application.getRealPath("/")+"test.xls";
//新建一输出流
FileOutputStream fout = new FileOutputStream(filename);
//存盘
workbook.write(fout);
fout.flush();
//结束关闭
fout.close();
out.println("excel 文件生成,存放在<br>"+filename);
%>
</body>
</html>
下面是利用poi来读取excel的小例子:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="org.apache.poi.hssf.usermodel.*,java.io.*" %>
<%
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>My JSP 'readExcel.jsp' starting page</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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page. <br>
<%
//读取excel
String filename = application.getRealPath("/")+"test.xls";
HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filename));
//按名引用excel工作表
HSSFSheet sheet = workbook.getSheet("JSP");
//也可以用以下方式来获取excel的工作表,采用工作表的索引值
//HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(0);
HSSFCell cell = row.getCell((short)0);
//打印读取值
out.println(cell.getStringCellValue()+" ");
cell = row.getCell((short)1);
out.println(cell.getStringCellValue()+" ");
%>
</body>
</html>
JXL(Java Excel API)是一个用来动态读写Excel文件的开源框架,利用它可以在任何支持Java的操作系统上动态读写Excel文件。JXL的主页是:http://www.andykhan.com/jexcelapi/,可以在这里下载到它的最新的版本。
你可以分别通过如下命令
java -jar jxl.jar -xml test.xls
java -jar jxl.jar -cvs test.xls
以xml和cvs格式查看test.xls,这是因为JXL作者实现了一个用来演示的jxl.demo.Demo的类。
当然我们使用JXL主要是用它来动态读写Excel文件。现在就来看看JXL在对Excel的读和写上都提供了那些支持。
先来看看Excel文件中都有写上面对象
1 文件对象 2工作簿对象 3 单元格对象。
相应的在JXL中就有Workbook,Sheet ,Cell 。通过这三个对象我们就可以实现Excel文件的读取工作。
我们先想想一下读取步骤,不管是什么样的Excel操作框架必定都要经历
1选取Excel文件,2选择工作簿,3选择Cell,4读取信息。
那么现在就可以看看JXL中这四步骤如何体现:
//通过Workbook的静态方法getWorkbook选取Excel文件
Workbook workbook = Workbook.getWorkbook(new File("myfile.xls"));
//通过Workbook的getSheet方法选择第一个工作簿(从0开始)
Sheet sheet = workbook.getSheet(0);
//通过Sheet方法的getCell方法选择位置为C2的单元格(两个参数都从0开始)
Cell c2 = sheet.getCell(2,1);
//通过Cell的getContents方法把单元格中的信息以字符的形式读取出来
String stringc2 = c2.getContents();
可以看到正是刚才所说的四个步骤。
我们都知道Excel单元格是有格式的,那么这些信息如何取得。
Cell提供了一个getType方法能够返回单元格的类型信息,同时JXL提供了一个CellType类用来预设Excel中的类型信息,而且JXL提供了一些Cell类的子类用来分别用来表示各种类型的单元格,如LabelCell,NumberCell,DateCell分别表示字符、数值、日期类型的单元格。所以我们可以这样写:
if (c2.getType() == CellType.NUMBER)
{
NumberCell nc = (NumberCell) c2;
numberb2 = nc.getValue();
}
最后不要忘记关闭workbook以释放资源:
workbook.close();
现在总结一下:三个对象,四个步骤,注意格式。就可以轻松的从Excel文件中读取数据。
Java操作Excel之理解JXL--读取Excel模板动态写入数据并生成Excel
现在来看看如何读取Excel模板然后把动态数据写入到模板以生成特定格式的Excel。
同样的思路,先来考虑下会涉及到那些对象,和上篇文章读取相比这里涉及到一个写入的步骤,所以JXL必然会提供一个对象
来支持写入,这就是WritableWorkbook。那么如何得到到这个类的实例,查看APIDoc发现Workbook类提供了几个
静态的createWorkbook方法返回WritableWorkbook实例,可以看到众多createWorkbook方法主要分为两类:一个参数
和两个参数。简单分析可以得知前者仅仅是用来直接生成Excel文件,后者先读取模板再向模板写入数据然后生成Excel。
(还有一个三参数方法加上一个用来设置workbook的参数)
现在按照上篇文章中所讲述的流程来看看读取模板并写入需要那些步骤。
第一步:选择模板文件:
Workbook wb = Workbook.getWorkbook(new File(realpath));
第二步:通过模板得到一个可写的Workbook:
WritableWorkbook wwb = Workbook.createWorkbook(targetFile, wb);
第一个参数是一个输出流对象,比如可以
ByteArrayOutputStream targetFile = new ByteArrayOutputStream();
这样定义这个输出流对象。第二个参数代表了要读取的模板。
第三步:选择模板中名称为StateResult的Sheet:
WritableSheet wws = wwb.getSheet("StateResult");
如果需要也可以创建Sheet
WritableSheet wws = wwb.createSheet("Sheet名称",i);
第四步:选择单元格,写入动态值,根据单元格的不同类型转换成相应类型的单元格:
Label A1 = (Label)wws.getWritableCell(0,0);
A1.setString("单元格内容")
或
Number A2 = (Number)wws.getWritableCell(0,1);//Number是jxl.write.Number
A2.setValue(3.3);
也可以创建新的单元格并且加入到Sheet中
Label C1 = new Label(2,0,"单元格内容");
wws.addCell(C1);
或
Number C1 = new Number(2,0,3.3);
wws.addCell(C1);
在生成Excel报表的时候还会遇到一种需求就是数据的格式问题,我们可能希望数值型单元格以某种格式显示,而字符串型单元格以另
一种格式显示。这些可以通过WritableFont、NumberFormat、WritableCellFormat等实现,下例给单元格A1、A2添加了不同的格式。
还有不要忘记关闭WritableWorkbook和Workbook以释放资源:
wwb.close();
wb.close();
最后就可以你需要的方式从输出流targetFile中取得Excel,比如直接生成文件存本地,输出到客户端浏览器等。
如果还有其他需求,按照这种思路,再参照APIDoc相信可以很容易的解决。
至此,Java操作Excel之理解JXL就写完了。
我在项目中实际使用的代码如下:
@SuppressWarnings({ "unchecked", "deprecation" })
public void getRyzgExcel(String filename) throws IOException {
System.out.println("FileName:"+filename);
List list = ryzgDao.getRyzgList();
System.out.println("list.size:"+list.size());
// HSSFWorkbook、HSSFSheet、HSSFRow、HSSFCell,分别代表了Excel电子表格中的Book、Sheet、行和单元格
HSSFWorkbook workbook = new HSSFWorkbook(); //创建新的Excel工作簿
HSSFSheet sheet = workbook.createSheet("人员资格信息");//在excel中新建一个工作表,起名字
HSSFRow row =sheet.createRow(0);//创建第一行
HSSFCell cellt = row.createCell((short)0);//创建第一列
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);//定义单元格为字符串类型
cellt.setCellValue("资格证号");//在单元格中输入一些内容
cellt = row.createCell((short)1);
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);
cellt.setCellValue("截止日期");
cellt = row.createCell((short)2);
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);
cellt.setCellValue("类型");
cellt = row.createCell((short)3);
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);
cellt.setCellValue("姓名");
cellt = row.createCell((short)4);
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);
cellt.setCellValue("电话");
cellt = row.createCell((short)5);
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);
cellt.setCellValue("身份证号");
cellt = row.createCell((short)6);
cellt.setEncoding(HSSFCell.ENCODING_UTF_16);
cellt.setCellValue("性别 ");
RyzgInfo info ;
for (int i=0; i<list.size(); i++){//循环数据a.zgzh,a.zgjz,a.zglx,b.xmin,b.lxdh,b.sfzh,b.xbie
info = new RyzgInfo();
info = (RyzgInfo) list.get(i);
HSSFRow row2 =sheet.createRow(i+1);//创建行
HSSFCell cell = row.createCell((short)0);//创建列
cell.setEncoding(HSSFCell.ENCODING_UTF_16);//定义单元格为字符串类型
cell.setCellValue(info.getZgzh());//在单元格中输入一些内容//资格证号
cell = row2.createCell((short)1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(DateUtil.formatUtilDate(info.getZgjz()));//截止日期
cell = row2.createCell((short)2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
String lx="";
if(info.getZglx()==281)
lx="危险货物运输装卸员";
else if(info.getZglx()==282)
lx="危险货物运输押运员";
else if(info.getZglx()==292 || info.getZglx()==294)
lx="危险货物运输驾驶员";
cell.setCellValue(lx);//类型
cell = row2.createCell((short)3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(info.getXmin());//姓名
cell = row2.createCell((short)4);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(info.getLxdh());//电话
cell = row2.createCell((short)5);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(info.getSfzh());//身份证号
cell = row2.createCell((short)6);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(info.getXbie()==0?"男":"女");//性别
}
//新建一输出流
FileOutputStream fout = new FileOutputStream(filename);
//存盘
workbook.write(fout);
fout.flush();
//结束关闭
fout.close();
System.out.println("excel 文件生成,存放在<br>"+filename);
}