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中的内容完全一致,说明我们的导入也已经成功了!发财

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值