java使用註解進行excel導入、導出

之前在項目中有遇到excel導入、導出的功能,起初做的時候在網上找了一些類似的例子,功能是實現了,但是總感覺代碼太過於臃腫,不夠靈活,每次進行導入導出的需要寫一長串代碼感覺非常不爽,於是結合網上和自己的理解寫了以下博客!

使用的第三方jar包是poi

首先在maven項目中的pom文件中加入這個依賴包

Xml代碼 收藏代碼

    <dependency>  
        <groupId>org.apache.poi</groupId>  
        <artifactId>poi</artifactId>  
        <version>3.9</version>  
    </dependency>  

 然後編寫控制excel導入、導出的註解

ExcelAttribute.java

 

Java代碼 收藏代碼

    package com.mango.insure.common.annotation;  
      
    import java.lang.annotation.Retention;  
    import java.lang.annotation.RetentionPolicy;  
    import java.lang.annotation.Target;  
      
    /** 
     * Excel配置註解自定義接口 
     *  
     * @author jiaxingHuang 
     * @version 1.0 2014-08-20 
     * @since 1.0 
     */  
    @Retention(RetentionPolicy.RUNTIME)  
    @Target({ java.lang.annotation.ElementType.FIELD })  
    public @interface ExcelAttribute {  
      
        /** 
         * Excel中的列名 
         *  
         * @return 
         */  
        public abstract String name();  
      
        /** 
         * 列名對應的A,B,C,D...,不指定按照默認順序排序 
         *  
         * @return 
         */  
        public abstract String column() default "";  
      
        /** 
         * 提示信息 
         *  
         * @return 
         */  
        public abstract String prompt() default "";  
      
        /** 
         * 設置只能選擇不能輸入的列內容 
         *  
         * @return 
         */  
        public abstract String[] combo() default {};  
      
        /** 
         * 是否導出數據 
         *  
         * @return 
         */  
        public abstract boolean isExport() default true;  
      
        /** 
         * 是否爲重要字段(整列標紅,着重顯示) 
         *  
         * @return 
         */  
        public abstract boolean isMark() default false;  
      
        /** 
         * 是否合計當前列 
         *  
         * @return 
         */  
        public abstract boolean isSum() default false;  
    }  

然後再編寫excel導入、導入所需要到的工具類

ExcelUtil.java

