Java POI 導出EXCEL經典實現

  • 時間:2018-07-01 23:30 作者:程序員小新人學習 來源:程序員小新人學習 閱讀:270
  • 掃一掃,手機訪問
摘要:在web開發中,有一個經典的功可以,就是數據的導入導出。特別是數據的導出,在生產管理或者者財務系統中使用的非常普遍,由于這些系統經常要做少量報表打印的工作。而數據導出的格式一般是EXCEL或者者PDF,我這里就分別給大家詳情下。(注意,我們這里說的數據導出可不是數據庫中的數據導出!么誤解啦^_^)首

在web開發中,有一個經典的功可以,就是數據的導入導出。特別是數據的導出,在生產管理或者者財務系統中使用的非常普遍,由于這些系統經常要做少量報表打印的工作。而數據導出的格式一般是EXCEL或者者PDF,我這里就分別給大家詳情下。(注意,我們這里說的數據導出可不是數據庫中的數據導出!么誤解啦^_^)

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

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

import java.util.Date;  public class Student {  private long id;  private String name;  private int age;  private boolean sex;  private Date birthday;   public Student()  {  }   public Student(long id, String name, int age, boolean sex, Date birthday)  {  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;  }  }
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()  {  }   public Book(int bookId, String name, String author, float price,  String isbn, String pubName, byte[] preface)  {  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風格的類。再看下面真正的重點類:

import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern;  import javax.swing.JOptionPane;  import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFComment; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFPatriarch; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor;  /** * 利使用開源組件POI3.0.2動態導出EXCEL文檔 轉載時請保留以下信息,注明出處! * * @author leno * @version v1.0 * @param  * 應使用泛型,代表任意一個符合javabean風格的類 * 注意這里為了簡單起見,boolean型的屬性xxx的get器方式為getXxx(),而不是isXxx() * byte[]表jpg格式的圖片數據 */ 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);  }   /**  * 這是一個通使用的方法,利使用了JAVA的反射機制,能將放置在JAVA集合中并且符號肯定條件的數據以EXCEL 的形式輸出到指定IO設施上  *  * @param title  * 表格標題名  * @param headers  * 表格屬性列名數組  * @param dataset  * 需要顯示的數據集合,集合中肯定要放置符合javabean風格的類的對象。此方法支持的  * javabean屬性的數據類型有基本數據類型及String,Date,byte[](圖片數據)  * @param out  * 與輸出設施關聯的流對象,能將EXCEL文檔導出到本地文件或者者網絡中  * @param pattern  * 假如有時間數據,設定輸出格式。默認為"yyy-MM-dd"  */  @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)  {  e.printStackTrace();  }  catch (NoSuchMethodException e)  {  e.printStackTrace();  }  catch (IllegalArgumentException e)  {  e.printStackTrace();  }  catch (IllegalAccessException e)  {  e.printStackTrace();  }  catch (InvocationTargetException e)  {  e.printStackTrace();  }  finally  {  // 清除資源  }  }  }  try  {  workbook.write(out);  }  catch (IOException e)  {  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("V://book.bmp"));  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();  out2.close();  JOptionPane.showMessageDialog(null, "導出成功!");  System.out.println("excel導出成功!");  } catch (FileNotFoundException e) {  e.printStackTrace();  } catch (IOException e) {  e.printStackTrace();  }  } }

寫完之后,假如你不是使用eclipse工具生成的Servlet,千萬別忘了在web.xml上注冊這個Servelt。而且同樣的,拷貝一張小巧的圖書圖片命名為book.jpg放置到當前WEB根目錄的/WEB-INF/下。部署好web工程,使用瀏覽器訪問Servlet看下效果吧!是不是下載成功了。你能將下載到本地的excel報表使用打印機打印出來,這樣就大功告成了。完事了我們就思考:我們發現,我們做的方法,不論是本地調使用,還是在WEB服務器端使用Servlet調使用;不論是輸出學生列表,還是圖書列表信息,代碼都幾乎一樣,而且這些數據我們很容器結合后端的DAO操作數據庫動態獲取。恩,類和方法的通使用性和靈活性開始有點感覺了。

Java導出Excel彈出下載框

將ExportExcel類的main方法改成public void test(),OutputStream out = new FileOutputStream("E://a.xls");這邊能對應Servlet適當改下路徑,Servlet代碼如下:

public class ExcelServlet extends HttpServlet {  public void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  (new ExportExcel()).test();  String str = "a.xls";  //String path = request.getSession().getServletContext().getRealPath(str);  download("E://a.xls", response);  }  private void download(String path, HttpServletResponse response) {  try {  // path是指欲下載的文件的路徑。  File file = new File(path);  // 獲得文件名。  String filename = file.getName();  // 以流的形式下載文件。  InputStream fis = new BufferedInputStream(new FileInputStream(path));  byte[] buffer = new byte[fis.available()];  fis.read(buffer);  fis.close();  // 清空response  response.reset();  // 設置response的Header  response.addHeader("Content-Disposition", "attachment;filename="  + new String(filename.getBytes()));  response.addHeader("Content-Length", "" + file.length());  OutputStream toClient = new BufferedOutputStream(  response.getOutputStream());  response.setContentType("application/vnd.ms-excel;charset=gb2312");  toClient.write(buffer);  toClient.flush();  toClient.close();  } catch (IOException ex) {  ex.printStackTrace();  }  } }
Java POI 導出EXCEL經典實現

  • 全部評論(0)
最新發布的資訊信息
【系統環境|服務器應用】在CentOS 7上如何安裝Gogs 0.11.53(2020-02-10 10:14)
【系統環境|】淘碼庫,據消息稱已被調查。淘碼庫源碼網,已經無法訪問!(2020-01-14 04:13)
【系統環境|服務器應用】Discuz隱藏后臺admin.php網址修改路徑(2019-12-16 16:48)
【系統環境|服務器應用】2020新網站如何讓百度快速收錄網站首頁最新方法,親測有用!免費(2019-12-16 16:46)
【系統環境|服務器應用】Discuz發布帖子時默認顯示第一個主題分類的修改方法(2019-12-09 00:13)
【系統環境|軟件環境】Android | App內存優化 之 內存泄漏 要點概述 以及 處理實戰(2019-12-04 14:27)
【系統環境|軟件環境】MySQL InnoDB 事務(2019-12-04 14:26)
【系統環境|軟件環境】vue-router(單頁面應用控制中心)常見用法(2019-12-04 14:26)
【系統環境|軟件環境】Linux中的Kill命令(2019-12-04 14:26)
【系統環境|軟件環境】Linux 入門時必學60個文件解決命令(2019-12-04 14:26)
手機二維碼手機訪問領取大禮包
返回頂部
3d开机号查询