java poi 通用工具類


數據導入導出工具類 

 Exception處理 

 
   public ExcelException() { 
       // TODO Auto-generated constructor stub 
   } 
 
   public ExcelException(String message) { 
       super(message); 
       // TODO Auto-generated constructor stub 
   } 
 
   public ExcelException(Throwable cause) { 
       super(cause); 
       // TODO Auto-generated constructor stub 
   } 
 
   public ExcelException(String message, Throwable cause) { 
       super(message, cause); 
       // TODO Auto-generated constructor stub 
   } 


 POI核心處理 

* @author     : SUNZK-QQ:1131341075 
* @Date       : 2018-8-23 下午9:13:21 
* @Comments   : 導入導出Excel工具類 
* @Version    : 1.0.0 
*/ 
 
 { 
 
   /** 
    * @MethodName  : listToExcel 
    * @Description : 導出Excel(可以導出到本地文件系統,也可以導出到瀏覽器,可
 
    * @param list      數據源 
    * @param fieldMap      類的英文屬性和Excel中的中文列名的對應關係 
    * 如果需要的是引用對象的屬性,則英文屬性使用類似於EL表達式的格式 
    * 如:list中存放的都是student,student中又有college屬性,而我們需要學院名
 
    * fieldMap.put("college.collegeName","學院名稱") 
    * @param sheetName 工作表的名稱 
    * @param sheetSize 每個工作表中記錄的最大個數 
    * @param out       導出流 
    * @throws ExcelException 
    */ 
   public static <T>  void   listToExcel ( 
           List<T> list , 
           LinkedHashMap<String,String> fieldMap, 
           String sheetName, 
           int sheetSize, 
           OutputStream out 
           ) throws ExcelException{ 
 
 
       if(list.size()==0 || list==null){ 
           throw new ExcelException("數據源中沒有任何數據"); 
       } 
 
       if(sheetSize>65535 || sheetSize<1){ 
           sheetSize=65535; 
       } 
 
       //創建工作簿併發送到OutputStream指定的地方 
       WritableWorkbook wwb; 
       try { 
           wwb = Workbook.createWorkbook(out); 
 
           //因爲2003的Excel一個工作表最多可以有65536條記錄,除去列頭剩下
條 
           //所以如果記錄太多,需要放到多個工作表中,其實就是個分頁的過程 
           //1.計算一共有多少個工作表 
           double sheetNum=Math.ceil(list.size()/new 

 
           //2.創建相應的工作表,並向其中填充數據 
           for(int i=0; i<sheetNum; i++){ 
               //如果只有一個工作表的情況 
               if(1==sheetNum){ 
                   WritableSheet sheet=wwb.createSheet(sheetName, i); 
                   fillSheet(sheet, list, fieldMap, 0, list.size()-1); 
 
               //有多個工作表的情況 
               }else{ 
                   WritableSheet sheet=wwb.createSheet(sheetName+(i+1), i); 
 
                   //獲取開始索引和結束索引 
                   int firstIndex=i*sheetSize; 
                   int lastIndex=(i+1)*sheetSize-1>list.size()-1 ? list.size()-1 : 

                   //填充工作表 
                   fillSheet(sheet, list, fieldMap, firstIndex, lastIndex); 
               } 
           } 
 
           wwb.write(); 
           wwb.close(); 
 
       }catch (Exception e) { 
           e.printStackTrace(); 
           //如果是ExcelException,則直接拋出 
           if(e instanceof ExcelException){ 
               throw (ExcelException)e; 
 
           //否則將其它異常包裝成ExcelException再拋出 
           }else{ 
               throw new ExcelException("導出Excel失敗"); 
           } 
       } 
 
   } 
 
   /** 
    * @MethodName  : listToExcel 
    * @Description : 導出Excel(可以導出到本地文件系統,也可以導出到瀏覽器,工
2003支持的最大值) 
    * @param list      數據源 
    * @param fieldMap      類的英文屬性和Excel中的中文列名的對應關係 
    * @param out       導出流 
    * @throws ExcelException 
    */ 
   public static  <T>  void   listToExcel ( 
           List<T> list , 
           LinkedHashMap<String,String> fieldMap, 
           String sheetName, 
           OutputStream out 
           ) throws ExcelException{ 
 
       listToExcel(list, fieldMap, sheetName, 65535, out); 
 
   } 
 
 
   /** 
    * @MethodName  : listToExcel 
    * @Description : 導出Excel(導出到瀏覽器,可以自定義工作表的大小) 
    * @param list      數據源 
    * @param fieldMap      類的英文屬性和Excel中的中文列名的對應關係 
    * @param sheetSize    每個工作表中記錄的最大個數 
    * @param response  使用response可以導出到瀏覽器 
    * @throws ExcelException 
    */ 
   public static  <T>  void   listToExcel ( 
           List<T> list , 
           LinkedHashMap<String,String> fieldMap, 
           String sheetName, 
           int sheetSize, 
           HttpServletResponse response  
           ) throws ExcelException{ 
 
       //設置默認文件名爲當前時間:年月日時分秒 
       String fileName=new SimpleDateFormat("yyyyMMddhhmmss").format(new 

 
       //設置response頭信息 
       response.reset();           
       response.setContentType("application/vnd.ms-excel");        //改成輸出excel
 
       response.setHeader("Content-disposition","attachment; 

 
       //創建工作簿併發送到瀏覽器 
       try { 
 
           OutputStream out=response.getOutputStream(); 
           listToExcel(list, fieldMap, sheetName, sheetSize,out ); 
 
       } catch (Exception e) { 
           e.printStackTrace(); 
 
           //如果是ExcelException,則直接拋出 
           if(e instanceof ExcelException){ 
               throw (ExcelException)e; 
 
           //否則將其它異常包裝成ExcelException再拋出 
           }else{ 
               throw new ExcelException("導出Excel失敗"); 
           } 
       } 
   } 
 
 
   /** 
    * @MethodName  : listToExcel 
    * @Description : 導出Excel(導出到瀏覽器,工作表的大小是2003支持的最大值) 
    * @param list      數據源 
    * @param fieldMap      類的英文屬性和Excel中的中文列名的對應關係 
    * @param response  使用response可以導出到瀏覽器 
    * @throws ExcelException 
    */ 
   public static <T>  void   listToExcel ( 
           List<T> list , 
           LinkedHashMap<String,String> fieldMap, 
           String sheetName, 
           HttpServletResponse response  
           ) throws ExcelException{ 
 
       listToExcel(list, fieldMap, sheetName, 65535, response); 
   } 
 
   /** 
    * @MethodName          : excelToList 
    * @Description             : 將Excel轉化爲List 
    * @param in                    :承載着Excel的輸入流 
    * @param sheetIndex        :要導入的工作表序號 
    * @param entityClass       :List中對象的類型(Excel中的每一行都要轉化爲該
 
    * @param fieldMap          :Excel中的中文列頭和類的英文屬性的對應關係

    * @param uniqueFields  :指定業務主鍵組合(即複合主鍵),這些列的組合不
 
    * @return                      :List 
    * @throws ExcelException 
    */ 
   public static <T>  List<T>  excelToList( 
           InputStream in, 
           String sheetName, 
           Class<T> entityClass, 
           LinkedHashMap<String, String> fieldMap, 
           String[] uniqueFields 
           ) throws ExcelException{ 
 
       //定義要返回的list 
       List<T> resultList=new ArrayList<T>(); 
 
       try { 
 
           //根據Excel數據源創建WorkBook 
           Workbook wb=Workbook.getWorkbook(in); 
           //獲取工作表 
           Sheet sheet=wb.getSheet(sheetName); 
 
           //獲取工作表的有效行數 
           int realRows=0; 
           for(int i=0;i<sheet.getRows();i++){ 
 
               int nullCols=0; 
               for(int j=0;j<sheet.getColumns();j++){ 
                   Cell currentCell=sheet.getCell(j,i); 
                   if(currentCell==null || 

                       nullCols++; 
                   } 
               } 
 
               if(nullCols==sheet.getColumns()){ 
                   break; 
               }else{ 
                   realRows++; 
               } 
           } 
 
 
           //如果Excel中沒有數據則提示錯誤 
           if(realRows<=1){ 
               throw new ExcelException("Excel文件中沒有任何數據"); 
           } 
 
 
           Cell[] firstRow=sheet.getRow(0); 
 
           String[] excelFieldNames=new String[firstRow.length]; 
 
           //獲取Excel中的列名 
           for(int i=0;i<firstRow.length;i++){ 
               excelFieldNames[i]=firstRow[i].getContents().toString().trim(); 
           } 
 
           //判斷需要的字段在Excel中是否都存在 
           boolean isExist=true; 
           List<String> excelFieldList=Arrays.asList(excelFieldNames); 
           for(String cnName : fieldMap.keySet()){ 
               if(!excelFieldList.contains(cnName)){ 
                   isExist=false; 
                   break; 
               } 
           } 
 
           //如果有列名不存在,則拋出異常,提示錯誤 
           if(!isExist){ 
               throw new ExcelException("Excel中缺少必要的字段,或字段名稱有誤

           } 
 
 
           //將列名和列號放入Map中,這樣通過列名就可以拿到列號 
           LinkedHashMap<String, Integer> colMap=new LinkedHashMap<String, 

           for(int i=0;i<excelFieldNames.length;i++){ 
               colMap.put(excelFieldNames[i], firstRow[i].getColumn()); 
           }  
 
 
 
           //判斷是否有重複行 
           //1.獲取uniqueFields指定的列 
           Cell[][] uniqueCells=new Cell[uniqueFields.length][]; 
           for(int i=0;i<uniqueFields.length;i++){ 
               int col=colMap.get(uniqueFields[i]); 
               uniqueCells[i]=sheet.getColumn(col); 
           } 
 
           //2.從指定列中尋找重複行 
           for(int i=1;i<realRows;i++){ 
               int nullCols=0; 
               for(int j=0;j<uniqueFields.length;j++){ 
                   String currentContent=uniqueCells[j][i].getContents(); 
                   Cell sameCell=sheet.findCell(currentContent,  
                           uniqueCells[j][i].getColumn(), 
                           uniqueCells[j][i].getRow()+1,  
                           uniqueCells[j][i].getColumn(),  
                           uniqueCells[j][realRows-1].getRow(),  
                           true); 
                   if(sameCell!=null){ 
                       nullCols++; 
                   } 
               } 
 
               if(nullCols==uniqueFields.length){ 
                   throw new ExcelException("Excel中有重複行,請檢查"); 
               } 
           } 
 
           //將sheet轉換爲list 
           for(int i=1;i<realRows;i++){ 
               //新建要轉換的對象 
               T entity=entityClass.newInstance(); 
 
               //給對象中的字段賦值 
               for(Entry<String, String> entry : fieldMap.entrySet()){ 
                   //獲取中文字段名 
                   String cnNormalName=entry.getKey(); 
                   //獲取英文字段名 
                   String enNormalName=entry.getValue(); 
                   //根據中文字段名獲取列號 
                   int col=colMap.get(cnNormalName); 
 
                   //獲取當前單元格中的內容 
                   String content=sheet.getCell(col, i).getContents().toString().trim(); 
 
                   //給對象賦值 
                   setFieldValueByName(enNormalName, content, entity); 
               } 
 
               resultList.add(entity); 
           } 
       } catch(Exception e){ 
           e.printStackTrace(); 
           //如果是ExcelException,則直接拋出 
           if(e instanceof ExcelException){ 
               throw (ExcelException)e; 
 
           //否則將其它異常包裝成ExcelException再拋出 
           }else{ 
               e.printStackTrace(); 
               throw new ExcelException("導入Excel失敗"); 
           } 
       } 
       return resultList; 
   } 
 
 
 
 
 
   /*<-------------------------輔助的私有方法----------------------------------------------->*/ 
   /** 
    * @MethodName  : getFieldValueByName 
    * @Description : 根據字段名獲取字段值 
    * @param fieldName 字段名 
    * @param o 對象 
    * @return  字段值 
    */ 
   private static  Object getFieldValueByName(String fieldName, Object o) throws 

 
       Object value=null; 
       Field field=getFieldByName(fieldName, o.getClass()); 
 
       if(field !=null){ 
           field.setAccessible(true); 
           value=field.get(o); 
       }else{ 
           throw new ExcelException(o.getClass().getSimpleName() + "類不存在字段名 

       } 
 
       return value; 
   } 
 
   /** 
    * @MethodName  : getFieldByName 
    * @Description : 根據字段名獲取字段 
    * @param fieldName 字段名 
    * @param clazz 包含該字段的類 
    * @return 字段 
    */ 
   private static Field getFieldByName(String fieldName, Class<?>  clazz){ 
       //拿到本類的所有字段 
       Field[] selfFields=clazz.getDeclaredFields(); 
 
       //如果本類中存在該字段,則返回 
       for(Field field : selfFields){ 
           if(field.getName().equals(fieldName)){ 
               return field; 
           } 
       } 
 
       //否則,查看父類中是否存在此字段,如果有則返回 
       Class<?> superClazz=clazz.getSuperclass(); 
       if(superClazz!=null  &&  superClazz !=Object.class){ 
           return getFieldByName(fieldName, superClazz); 
       } 
 
       //如果本類和父類都沒有,則返回空 
       return null; 
   } 
 
 
 
   /** 
    * @MethodName  : getFieldValueByNameSequence 
    * @Description :  
    * 根據帶路徑或不帶路徑的屬性名獲取屬性值 
    * 即接受簡單屬性名,如userName等,又接受帶路徑的屬性名,如
等 
    *  
    * @param fieldNameSequence  帶路徑的屬性名或簡單屬性名 
    * @param o 對象 
    * @return  屬性值 
    * @throws Exception 
    */ 
   private static  Object getFieldValueByNameSequence(String fieldNameSequence, 

 
       Object value=null; 
 
       //將fieldNameSequence進行拆分 
       String[] attributes=fieldNameSequence.split("\\."); 
       if(attributes.length==1){ 
           value=getFieldValueByName(fieldNameSequence, o); 
       }else{ 
           //根據屬性名獲取屬性對象 
           Object fieldObj=getFieldValueByName(attributes[0], o); 
           String 

           value=getFieldValueByNameSequence(subFieldNameSequence, fieldObj); 
       } 
       return value;  
 
   }  
 
 
   /** 
    * @MethodName  : setFieldValueByName 
    * @Description : 根據字段名給對象的字段賦值 
    * @param fieldName  字段名 
    * @param fieldValue    字段值 
    * @param o 對象 
    */ 
   private static void setFieldValueByName(String fieldName,Object fieldValue,Object o) 

 
           Field field=getFieldByName(fieldName, o.getClass()); 
           if(field!=null){ 
               field.setAccessible(true); 
               //獲取字段類型 
               Class<?> fieldType = field.getType();   
 
               //根據字段類型給字段賦值 
               if (String.class == fieldType) {   
                   field.set(o, String.valueOf(fieldValue));   
               } else if ((Integer.TYPE == fieldType)   
                       || (Integer.class == fieldType)) {   
                   field.set(o, Integer.parseInt(fieldValue.toString()));   
               } else if ((Long.TYPE == fieldType)   
                       || (Long.class == fieldType)) {   
                   field.set(o, Long.valueOf(fieldValue.toString()));   
               } else if ((Float.TYPE == fieldType)   
                       || (Float.class == fieldType)) {   
                   field.set(o, Float.valueOf(fieldValue.toString()));   
               } else if ((Short.TYPE == fieldType)   
                       || (Short.class == fieldType)) {   
                   field.set(o, Short.valueOf(fieldValue.toString()));   
               } else if ((Double.TYPE == fieldType)   
                       || (Double.class == fieldType)) {   
                   field.set(o, Double.valueOf(fieldValue.toString()));   
               } else if (Character.TYPE == fieldType) {   
                   if ((fieldValue!= null) && (fieldValue.toString().length() > 0)) {   
                       field.set(o, Character   
                               .valueOf(fieldValue.toString().charAt(0)));   
                   }   
               }else if(Date.class==fieldType){ 
                   field.set(o, new SimpleDateFormat("yyyy-MM-dd 

               }else{ 
                   field.set(o, fieldValue); 
               } 
           }else{ 
               throw new ExcelException(o.getClass().getSimpleName() + "類不存在字
 "+fieldName); 
           } 
   } 
 
 
   /** 
    * @MethodName  : setColumnAutoSize 
    * @Description : 設置工作表自動列寬和首行加粗 
    * @param ws 
    */ 
   private static void setColumnAutoSize(WritableSheet ws,int extraWith){ 
       //獲取本列的最寬單元格的寬度 
       for(int i=0;i<ws.getColumns();i++){ 
           int colWith=0; 
           for(int j=0;j<ws.getRows();j++){ 
               String content=ws.getCell(i,j).getContents().toString(); 
               int cellWith=content.length(); 
               if(colWith<cellWith){ 
                   colWith=cellWith; 
               } 
           } 
           //設置單元格的寬度爲最寬寬度+額外寬度 
           ws.setColumnView(i, colWith+extraWith); 
       } 
 
   } 
 
   /** 
    * @MethodName  : fillSheet 
    * @Description : 向工作表中填充數據 
    * @param sheet     工作表  
    * @param list  數據源 
    * @param fieldMap 中英文字段對應關係的Map 
    * @param firstIndex    開始索引 
    * @param lastIndex 結束索引 
    */ 
   private static <T> void fillSheet( 
           WritableSheet sheet, 
           List<T> list, 
           LinkedHashMap<String,String> fieldMap, 
           int firstIndex, 
           int lastIndex 
           )throws Exception{ 
 
       //定義存放英文字段名和中文字段名的數組 
       String[] enFields=new String[fieldMap.size()]; 
       String[] cnFields=new String[fieldMap.size()]; 
 
       //填充數組 
       int count=0; 
       for(Entry<String,String> entry:fieldMap.entrySet()){ 
           enFields[count]=entry.getKey(); 
           cnFields[count]=entry.getValue(); 
           count++; 
       } 
       //填充表頭 
       for(int i=0;i<cnFields.length;i++){ 
           Label label=new Label(i,0,cnFields[i]); 
           sheet.addCell(label); 
       } 
 
       //填充內容 
       int rowNo=1; 
       for(int index=firstIndex;index<=lastIndex;index++){ 
           //獲取單個對象 
           T item=list.get(index); 
           for(int i=0;i<enFields.length;i++){ 
               Object objValue=getFieldValueByNameSequence(enFields[i], item); 
               String fieldValue=objValue==null ? "" : objValue.toString(); 
               Label label =new Label(i,rowNo,fieldValue); 
               sheet.addCell(label); 
           } 
 
           rowNo++; 
       } 
       //設置自動列寬 
       setColumnAutoSize(sheet, 5); 
   } 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章