Java代碼 收藏代碼

    package com.mango.insure.common.utils;  
      
    import java.io.InputStream;  
    import java.io.OutputStream;  
    import java.io.Serializable;  
    import java.lang.reflect.Field;  
    import java.math.BigDecimal;  
    import java.text.SimpleDateFormat;  
    import java.util.ArrayList;  
    import java.util.Date;  
    import java.util.HashMap;  
    import java.util.Iterator;  
    import java.util.List;  
    import java.util.Locale;  
    import java.util.Map;  
      
    import org.apache.commons.lang3.StringUtils;  
    import org.apache.poi.hssf.usermodel.DVConstraint;  
    import org.apache.poi.hssf.usermodel.HSSFCell;  
    import org.apache.poi.hssf.usermodel.HSSFCellStyle;  
    import org.apache.poi.hssf.usermodel.HSSFDataValidation;  
    import org.apache.poi.hssf.usermodel.HSSFFont;  
    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.ss.usermodel.Cell;  
    import org.apache.poi.ss.util.CellRangeAddressList;  
      
    import com.mango.core.common.util.BigDecimalUtils;  
    import com.mango.core.common.util.DateUtils;  
    import com.mango.core.enums.CalculateType;  
    import com.mango.insure.common.annotation.ExcelAttribute;  
    import com.mango.insure.common.exception.ExcelException;  
      
    /** 
     * excel導入導出工具類 
     *  
     * @author jiaxingHuang 
     * @version 1.0 2014-08-20 
     * @since 1.0 
     */  
    public class ExcelUtil<T> implements Serializable {  
      
        private static final long serialVersionUID = 551970754610248636L;  
      
        private Class<T> clazz;  
      
        public ExcelUtil(Class<T> clazz) {  
            this.clazz = clazz;  
        }  
      
        /** 
         * 將excel表單數據源的數據導入到list 
         *  
         * @param sheetName 
         *            工作表的名稱 
         * @param output 
         *            java輸入流 
         */  
        public List<T> getExcelToList(String sheetName, InputStream input) {  
            List<T> list = new ArrayList<T>();  
            try {  
                HSSFWorkbook book = new HSSFWorkbook(input);  
                HSSFSheet sheet = null;  
                // 如果指定sheet名,則取指定sheet中的內容.  
                if (StringUtils.isNotBlank(sheetName)) {  
                    sheet = book.getSheet(sheetName);  
                }  
                // 如果傳入的sheet名不存在則默認指向第1個sheet.  
                if (sheet == null) {  
                    sheet = book.getSheetAt(0);  
                }  
                // 得到數據的行數  
                int rows = sheet.getLastRowNum();  
                // 有數據時才處理  
                if (rows > 0) {  
                    // 得到類的所有field  
                    Field[] allFields = clazz.getDeclaredFields();  
                    // 定義一個map用於存放列的序號和field  
                    Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();  
                    for (int i = 0, index = 0; i < allFields.length; i++) {  
                        Field field = allFields[i];  
                        // 將有註解的field存放到map中  
                        if (field.isAnnotationPresent(ExcelAttribute.class)) {  
                            // 設置類的私有字段屬性可訪問  
                            field.setAccessible(true);  
                            fieldsMap.put(index, field);  
                            index++;  
                        }  
                    }  
                    // 從第2行開始取數據,默認第一行是表頭  
                    for (int i = 1, len = rows; i < len; i++) {  
                        // 得到一行中的所有單元格對象.  
                        HSSFRow row = sheet.getRow(i);  
                        Iterator<Cell> cells = row.cellIterator();  
                        T entity = null;  
                        int index = 0;  
                        while (cells.hasNext()) {  
                            // 單元格中的內容.  
                            String c = cells.next().getStringCellValue();  
                            if (!StringUtils.isNotBlank(c)) {  
                                continue;  
                            }  
                            if (c.indexOf("合計:") != -1) {  
                                continue;  
                            }  
                            // 如果不存在實例則新建  
                            entity = (entity == null ? clazz.newInstance() : entity);  
                            // 從map中得到對應列的field  
                            Field field = fieldsMap.get(index);  
                            if (field == null) {  
                                continue;  
                            }  
                            // 取得類型,並根據對象類型設置值.  
                            Class<?> fieldType = field.getType();  
                            if (fieldType == null) {  
                                continue;  
                            }  
                            if (String.class == fieldType) {  
                                field.set(entity, String.valueOf(c));  
                            } else if (BigDecimal.class == fieldType) {  
                                c = c.indexOf("%") != -1 ? c.replace("%", "") : c;  
                                field.set(entity, BigDecimal.valueOf(Double.valueOf(c)));  
                            } else if (Date.class == fieldType) {  
                                field.set(entity, DateUtils.parseDate(c));  
                            } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {  
                                field.set(entity, Integer.parseInt(c));  
                            } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {  
                                field.set(entity, Long.valueOf(c));  
                            } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {  
                                field.set(entity, Float.valueOf(c));  
                            } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {  
                                field.set(entity, Short.valueOf(c));  
                            } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {  
                                field.set(entity, Double.valueOf(c));  
                            } else if (Character.TYPE == fieldType) {  
                                if ((c != null) && (c.length() > 0)) {  
                                    field.set(entity, Character.valueOf(c.charAt(0)));  
                                }  
                            }  
                            index++;  
      
                        }  
                        if (entity != null) {  
                            list.add(entity);  
                        }  
                    }  
                }  
            } catch (Exception e) {  
                throw new ExcelException("將excel表單數據源的數據導入到list異常!", e);  
            }  
            return list;  
        }  
      
        /** 
         * 將list數據源的數據導入到excel表單 
         *  
         * @param list 
         *            數據源 
         * @param sheetName 
         *            工作表的名稱 
         * @param output 
         *            java輸出流 
         */  
        public boolean getListToExcel(List<T> list, String sheetName, OutputStream output) {  
            try {  
                // excel中每個sheet中最多有65536行  
                int sheetSize = 65536;  
                // 得到所有定義字段  
                Field[] allFields = clazz.getDeclaredFields();  
                List<Field> fields = new ArrayList<Field>();  
                // 得到所有field並存放到一個list中  
                for (Field field : allFields) {  
                    if (field.isAnnotationPresent(ExcelAttribute.class)) {  
                        fields.add(field);  
                    }  
                }  
                // 產生工作薄對象  
                HSSFWorkbook workbook = new HSSFWorkbook();  
                // 取出一共有多少個sheet  
                int listSize = 0;  
                if (list != null && list.size() >= 0) {  
                    listSize = list.size();  
                }  
                double sheetNo = Math.ceil(listSize / sheetSize);  
                for (int index = 0; index <= sheetNo; index++) {  
                    // 產生工作表對象  
                    HSSFSheet sheet = workbook.createSheet();  
                    // 設置工作表的名稱.  
                    workbook.setSheetName(index, sheetName + index);  
                    HSSFRow row;  
                    HSSFCell cell;// 產生單元格  
                    row = sheet.createRow(0);// 產生一行  
                    /* *********普通列樣式********* */  
                    HSSFFont font = workbook.createFont();  
                    HSSFCellStyle cellStyle = workbook.createCellStyle();  
                    font.setFontName("Arail narrow"); // 字體  
                    font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 字體寬度  
                    /* *********標紅列樣式********* */  
                    HSSFFont newFont = workbook.createFont();  
                    HSSFCellStyle newCellStyle = workbook.createCellStyle();  
                    newFont.setFontName("Arail narrow"); // 字體  
                    newFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 字體寬度  
                    /* *************創建列頭名稱*************** */  
                    for (int i = 0; i < fields.size(); i++) {  
                        Field field = fields.get(i);  
                        ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);  
                        int col = i;  
                        // 根據指定的順序獲得列號  
                        if (StringUtils.isNotBlank(attr.column())) {  
                            col = getExcelCol(attr.column());  
                        }  
                        // 創建列  
                        cell = row.createCell(col);  
                        if (attr.isMark()) {  
                            newFont.setColor(HSSFFont.COLOR_RED); // 字體顏色  
                            newCellStyle.setFont(newFont);  
                            cell.setCellStyle(newCellStyle);  
                        } else {  
                            font.setColor(HSSFFont.COLOR_NORMAL); // 字體顏色  
                            cellStyle.setFont(font);  
                            cell.setCellStyle(cellStyle);  
                        }  
                        sheet.setColumnWidth(i, (int) ((attr.name().getBytes().length <= 4 ? 6 : attr.name().getBytes().length) * 1.5 * 256));  
                        // 設置列中寫入內容爲String類型  
                        cell.setCellType(HSSFCell.CELL_TYPE_STRING);  
                        // 寫入列名  
                        cell.setCellValue(attr.name());  
                        // 如果設置了提示信息則鼠標放上去提示.  
                        if (StringUtils.isNotBlank(attr.prompt())) {  
                            setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, col, col);  
                        }  
                        // 如果設置了combo屬性則本列只能選擇不能輸入  
                        if (attr.combo().length > 0) {  
                            setHSSFValidation(sheet, attr.combo(), 1, 100, col, col);  
                        }  
                    }  
                    /* *************創建內容列*************** */  
                    font = workbook.createFont();  
                    cellStyle = workbook.createCellStyle();  
                    int startNo = index * sheetSize;  
                    int endNo = Math.min(startNo + sheetSize, listSize);  
                    // 寫入各條記錄,每條記錄對應excel表中的一行  
                    for (int i = startNo; i < endNo; i++) {  
                        row = sheet.createRow(i + 1 - startNo);  
                        T vo = (T) list.get(i); // 得到導出對象.  
                        for (int j = 0; j < fields.size(); j++) {  
                            // 獲得field  
                            Field field = fields.get(j);  
                            // 設置實體類私有屬性可訪問  
                            field.setAccessible(true);  
                            ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);  
                            int col = j;  
                            // 根據指定的順序獲得列號  
                            if (StringUtils.isNotBlank(attr.column())) {  
                                col = getExcelCol(attr.column());  
                            }  
                            // 根據ExcelVOAttribute中設置情況決定是否導出,有些情況需要保持爲空,希望用戶填寫這一列.  
                            if (attr.isExport()) {  
                                // 創建cell  
                                cell = row.createCell(col);  
                                if (attr.isMark()) {  
                                    newFont.setColor(HSSFFont.COLOR_RED); // 字體顏色  
                                    newCellStyle.setFont(newFont);  
                                    cell.setCellStyle(newCellStyle);  
                                } else {  
                                    font.setColor(HSSFFont.COLOR_NORMAL); // 字體顏色  
                                    cellStyle.setFont(font);  
                                    cell.setCellStyle(cellStyle);  
                                }  
                                // 如果數據存在就填入,不存在填入空格  
                                Class<?> classType = (Class<?>) field.getType();  
                                String value = null;  
                                if (field.get(vo) != null && classType.isAssignableFrom(Date.class)) {  
                                    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);  
                                    value = DateUtils.formatDate(sdf.parse(String.valueOf(field.get(vo))));  
                                }  
                                cell.setCellValue(field.get(vo) == null ? "" : value == null ? String.valueOf(field.get(vo)) : value);  
                            }  
                        }  
                    }  
                    /* *************創建合計列*************** */  
                    HSSFRow lastRow = sheet.createRow((short) (sheet.getLastRowNum() + 1));  
                    for (int i = 0; i < fields.size(); i++) {  
                        Field field = fields.get(i);  
                        ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);  
                        if (attr.isSum()) {  
                            int col = i;  
                            // 根據指定的順序獲得列號  
                            if (StringUtils.isNotBlank(attr.column())) {  
                                col = getExcelCol(attr.column());  
                            }  
                            BigDecimal totalNumber = BigDecimal.ZERO;  
                            for (int j = 1, len = (sheet.getLastRowNum() - 1); j < len; j++) {  
                                HSSFRow hssfRow = sheet.getRow(j);  
                                if (hssfRow != null) {  
                                    HSSFCell hssfCell = hssfRow.getCell(col);  
                                    if (hssfCell != null && hssfCell.getCellType() == HSSFCell.CELL_TYPE_STRING  
                                            && ValidateUtil.isFloat(hssfCell.getStringCellValue())) {  
                                        totalNumber = BigDecimalUtils.getValue(totalNumber,  
                                                BigDecimal.valueOf(Double.valueOf(hssfCell.getStringCellValue())), CalculateType.Add);  
                                    }  
                                }  
                            }  
                            HSSFCell sumCell = lastRow.createCell(col);  
                            sumCell.setCellValue(new HSSFRichTextString("合計:" + totalNumber));  
                        }  
                    }  
                }  
                output.flush();  
                workbook.write(output);  
                output.close();  
                return Boolean.TRUE;  
            } catch (Exception e) {  
                throw new ExcelException("將list數據源的數據導入到excel表單異常!", e);  
            }  
      
        }  
      
        /** 
         * 將EXCEL中A,B,C,D,E列映射成0,1,2,3 
         *  
         * @param col 
         */  
        public static int getExcelCol(String col) {  
            col = col.toUpperCase();  
            // 從-1開始計算,字母重1開始運算。這種總數下來算數正好相同。  
            int count = -1;  
            char[] cs = col.toCharArray();  
            for (int i = 0; i < cs.length; i++) {  
                count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);  
            }  
            return count;  
        }  
      
        /** 
         * 設置單元格上提示 
         *  
         * @param sheet 
         *            要設置的sheet. 
         * @param promptTitle 
         *            標題 
         * @param promptContent 
         *            內容 
         * @param firstRow 
         *            開始行 
         * @param endRow 
         *            結束行 
         * @param firstCol 
         *            開始列 
         * @param endCol 
         *            結束列 
         * @return 設置好的sheet. 
         */  
        public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,  
                int firstCol, int endCol) {  
            // 構造constraint對象  
            DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1");  
            // 四個參數分別是:起始行、終止行、起始列、終止列  
            CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);  
            // 數據有效性對象  
            HSSFDataValidation data_validation_view = new HSSFDataValidation(regions, constraint);  
            data_validation_view.createPromptBox(promptTitle, promptContent);  
            sheet.addValidationData(data_validation_view);  
            return sheet;  
        }  
      
        /** 
         * 設置某些列的值只能輸入預製的數據,顯示下拉框. 
         *  
         * @param sheet 
         *            要設置的sheet. 
         * @param textlist 
         *            下拉框顯示的內容 
         * @param firstRow 
         *            開始行 
         * @param endRow 
         *            結束行 
         * @param firstCol 
         *            開始列 
         * @param endCol 
         *            結束列 
         * @return 設置好的sheet. 
         */  
        public static HSSFSheet setHSSFValidation(HSSFSheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) {  
            // 加載下拉列表內容  
            DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);  
            // 設置數據有效性加載在哪個單元格上,四個參數分別是:起始行、終止行、起始列、終止列  
            CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);  
            // 數據有效性對象  
            HSSFDataValidation data_validation_list = new HSSFDataValidation(regions, constraint);  
            sheet.addValidationData(data_validation_list);  
            return sheet;  
        }  
      
    }  

 以上註解類和工具類已經編寫完成了,接下來我們看看如何使用

 首先我們創建一個需要進行導入、導出進行映射的java文件

