Java的POI的封裝與應用


Java對Excel表格的導出一直是對我有種可怕噩夢的東西,每次對要建立行與列,並一個一個放值,我是從心底拒絕的。

處於項目需求,需要導出表格,於是找到網上一版很好的開發, 《不想用POI?幾行代碼完成Excel導出導入》原文鏈接:  https://juejin.im/post/5c3b683ee51d4551d14175ee  

但是、我們項目不支持如此進行開發,

================================分割線=================================

因為需要引入xml文件進行開發,於是,只能自己動手封裝一個滿足需求的類:

一、需求:

查詢統計的數據 List,進行數據導出,並且表頭有合並單元格的需求。

直接上圖:以下是部分結果(由於全部截取失真)

二、設計思路:

表頭::把表頭與數據插入表格對象進行分開。表頭部分,每一行做為一個list, 使用String[]進行存儲。每次分析表頭,進行解析,生成表頭。

表體::需要插入的數據使用list中存入 map對象,其中的對象字段名稱與表頭部分相同,就可以進行數據的插入。

代碼如下:

/**
  * Created by 閑一 on 2019/2/20.
  */
package  com.test;
 
import  org.apache.poi.ss.usermodel.Cell;
import  org.apache.poi.ss.usermodel.Row;
import  org.apache.poi.ss.usermodel.Sheet;
import  org.apache.poi.ss.util.CellRangeAddress;
import  org.apache.poi.xssf.usermodel.XSSFWorkbook;
import  org.junit.Test;
 
import  java.io.File;
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.OutputStream;
import  java.text.SimpleDateFormat;
import  java.util.*;
 
public  class  POItest2 {
     
     @Test
     public  void  test1()  throws  IOException {
         List<String[]> list =  new  ArrayList<>();
         String[] arr = { "部門" "雲速" };
         String[] arr1 = { "總計" "10000000" };
         String[] arr2 = { "單位" "元" };
         list.add(arr);
         list.add(arr1);
         list.add(arr2);
         XSSFWorkbook workbook =  new  XSSFWorkbook();
         workbook = workbookList(workbook,  "come" "" , list);
 
         String[] arra0 = { "name" "名稱" "1" "1" };
         String[] arra1 = { "Person" "人類" "1" "2" };
         String[] arrb1 = { "Amions" "動物" "1" "1" };
         List<String[]> lista =  new  ArrayList<>();
         List<List<String[]>> titles =  new  ArrayList<>();
         lista.add(arra0);
         lista.add(arra1);
         lista.add(arrb1);
         titles.add(lista);
         String[] arr11 = { "" "" "2" "1" };
         List<String[]> list1 =  new  ArrayList<>();
         list1.add(arr11);
         String[] arr21 = { "sex" "性別" "1" "1" };
         list1.add(arr21);
         String[] arr31 = { "kaka" "咳咳" "1" "1" };
         list1.add(arr31);
         String[] arr41 = { "kaka" "小米" "1" "1" };
         list1.add(arr41);
         titles.add(list1);
 
         workbook = workbookinList(workbook,  "come" "" , titles,  new  ArrayList<>());
         workbook = workbookinList(workbook,  "come" "" , titles,  new  ArrayList<>());
 
         String path =  "d:/data/2019-02-19-04.csv" ;
         wirteOutWorkbook(workbook, path);
     }
 
