天天看點

hssfcolor 不建議使用_POI導出Excel經典實作

POI導出EXCEL經典實作

在web開發中,有一個經典的功能,就是資料的導入導出。特别是資料的導出,在生産管理或者财務系統中用的非常普遍,因為這些系統經常要做一些報表列印的工作。而資料導出的格式一般是EXCEL或者PDF,我這裡就用兩篇文章分别給大家介紹下。(注意,我們這裡說的資料導出可不是資料庫中的資料導出!麼誤會啦^_^)

呵呵,首先我們來導出EXCEL格式的檔案吧。現在主流的操作Excel檔案的開源工具有很多,用得比較多的就是Apache的POI及JExcelAPI。這裡我們用Apache POI!我們先去Apache的大學營下載下傳POI的jar包:http://poi.apache.org/ ,我這裡使用的是3.0.2版本。

将3個jar包導入到classpath下,什麼?忘了怎麼導包?不會吧!好,我們來寫一個導出Excel的實用類(所謂實用,是指基本不用怎麼修改就可以在實際項目中直接使用的!)。我一直強調做類也好,做方法也好,一定要通用性和靈活性強。下面這個類就算基本貫徹了我的這種思想。那麼,熟悉許老師風格的人應該知道,這時候該要甩出一長串代碼了。沒錯,大夥請看:

package org.leno.export.util;

import java.util.Date;

public class Student {

private long id;

private String name;

private int age;

private boolean sex;

private Date birthday;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(long id, String name, int age, boolean sex, Date birthday) {

super();

this.id = id;

this.name = name;

this.age = age;

this.sex = sex;

this.birthday = birthday;

}

public long getId() {

return id;

}

public void setId(long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public boolean getSex() {

return sex;

}

public void setSex(boolean sex) {

this.sex = sex;

}

public Date getBirthday() {

return birthday;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

}

package org.leno.export.util;

public class Book {

private int bookId;

private String name;

private String author;

private float price;

private String isbn;

private String pubName;

private byte[] preface;

public Book() {

super();

}

public Book(int bookId, String name, String author, float price,

String isbn, String pubName, byte[] preface) {

super();

this.bookId = bookId;

this.name = name;

this.author = author;

this.price = price;

this.isbn = isbn;

this.pubName = pubName;

this.preface = preface;

}

public int getBookId() {

return bookId;

}

public void setBookId(int bookId) {

this.bookId = bookId;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAuthor() {

return author;

}

public void setAuthor(String author) {

this.author = author;

}

public float getPrice() {

return price;

}

public void setPrice(float price) {

this.price = price;

}

public String getIsbn() {

return isbn;

}

public void setIsbn(String isbn) {

this.isbn = isbn;

}

public String getPubName() {

return pubName;

}

public void setPubName(String pubName) {

this.pubName = pubName;

}

public byte[] getPreface() {

return preface;

}

public void setPreface(byte[] preface) {

this.preface = preface;

}

}

上面這兩個類一目了然,就是兩個簡單的javabean風格的類。再看下面真正的重點類:

package org.leno.export.util;

import java.io.*;

import java.lang.reflect.*;

import java.util.*;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import java.text.SimpleDateFormat;

import javax.swing.JOptionPane;

import org.apache.poi.hssf.usermodel.*;

import org.apache.poi.hssf.util.HSSFColor;

public class ExportExcel {

public void exportExcel(Collection dataset, OutputStream out) {

exportExcel("測試POI導出EXCEL文檔", null, dataset, out, "yyyy-MM-dd");

}

public void exportExcel(String[] headers, Collection dataset,

OutputStream out) {

exportExcel("測試POI導出EXCEL文檔", headers, dataset, out, "yyyy-MM-dd");

}

public void exportExcel(String[] headers, Collection dataset,

OutputStream out, String pattern) {

exportExcel("測試POI導出EXCEL文檔", headers, dataset, out, pattern);

}

@SuppressWarnings("unchecked")

public void exportExcel(String title, String[] headers,

Collection dataset, OutputStream out, String pattern) {

// 聲明一個工作薄

HSSFWorkbook workbook = new HSSFWorkbook();

// 生成一個表格

HSSFSheet sheet = workbook.createSheet(title);

// 設定表格預設列寬度為15個位元組

sheet.setDefaultColumnWidth((short) 15);

// 生成一個樣式

HSSFCellStyle style = workbook.createCellStyle();

// 設定這些樣式

style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);

style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

style.setBorderBottom(HSSFCellStyle.BORDER_THIN);

style.setBorderLeft(HSSFCellStyle.BORDER_THIN);

style.setBorderRight(HSSFCellStyle.BORDER_THIN);

style.setBorderTop(HSSFCellStyle.BORDER_THIN);

style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

// 生成一個字型

HSSFFont font = workbook.createFont();

font.setColor(HSSFColor.VIOLET.index);

font.setFontHeightInPoints((short) 12);

font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

// 把字型應用到目前的樣式

style.setFont(font);

// 生成并設定另一個樣式

HSSFCellStyle style2 = workbook.createCellStyle();

style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);

style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);

style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);

style2.setBorderRight(HSSFCellStyle.BORDER_THIN);

style2.setBorderTop(HSSFCellStyle.BORDER_THIN);

style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);

