java 通過註解,反射,poi 生成Excel

最近公司項目需要把數據通過Excel形式展示給用戶,由於第一次接觸java 生成Excel,在網上找了很多資料,但是很多都不是很理想,自己設計了一個通過自定義註解把列名配置到實體類上,然後通過代碼讀取自定義註解作爲列名,具體實現可以看一下代碼(代碼是實習時候寫的,有點low,大家湊合着看吧,該功能已經上生產了,代碼應該問題沒什麼問題了,就是不夠優雅)

實體類

package com.ifp.business.common.utils;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
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.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
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.ss.util.CellRangeAddress;

import com.ifp.common.common.utils.ColumnName;

@SuppressWarnings("all")
public class CreateExcelTool {
    private static HSSFWorkbook workbook = null;
    private  List listAll = new ArrayList();
    private  List<Map> listMap = null;
    private  Map mapTitle = new  HashMap();
    private static String type[] = {"long","int","double","float","short","byte","boolean","char"};
    /** 
     * 判斷文件是否存在. 
     * @param fileDir  文件路徑 
     * @return 
     */  
    public static boolean fileExist(String fileDir){  
         boolean flag = false;  
         File file = new File(fileDir);  
         flag = file.exists();  
         return flag;  
    }  
    /** 
     * 判斷文件的sheet是否存在. 
     * @param fileDir   文件路徑 
     * @param sheetName  表格索引名 
     * @return 
     */  
    public static boolean sheetExist(String fileDir,String sheetName) throws Exception{  
         boolean flag = false;  
         File file = new File(fileDir);  
         if(file.exists()){    //文件存在  
            //創建workbook  
             try {  
                workbook = new HSSFWorkbook(new FileInputStream(file));  
                //添加Worksheet(不添加sheet時生成的xls文件打開時會報錯)  
                HSSFSheet sheet = workbook.getSheet(sheetName);    
                if(sheet!=null)  
                    flag = true;  
            } catch (Exception e) {  
                throw e;
            }   
              
         }else{    //文件不存在  
             flag = false;  
         }  
         return flag;  
    }  
    /** 
     * 創建新excel. 
     * @param fileDir  excel的路徑 
     * @param sheetName 要創建的表格索引 
     * @param list excel的第一行即列名 
     */  
    public static void CreateExcelTitle(String fileDir,String sheetName,List list,String name) throws Exception{
        //CreateExcelUtil.deleteExcel(fileDir);
        System.out.println("Excel路徑:----------------------------------------"+fileDir);
        String path = fileDir.substring(0,fileDir.lastIndexOf("\\")+1);
        if (getCurrentOS().equals("linux")) {
            path = fileDir.substring(0,fileDir.lastIndexOf("/")+1);
        }
        
        File file=new File(path);
        if(!file.exists()){
            file.mkdirs(); 
        }
        HSSFSheet sheet1;
        Map<String, String> sheetStyle = new HashMap<String, String>();  
        //判斷文件是否存在
        if(CreateExcelUtil.fileExist(fileDir)){
            workbook = new HSSFWorkbook(new FileInputStream(fileDir));
            
            //判斷sheet頁是否存在
            if(CreateExcelUtil.sheetExist(fileDir, sheetName)){
                sheet1 = workbook.getSheet(sheetName);
            }else{
                //添加Worksheet(不添加sheet時生成的xls文件打開時會報錯)
                sheet1 = workbook.createSheet(sheetName); 
            }
        }else{
             workbook = new HSSFWorkbook();
            //添加Worksheet(不添加sheet時生成的xls文件打開時會報錯)  
            sheet1 = workbook.createSheet(sheetName); 
        }
        sheet1.autoSizeColumn(1); 
        sheet1.autoSizeColumn(1, true);
        /**合併單元格
         * 參數:起始行號,終止行號, 起始列號,終止列號
         * 只有 該文件中不存在sheet頁纔會合併單元格
         * */
        sheet1.addMergedRegion(new CellRangeAddress(0, 0, 0, list.size() - 1));
        sheet1.addMergedRegion(new CellRangeAddress(1, 1, 0, list.size() - 1));
        SimpleDateFormat format = new SimpleDateFormat("yyyy年M月");
        
        //新建文件  
        FileOutputStream out = null;  
        try {
            HSSFFont fontName = workbook.createFont();
            HSSFCellStyle cellStyleName = workbook.createCellStyle();
            fontName.setFontHeightInPoints((short) 14); //字體高度
            fontName.setFontName("宋體"); //字體
            fontName.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //加粗
            cellStyleName.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            cellStyleName.setFont(fontName);
            HSSFRow row1 = workbook.getSheet(sheetName).createRow(0);
            row1.setHeight((short)450);
            HSSFCell cell1 = row1.createCell(0);  
            cell1.setCellValue(name);
            cell1.setCellStyle(cellStyleName);
            //設置單元格爲文本格式
            cell1.setCellType(HSSFCell.CELL_TYPE_STRING);
            HSSFRow row2 = workbook.getSheet(sheetName).createRow(1);
            HSSFCell cell2 = row2.createCell(0);  
            cell2.setCellValue("製表日期:"+format.format(new Date())); 
            
            //添加列名 
            HSSFRow row = workbook.getSheet(sheetName).createRow(2);    //創建第一行
            HSSFFont font = workbook.createFont();
            HSSFCellStyle cellStyle = workbook.createCellStyle();
            font.setFontHeightInPoints((short) 12); //字體高度
            cellStyle.setFont(font);
            for(short i = 0;i < list.size();i++){  
                HSSFCell cell = row.createCell(i);
                //設置列寬
                sheet1.setColumnWidth(i,list.get(i).toString().getBytes().length*256);
                cell.setCellValue("" + list.get(i)); 
                cell.setCellStyle(cellStyle);
            }  
            out = new FileOutputStream(fileDir);  
            workbook.write(out);  
        } catch (Exception e) {  
            throw e;
        } finally {    
            try {    
                out.close();    
            } catch (IOException e) {    
                e.printStackTrace();  
            }    
        }    
    } 
    /** 
     * 刪除文件. 
     * @param fileDir  文件路徑 
     */  
    public static boolean deleteExcel(String fileDir) {  
        boolean flag = false;  
        File file = new File(fileDir);  
        // 判斷目錄或文件是否存在    
        if (!file.exists()) {  // 不存在返回 false    
            return flag;    
        } else {    
            // 判斷是否爲文件    
            if (file.isFile()) {  // 爲文件時調用刪除文件方法    
                file.delete();  
                flag = true;  
            }   
        }  
        return flag;  
    }  
    /** 
     * 往excel中寫入
     * @param fileDir    文件路徑 
     * @param sheetName  表格索引 
     * @param object 
     * @throws Exception 
     */  
    public  void writeToExcel(String fileDir,String sheetName,List<Map> mapList) throws Exception{  
        //創建workbook  
        File file = new File(fileDir);  
        try {  
            workbook = new HSSFWorkbook(new FileInputStream(file));  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        //流  
        FileOutputStream out = null;  
        HSSFSheet sheet = workbook.getSheet(sheetName);  
        HSSFFont font = workbook.createFont();
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        font.setFontHeightInPoints((short) 12); //字體高度
        cellStyle.setFont(font);
        /*sheet.setDefaultColumnWidth(14);//設置默認列寬
        sheet.setDefaultRowHeight((short) (6 * 256)); //設置默認行高,表示2個字符的高度*/ 
       // 獲取表格的總行數  
        // int rowCount = sheet.getLastRowNum() + 1; // 需要加一  
        // 獲取表頭的列數  
        int columnCount = sheet.getRow(2).getLastCellNum();  
        try {  
            // 獲得表頭行對象  
            HSSFRow titleRow = sheet.getRow(2);  
            if(titleRow!=null){
                int rowId = 3;
                int i = 0;
                int rowsIndex = 0;
                int row = 3;
                boolean flag = false;
                while(i<mapList.size()){
                    Map map = mapList.get(i);
                    HSSFRow newRow1=sheet.createRow(row);
                    for (short columnIndex = 0; columnIndex < columnCount; columnIndex++) {  //遍歷表頭  
                        String titleName = titleRow.getCell(columnIndex).toString().trim().toString().trim();
                        String mapKey = (String) mapTitle.get(titleName);
                        List list = new ArrayList();
                        if(map.get(mapKey)!=null&&map.get(mapKey).getClass().equals(list.getClass())){
                            flag = true;
                            list = (List) map.get(mapKey);
                            int j = 0;
                            HSSFRow newRow;
                            for(int listIndex = 0;listIndex<list.size();listIndex++){
                                if(sheet.getRow(rowId + j)!=null){
                                    newRow = sheet.getRow(rowId+j); 
                                }else{
                                    newRow=sheet.createRow(rowId+j);
                                }
                                newRow.setHeightInPoints(50);
                                HSSFCell cell = newRow.createCell(columnIndex);  
                                //設置列寬
                                sheet.setColumnWidth(i,list.get(listIndex).toString().getBytes().length*256);
                                cell.setCellValue(list.get(listIndex)==null ? null : list.get(listIndex).toString());
                                setStyle(cell,font);
                                j++;
                                rowsIndex = j;
                            }
                        }else{
                            try{
                                HSSFCell cell = newRow1.createCell(columnIndex);  
                                //判斷字符串長度是否大於列寬,大於列寬,從新設置列寬
                                if(!"".equals(map.get(mapKey))&&map.get(mapKey)!=null){
                                    //判斷是否是中文
                                    if(isContainChinese(map.get(mapKey).toString())&&sheet.getColumnWidth(columnIndex)<map.get(mapKey).toString().getBytes().length*256){
                                        
                                        sheet.setColumnWidth(columnIndex,map.get(mapKey).toString().getBytes().length*256);
                                        
                                    }else if(!isContainChinese(map.get(mapKey).toString())&&sheet.getColumnWidth(columnIndex)<map.get(mapKey).toString().getBytes().length*512){
                                        
                                        sheet.setColumnWidth(columnIndex,map.get(mapKey).toString().getBytes().length*512);
                                    }
                                }
                                    
                                cell.setCellValue(map.get(mapKey)==null ? null : map.get(mapKey).toString());
                                /*setStyle(cell,font);*/
                                
                                cell.setCellStyle(cellStyle);
                            }catch(Exception e){
                                System.out.println("------------------------------------空---------------------------");
                                e.printStackTrace();
                            }
                        }
                    }
                    if(flag){
                        row = row+rowsIndex;
                    }else{
                        row = row+rowsIndex + 1;
                    }
                    
                    rowId = row;
                    i++;
                }
                
            }  
            out = new FileOutputStream(fileDir);  
            workbook.write(out);  
        } catch (Exception e) {  
            e.printStackTrace();
        } finally {    
            try {    
                out.close();    
            } catch (IOException e) {    
                e.printStackTrace();  
            }    
        }    
    }
    /**  
     * 將一個 JavaBean 對象轉化爲一個 Map  
     * @param bean 要轉化的JavaBean 對象  
     * @return 轉化出來的 Map 對象  
     * @throws ClassNotFoundException 
     * @throws InstantiationException 
     * @throws IntrospectionException 如果分析類屬性失敗  
     * @throws IllegalAccessException 如果實例化 JavaBean 失敗  
     * @throws InvocationTargetException 如果調用屬性的 setter 方法失敗  
     */    
   
    public static Map toMap(Object bean) throws ClassNotFoundException, InstantiationException {  
        Map<Object, Object> returnMap = new HashMap<Object, Object>();
        Class clazz = null;
        if(!bean.toString().contains("@")){
            try {
                clazz = Class.forName(bean + "");
                bean = clazz.newInstance();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }else{
            clazz = bean.getClass();
            
        }
        StringBuffer sb = new StringBuffer();  
        BeanInfo beanInfo = null;    
        try {
            //得到的BeanInfo對象封裝了把這個類當做JavaBean看的結果信息,即屬性的信息
            beanInfo = Introspector.getBeanInfo(clazz);  
            //獲取 clazz 類型中的 propertyName 的屬性描述器  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            
            for (int i = 0; i < propertyDescriptors.length; i++) {
                
                PropertyDescriptor descriptor = propertyDescriptors[i];
                if("class".equals(descriptor.getName())){
                    continue;
                }
                String propertyType = descriptor.getPropertyType().toString();
                boolean boo = com.ifp.common.common.utils.StringUtil.isInList(propertyType, com.ifp.common.common.utils.StringUtil.arrayToList(type));
                        
                if(propertyType.contains("java.util.List")){
                    try {
                        Method readMethod = descriptor.getReadMethod();    
                        List result = null;  
                        //調用 set 方法將傳入的value值保存屬性中去  
                        result = (List) readMethod.invoke(bean, new Object[0]);
                       
                        for(Object o:result){
                            toMap(o);
                        }
                        
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    }
                    continue;
                }else if(propertyType.contains("lang") || boo){
                    String propertyName = descriptor.getName(); 
                    if (!propertyName.equals("class")) {
                        Method readMethod = descriptor.getReadMethod();    
                        Object result = null;  
                        //調用 set 方法將傳入的value值保存屬性中去  
                        result = readMethod.invoke(bean, new Object[0]);
                        if (null != result) {
                            if(returnMap!=null&&returnMap.containsKey(propertyName)){
                                List list1 = new ArrayList();
                                List list2 = new ArrayList();
                                list1.add(result);
                                if(!returnMap.get(propertyName).getClass().equals(list2.getClass())){
                                    list2.add(returnMap.get(propertyName));
                                }else{
                                    list2 = (List) returnMap.get(propertyName);
                                }
                                
                                list1.addAll(list2);
                                result = list1;
                            }else{
                                result = result.toString(); 
                            }
                               
                        }
                        returnMap.put(propertyName, result);    
                    } 
                }else{
                    Object obj = propertyType.substring(propertyType.indexOf(" ") + 1);
                    Method readMethod = descriptor.getReadMethod();    
                    Object result = null;  
                    //調用 set 方法將傳入的value值保存屬性中去  
                    result = readMethod.invoke(bean, new Object[0]);
                    toMap(result);
                    continue;
                }
                   
            }    
        } catch (IntrospectionException e) {    
            System.out.println("分析類屬性失敗");    
        } catch (IllegalAccessException e) {    
            System.out.println("實例化 JavaBean 失敗");    
        } catch (IllegalArgumentException e) {    
            System.out.println("映射錯誤");    
        } catch (InvocationTargetException e) {    
            System.out.println("調用屬性的 setter 方法失敗");    
        }    
        return returnMap;    
    }
    /**
     * 獲取父類和當前類所有屬性(包括private)
     * @param object
     * @return
     */
    public static List getAllFields(Object object){
          Class clazz = object.getClass();
          List fieldList = new ArrayList();
          while (clazz != null){
              for (Field field : clazz.getDeclaredFields()) {
                  if (field.getGenericType().toString().contains("java.util.List")){
                      Object obj = (Object)field.toString().substring(field.toString().lastIndexOf(".")+1);
                       Class clazzList = obj.getClass();
                          field.setAccessible(true);
                          String fieldName = field.getName();
                          fieldList.add(fieldName);
                  }
                   
                }
             
            clazz = clazz.getSuperclass();
          }
        
          return fieldList;
    }
    /**
     * 獲得傳入對象的所有屬性名
     * @param object
     * @return
     */
    public  List getFields(Object object){
        Class cla = null;
        if(!object.toString().contains("@")){
            try {
                cla = Class.forName(object + "");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }else{
            cla = object.getClass();
        }
        
        for(Field field : cla.getDeclaredFields()){
            boolean boo = com.ifp.common.common.utils.StringUtil.isInList(field.getGenericType().toString(), com.ifp.common.common.utils.StringUtil.arrayToList(type));
            //判斷該字段的聲明類型
            if(field.getGenericType().toString().contains("java.util.List")){
                Object obj = (Object)(field.getGenericType().toString().substring(field.getGenericType().toString().indexOf("<")+1,field.getGenericType().toString().indexOf(">")));
                getFields(obj);
                continue;
            }else if(field.getGenericType().toString().contains("lang") || boo){
                field.setAccessible(true);
                //獲取自定義註解
                ColumnName anno = field.getAnnotation(ColumnName.class);
                String fieldName = field.getName();
                String annoValue = null;
                if(anno == null){
                    /*annoValue = fieldName;
                    mapTitle.put(fieldName, fieldName);*/
                    //如果該字段沒有註解,直接跳過,表格中不會顯示此字段
                    continue;
                }else{
                    annoValue = anno.value();
                    mapTitle.put(anno.value(),fieldName);
                }
                listAll.add(annoValue);
            }else{
                Object obj = field.getGenericType().toString().substring(field.getGenericType().toString().indexOf(" ") + 1);
                getFields(obj);
                continue;
            }
            
        }
        
     
      return listAll;
    }
    /**
     * 判斷字符串是否包含中文
     * @param str
     * @return
     */
    public static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }
    //設置字體樣式
    public static void setStyle(HSSFCell cell,HSSFFont font){
         // 設置字體
       
        font.setFontHeightInPoints((short) 12); //字體高度
        //font.setColor(HSSFFont.COLOR_RED); //字體顏色
        //font.setFontName("楷體"); //字體
        //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //寬度
        //font.setItalic(true); //是否使用斜體
        //font.setStrikeout(true); //是否使用劃線
        // 設置單元格類型
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setFont(font);
       // cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); //水平佈局:居中
        //cellStyle.setWrapText(true);
        cell.setCellStyle(cellStyle);
    }
    public static String getCurrentOS() {
        String system = "";
        int OS = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS");
        if (OS != -1) {
            system = "windows";
        } else
            system = "linux";
        return system;
    }
    /**
     * 
     * @param fileDir
     * @param sheetName  sheet頁名字
     * @param mapList
     * @throws Exception 
     */
    public  void createExcel(String fileDir,String sheetName,List<Object> list, String name ) throws Exception{
        listMap = new ArrayList();
        List titleList = new ArrayList();
        CreateExcelTool CreateExcelTool = new CreateExcelTool();
        for(Object obj : list){
            listMap.add(toMap(obj));
        } 
        //System.out.println(listMap);
        titleList = CreateExcelTool.getFields(list.get(0));
        System.out.println("表頭:"+titleList);
        CreateExcelTool.CreateExcelTitle(fileDir, sheetName, titleList,name);
        CreateExcelTool.writeToExcel(fileDir, sheetName,listMap);
        System.out.println("---------------------------------------生成表格成功-------------------------------------");
    }
   
    public static void main(String[] args) throws Exception {  
      
        List<Object> list=new ArrayList<Object>();
        List<Object> list2=new ArrayList<Object>();
        Map<String,String> map=new HashMap<String,String>();
        
/*      for(int i = 0;i<3;i++){
          Person p = new Person();
          p.setName("2018-01-16 00:00:00.0"+i);
          p.setAge("2018-01-16 00:00:00.0");
          p.setSex("2018-01-16 00:00:00.0"+i);
            list.add(p);
        }
      for(int i = 0;i<3;i++){
          person2 p = new person2();
          p.setName("list2少時誦詩書所所所所所所所所所所所所所所"+i);
            list2.add(p);
        }*/
      CreateExcelTool CreateExcelTool = new CreateExcelTool();
      String path ="E:/excel/123456778.xls";
      CreateExcelTool.createExcel(path, "sheet1", list, "測試1");
      CreateExcelTool.createExcel(path, "sheet2", list2, "測試2");
    }  
}
自定義註解

package com.ifp.common.common.utils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/**
 * 自定義註解,程序可以讀取註解values(該程序主要用於生成表格時,通過讀取類屬性中配置的註解,生產表格列名)
 * @author cdy
 * @Retention(RetentionPolicy.RUNTIME) 表示該註解在jvm運行時存在
 *@Target(ElementType.FIELD) 只可以修飾屬性
 */
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)
public @interface ColumnName {

    String value(); }