TestModel.java

 

Java代碼

    package com.mango.insure.test;  
      
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
      
    import com.mango.insure.common.annotation.ExcelAttribute;  
      
    public class TestModel {  
      
        @ExcelAttribute(name = "ID")  
        private Long id;  
      
        @ExcelAttribute(name = "姓名", isMark = true)  
        private String name;  
      
        @ExcelAttribute(name = "年齡", isMark = true)  
        private Integer age;  
      
        @ExcelAttribute(name = "生日")  
        private Date birthday;  
      
        @ExcelAttribute(name = "備註")  
        private String mark;  
      
        public TestModel() {  
        }  
      
        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 Integer getAge() {  
            return age;  
        }  
      
        public void setAge(Integer age) {  
            this.age = age;  
        }  
      
        public Date getBirthday() {  
            return birthday;  
        }  
      
        public void setBirthday(Date birthday) {  
            this.birthday = birthday;  
        }  
      
        public String getMark() {  
            return mark;  
        }  
      
        public void setMark(String mark) {  
            this.mark = mark;  
        }  
      
        @Override  
        public String toString() {  
            return "TestModel [id=" + id + ", name=" + name + ", age=" + age + ", birthday="  
                    + new SimpleDateFormat("yyyy-MM-dd").format(birthday) + ", mark=" + mark + "]";  
        }  
      
    }  