style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

// 生成另一個字型

HSSFFont font2 = workbook.createFont();

font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);

// 把字型應用到目前的樣式

style2.setFont(font2);

// 聲明一個畫圖的頂級管理器

HSSFPatriarch patriarch = sheet.createDrawingPatriarch();

// 定義注釋的大小和位置,詳見文檔

HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));

// 設定注釋内容

comment.setString(new HSSFRichTextString("可以在POI中添加注釋!"));

// 設定注釋作者,當滑鼠移動到單元格上是可以在狀态欄中看到該内容.

comment.setAuthor("leno");

//産生表格标題行

HSSFRow row = sheet.createRow(0);

for (short i = 0; i < headers.length; i++) {

HSSFCell cell = row.createCell(i);

cell.setCellStyle(style);

HSSFRichTextString text = new HSSFRichTextString(headers[i]);

cell.setCellValue(text);

}

//周遊集合資料,産生資料行

Iterator it = dataset.iterator();

int index = 0;

while (it.hasNext()) {

index++;

row = sheet.createRow(index);

T t = (T) it.next();

//利用反射,根據javabean屬性的先後順序,動态調用getXxx()方法得到屬性值

Field[] fields = t.getClass().getDeclaredFields();

for (short i = 0; i < fields.length; i++) {

HSSFCell cell = row.createCell(i);

cell.setCellStyle(style2);

Field field = fields[i];

String fieldName = field.getName();

String getMethodName = "get"

+ fieldName.substring(0, 1).toUpperCase()

+ fieldName.substring(1);

try {

Class tCls = t.getClass();

Method getMethod = tCls.getMethod(getMethodName,

new Class[] {});

Object value = getMethod.invoke(t, new Object[] {});

//判斷值的類型後進行強制類型轉換

String textValue = null;

//              if (value instanceof Integer) {

//                 int intValue = (Integer) value;

//                 cell.setCellValue(intValue);

//              } else if (value instanceof Float) {

//                 float fValue = (Float) value;

//                 textValue = new HSSFRichTextString(

//                       String.valueOf(fValue));

//                 cell.setCellValue(textValue);

//              } else if (value instanceof Double) {

//                 double dValue = (Double) value;

//                 textValue = new HSSFRichTextString(

//                       String.valueOf(dValue));

//                 cell.setCellValue(textValue);

//              } else if (value instanceof Long) {

//                 long longValue = (Long) value;

//                 cell.setCellValue(longValue);

//              }

if (value instanceof Boolean) {

boolean bValue = (Boolean) value;

textValue = "男";

if (!bValue) {

textValue ="女";

}

} else if (value instanceof Date) {

Date date = (Date) value;

SimpleDateFormat sdf = new SimpleDateFormat(pattern);

textValue = sdf.format(date);

} else if (value instanceof byte[]) {

// 有圖檔時,設定行高為60px;

row.setHeightInPoints(60);

// 設定圖檔所在列寬度為80px,注意這裡機關的一個換算

sheet.setColumnWidth(i, (short) (35.7 * 80));

// sheet.autoSizeColumn(i);

byte[] bsValue = (byte[]) value;

HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,

1023, 255, (short) 6, index, (short) 6, index);

anchor.setAnchorType(2);

patriarch.createPicture(anchor, workbook.addPicture(

bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));

} else{

//其它資料類型都當作字元串簡單處理

textValue = value.toString();

}

//如果不是圖檔資料,就利用正規表達式判斷textValue是否全部由數字組成

if(textValue!=null){

Pattern p = Pattern.compile("^""d+("".""d+)?$");

Matcher matcher = p.matcher(textValue);

if(matcher.matches()){

//是數字當作double處理

cell.setCellValue(Double.parseDouble(textValue));

}else{

HSSFRichTextString richString = new HSSFRichTextString(textValue);

HSSFFont font3 = workbook.createFont();

font3.setColor(HSSFColor.BLUE.index);

richString.applyFont(font3);

cell.setCellValue(richString);

}

}

} catch (SecurityException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchMethodException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalArgumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InvocationTargetException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

//清理資源

}

}

}

