akarta 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>
Java操作Excel之理解JXL--讀取Excel
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添加了不同的格式。
- WritableFont font= new WritableFont(WritableFont.createFont("宋體"),10,WritableFont.NO_BOLD);
- NumberFormat format = new NumberFormat("###,##0.00"); //NumberFormat是jxl.write.NumberFormat
- WritableCellFormat cellFormat1 = new WritableCellFormat(font,format);
- WritableCellFormat cellFormat2 = new WritableCellFormat(font);
- cellFormat1.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN); //Border是jxl.format.Border
- cellFormat2.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN); //Border是jxl.format.Border
- A2.setCellFormat(cellFormat1);
- A1.setCellFormat(cellFormat2);
還有不要忘記關閉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);
}