需要進行導入、導出的屬性字段我加上了@ExcelAttribute這個註解類進行配置

現在我們先來測試一下導出好用不

ExportTest.java

    package com.mango.insure.test;  
      
    import java.io.FileOutputStream;  
    import java.util.ArrayList;  
    import java.util.Date;  
    import java.util.List;  
    import java.util.Random;  
      
    import org.junit.Test;  
      
    import com.mango.insure.common.utils.ExcelUtil;  
      
    /** 
     * 測試導出Excel數據 
     *  
     * @author jiaxingHuang 
     * @version 1.0 2014年8月20日 
     *  
     */  
    public class ExportTest {  
      
        @Test  
        public void test() throws Exception {  
            List<TestModel> list = new ArrayList<TestModel>();  
            for (int i = 0; i < 25; i++) {  
                TestModel testModel = new TestModel();  
                testModel.setId(Long.valueOf(i + 1));  
                testModel.setName("黃佳興" + (i + 1));  
                testModel.setAge(Random.class.newInstance().nextInt(100));  
                testModel.setBirthday(new Date());  
                testModel.setMark("黃佳興test" + Random.class.newInstance().nextInt(100));  
                list.add(testModel);  
            }  
            FileOutputStream out = new FileOutputStream("D:\\test.xls");  
            ExcelUtil<TestModel> util1 = new ExcelUtil<TestModel>(TestModel.class);  
            util1.getListToExcel(list, "test信息", out);  
            System.out.println("----執行完畢----");  
        }  
      
    }  

 然後去D盤找下是否有test.xls這個文件


發現裏面所導出的字段跟我預想的一樣,那說明導出已經成功完成了!

接下來我們來試試導入

ImportTest.java

    package com.mango.insure.test;  
      
    import java.io.FileInputStream;  
    import java.util.List;  
      
    import org.junit.Test;  
      
    import com.mango.insure.common.utils.ExcelUtil;  
      
    /** 
     * 測試導入Excel數據 
     *  
     * @author jiaxingHuang 
     * @version 1.0 2014年09月21日 
     *  
     */  
    public class ImportTest {  
      
        @Test  
        public void test() throws Exception {  
            FileInputStream fis = new FileInputStream("D:\\test.xls");  
            ExcelUtil<TestModel> util1 = new ExcelUtil<TestModel>(TestModel.class);  
            List<TestModel> testModels = util1.getExcelToList("test", fis);  
            for (TestModel testModel : testModels) {  
                System.out.println(testModel.toString());  
            }  
            System.out.println("----執行完畢----");  
        }  
      
    }  


 執行完畢後發現所輸出的內容跟我們excel中的內容完全一致,說明我們的導入也已經成功了!發財

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