try {

workbook.write(out);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public static void main(String[] args) {

// 測試學生

ExportExcel ex = new ExportExcel();

String[] headers = { "學号", "姓名", "年齡", "性别", "出生日期" };

List dataset = new ArrayList();

dataset.add(new Student(10000001, "張三", 20, true, new Date()));

dataset.add(new Student(20000002, "李四", 24, false, new Date()));

dataset.add(new Student(30000003, "王五", 22, true, new Date()));

// 測試圖書

ExportExcel ex2 = new ExportExcel();

String[] headers2 = { "圖書編号", "圖書名稱", "圖書作者", "圖書價格", "圖書ISBN",

"圖書出版社", "封面圖檔" };

List dataset2 = new ArrayList();

try {

BufferedInputStream bis = new BufferedInputStream(

new FileInputStream("book.jpg"));

byte[] buf = new byte[bis.available()];

while ((bis.read(buf)) != -1) {

//

}

dataset2.add(new Book(1, "jsp", "leno", 300.33f, "1234567",

"清華出版社", buf));

dataset2.add(new Book(2, "java程式設計思想", "brucl", 300.33f, "1234567",

"陽光出版社", buf));

dataset2.add(new Book(3, "DOM藝術", "lenotang", 300.33f, "1234567",

"清華出版社", buf));

dataset2.add(new Book(4, "c++經典", "leno", 400.33f, "1234567",

"清華出版社", buf));

dataset2.add(new Book(5, "c#入門", "leno", 300.33f, "1234567",

"湯春秀出版社", buf));

OutputStream out = new FileOutputStream("E:""a.xls");

OutputStream out2 = new FileOutputStream("E:""b.xls");

ex.exportExcel(headers, dataset, out);

ex2.exportExcel(headers2, dataset2, out2);

out.close();

JOptionPane.showMessageDialog(null, "導出成功!");

System.out.println("excel導出成功!");

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

不行,頭有點暈^_^。呵呵,又是泛型,又是反射,又是正規表達式,又是重載,還有多參數清單和POI API。一下子蹦出來,實在讓人吃不消。不管了,頂住看效果先。在本地運作後,我們發現在E:""下生成了兩份excel檔案:學生記錄和圖書記錄,并且中文,數字,顔色,日期,圖檔等等一且正常。恩,太棒了。有人看到這裡開始苦臉了:喂,我怎麼一運作就報錯啊!呵呵,看看什麼錯吧!哦,找不到檔案,也就是說你沒有book.jpg嘛。好,拷貝一張小巧的圖書圖檔命名為book.jpg放置到目前工程下吧。注意,您千萬别把張桌面大小的圖檔丢進去了^_^!看到效果了吧。現在我們再來簡單梳理一下代碼,實際上上面就做了一個導出excel的方法和一個本地測試main()方法。并且代碼的結構也很清晰,隻是涉及的知識點稍微多一點。大家細心看看注釋,結合要完成的功能,應該沒有太大問題的。好啦,吃杯茶,擦把汗,總算把這個類消化掉,你又進步了。咦,你不是說是在WEB環境下導出的嗎?别急,因為導出就是一個下載下傳的過程。我們隻需要在伺服器端寫一個Jsp或者Servlet元件完成輸出excel到浏覽器用戶端的工作就好了。我們以Servlet為例,還是看代碼吧:

package org.leno.export.util;

import java.io.*;

import java.util.ArrayList;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class Export extends javax.servlet.http.HttpServlet{

static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

File file = new File(getServletContext().getRealPath("WEB-INF/book.jpg"));

response.setContentType("octets/stream");

response.addHeader("Content-Disposition", "attachment;filename=test.xls");

//測試圖書

ExportExcel ex = new ExportExcel();

String[] headers = { "圖書編号", "圖書名稱", "圖書作者", "圖書價格", "圖書ISBN",

"圖書出版社", "封面圖檔" };

List dataset = new ArrayList();

try {

BufferedInputStream bis = new BufferedInputStream(

new FileInputStream(file));

byte[] buf = new byte[bis.available()];

while ((bis.read(buf)) != -1) {

//将圖檔資料存放到緩沖數組中

}

dataset.add(new Book(1, "jsp", "leno", 300.33f, "1234567",

"清華出版社", buf));

dataset.add(new Book(2, "java程式設計思想", "brucl", 300.33f, "1234567",

"陽光出版社", buf));

dataset.add(new Book(3, "DOM藝術", "lenotang", 300.33f, "1234567",

"清華出版社", buf));

dataset.add(new Book(4, "c++經典", "leno", 400.33f, "1234567",

"清華出版社", buf));

dataset.add(new Book(5, "c#入門", "leno", 300.33f, "1234567",

"湯春秀出版社", buf));

OutputStream out = response.getOutputStream();

ex.exportExcel(headers, dataset, out);

out.close();

System.out.println("excel導出成功!");

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

}

寫完之後,如果您不是用eclipse工具生成的Servlet,千萬别忘了在web.xml上注冊這個Servelt。而且同樣的,拷貝一張小巧的圖書圖檔命名為book.jpg放置到目前WEB根目錄的/WEB-INF/下。部署好web工程,用浏覽器通路Servlet看下效果吧!是不是下載下傳成功了。呵呵,您可以将下載下傳到本地的excel報表用列印機列印出來,這樣您就大功告成了。完事了我們就思考:我們發現,我們做的方法,不管是本地調用,還是在WEB伺服器端用Servlet調用;不管是輸出學生清單,還是圖書清單資訊,代碼都幾乎一樣,而且這些資料我們很容器結合背景的DAO操作資料庫動态擷取。恩,類和方法的通用性和靈活性開始有點感覺了。好啦,祝您學習愉快!

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/lenotang/archive/2008/08/24/2823230.aspx

posted on 2010-11-24 09:32 David1228 閱讀(967) 評論(0)  編輯  收藏