     /**
      * 將數據寫入指定Excel對象中
      *
      * @param workbook  Excel對象
      * @param sheetName sheet名
      * @param style     Excel類型
      * @param titles    標題串 {{['person','人類',1,2]},
      *                  {['name','名稱',1,1], ['sex','性別',1,1]}}   【 字段名稱,標題,所占行數,所占列數】
      * @param values    內容集
      * @return True\False
      */
     public  XSSFWorkbook workbookinList(XSSFWorkbook workbook, String sheetName, String style, List<List<String[]>> titles, List<Map<String, Object>> values) {
         // 生成一個表格
         Sheet sheet;
         sheet = workbook.getSheet(sheetName);
         if  (sheet ==  null ) {
             if  ( null  == sheetName ||  "" .equals(sheetName)) {
                 sheet = workbook.createSheet();  // sheetName 為空則使用默認值
             else  {
                 sheet = workbook.createSheet(sheetName);
             }
         }
         // 設置表格默認列寬度為15個字節
         sheet.setDefaultColumnWidth(( short 15 );
         // 第一行生成賬單標題
         Row row =  null ;
         int  rowNumCount =  0  == sheet.getLastRowNum() ?  0  : sheet.getLastRowNum() +  2 ; //獲得總行數
         // 存儲標題在Excel文件中的序號
         Map<String, Integer> titleOrder =  new  HashMap<>();
         for  ( int  j =  0 ; j < titles.size(); j++) {
             List<String[]> list = titles.get(j);
             row = sheet.createRow(rowNumCount + j);
             int  curCol =  0 //當前列數名稱
             for  ( int  i =  0 ; i < list.size(); i++) {
                 org.apache.poi.ss.usermodel.Cell cell = row.createCell(curCol);
                 String[] title = list.get(i);
                 cell.setCellValue(title[ 1 ]);  // 標題值
                 // 需要記錄每次的列位置
                 int  rowNum = Integer.valueOf(title[ 2 ]) -  1 // 需要占用的行數
                 int  colNum = Integer.valueOf(title[ 3 ]) -  1 // 需要占用的列數
                 if  ( 0  != rowNum ||  0  != colNum) {
                     int  curRow = rowNumCount + j;
                     CellRangeAddress region =  new  CellRangeAddress(curRow - rowNum, curRow, curCol, curCol + colNum);
                     sheet.addMergedRegion(region);
                     curCol += Integer.valueOf(title[ 3 ]);
                 else  {
                     curCol++;
                 }
                 // 最后一行包含所有列
                 if  (j == titles.size() -  1 ) {
                     titleOrder.put(title[ 0 ], i);
                 }
             }
         }
         /*
          * 寫入正文
          */
         Iterator<Map<String, Object>> iterator = values.iterator();
         int  index = rowNumCount +  1 // 行號
         while  (iterator.hasNext()) {
             index++;  // 出去標題行,從第一行開始寫
             row = sheet.createRow(index);
             Map<String, Object> value = iterator.next();
             for  (Map.Entry<String, Object> map : value.entrySet()) {
                 // 獲取列名
                 String title = map.getKey();
                 // 根據列名獲取序號
                 Integer i = titleOrder.get(title);
                 if  (i ==  null ) {
                     continue ;
                 }
                 // 在指定序號處創建cell
                 Cell cell = row.createCell(i);
                 // 獲取列的值
                 Object object = map.getValue();
                 // 判斷object的類型
                 SimpleDateFormat simpleDateFormat =  new  SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
                 if  (object  instanceof  Double) {
                     cell.setCellValue((Double) object);
                 else  if  (object  instanceof  Date) {
                     String time = simpleDateFormat.format((Date) object);
                     cell.setCellValue(time);
                 else  if  (object  instanceof  Calendar) {
                     Calendar calendar = (Calendar) object;
                     String time = simpleDateFormat.format(calendar.getTime());
                     cell.setCellValue(time);
                 else  if  (object  instanceof  Boolean) {
                     cell.setCellValue((Boolean) object);
                 else  {
                     if  (object ==  null ) {
                         cell.setCellValue( "" );
                     else  {
                         cell.setCellValue(object.toString());
                     }
                 }
             }
         }
         return  workbook;
     }
 
     /**
      * 將數據寫入Excel文件中
      *
      * @param workbook  Excel對象
      * @param sheetName sheet名
      * @param style     Excel類型
      * @param dataList  標題串+內容集 {{'部門','201930'},{'總計','10000萬'}}
      * @return True\False
      */
     public  XSSFWorkbook workbookList(XSSFWorkbook workbook, String sheetName, String style, List<String[]> dataList) {
         // 生成一個表格
         Sheet sheet;
         sheet = workbook.getSheet(sheetName);
         if  (sheet ==  null ) {
             if  ( null  == sheetName ||  "" .equals(sheetName)) {
                 sheet = workbook.createSheet();  // sheetName 為空則使用默認值
             else  {
                 sheet = workbook.createSheet(sheetName);
             }
         }
         // 設置表格默認列寬度為15個字節
         sheet.setDefaultColumnWidth(( short 15 );
         // 第一行生成賬單標題
         Row row =  null ;
         int  rowNumCount =  0  == sheet.getLastRowNum() ?  0  : sheet.getLastRowNum() +  2 ; //獲得總行數
         // 存儲標題在Excel文件中的序號
         for  ( int  i =  0 ; i < dataList.size(); i++) {
             row = sheet.createRow(rowNumCount + i);
             row.createCell( 0 ).setCellValue(dataList.get(i)[ 0 ]);
             row.createCell( 1 ).setCellValue(dataList.get(i)[ 1 ]);
         }
         return  workbook;
     }
 
     /**
      * 文件寫出
      *
      * @param workbook
      * @param path
      * @throws IOException
      */
     public  void  wirteOutWorkbook(XSSFWorkbook workbook, String path)  throws  IOException {
         String dirPath = path.substring( 0 , path.lastIndexOf( '.' ));
         File dirFile =  new  File(dirPath);
         if  (!dirFile.exists() && !dirFile.isDirectory()) {
             dirFile.mkdirs();
         }
         File file =  new  File(path);
         if  (file.exists()) {
             file.delete();
         }
         OutputStream outputStream =  new  FileOutputStream(file);
         workbook.write(outputStream);
         outputStream.close();
         workbook.close();
     }
}

 

如有疑問,歡迎留言討論!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM