SpringMvc+jxl实现excel导入导出

对于J2EE项目导入导出Excel是最普通和实用功能,本工具类使用步骤简单,功能强大,只需要对实体类进行简单的注解就能实现导入导出功能,导入导出操作的都是实体对象.

请看一下这个类都有哪些功能:
      * 1.实体属性配置了注解就能导出到excel中,每个属性都对应一列.
      * 2.列名称可以通过注解配置.
      * 3.导出到哪一列可以通过注解配置.
      * 4.鼠标移动到该列时提示信息可以通过注解配置.
      * 5.用注解设置只能下拉选择不能随意填写功能.
      * 6.用注解设置是否只导出标题而不导出内容,这在导出内容作为模板以供用户填写时比较实用.


请看一下效果图:

 

 

请看一下使用步骤:

1.写一个实体类,并设置注解配置.
2.实例化一个ExcelUtil<T>对象,调用exportExcel或importExcel方法.

请看一个demo.

1.写一个实体类,并设置注解配置.

[java]  view plain  copy
  1. package com.tgb.lk.test03;  
  2.   
  3. import com.tgb.lk.util.ExcelVOAttribute;  
  4.   
  5. public class StudentVO {  
  6.     @ExcelVOAttribute(name = "序号", column = "A")  
  7.     private int id;  
  8.   
  9.     @ExcelVOAttribute(name = "姓名", column = "B", isExport = true)  
  10.     private String name;  
  11.   
  12.     @ExcelVOAttribute(name = "年龄", column = "C", prompt = "年龄保密哦!", isExport = false)  
  13.     private int age;  
  14.   
  15.     @ExcelVOAttribute(name = "班级", column = "D", combo = { "五期提高班""六期提高班",  
  16.             "七期提高班" })  
  17.     private String clazz;  
  18.   
  19.     @ExcelVOAttribute(name = "公司", column = "F")  
  20.     private String company;  
  21.   
  22.     //get和set方法(略)...  
  23.   
  24.     @Override  
  25.     public String toString() {  
  26.         return "StudentVO [id=" + id + ", name=" + name + ", company="  
  27.                 + company + ", age=" + age + ", clazz=" + clazz + "]";  
  28.     }  
  29.   
  30. }  

2.实例化一个ExcelUtil<T>对象,调用exportExcel或importExcel方法.
(1)导出

[java]  view plain  copy
  1. package com.tgb.lk.test03;  
  2.   
  3. import java.io.FileNotFoundException;  
  4. import java.io.FileOutputStream;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7.   
  8. import com.tgb.lk.util.ExcelUtil;  
  9.   
  10. /* 
  11.  * 使用步骤: 
  12.  * 1.新建一个类,例如StudentVO. 
  13.  * 2.设置哪些属性需要导出,哪些需要设置提示. 
  14.  * 3.设置实体数据 
  15.  * 4.调用exportExcel方法. 
  16.  */  
  17. public class ExportTest03 {  
  18.     public static void main(String[] args) {  
  19.         // 初始化数据  
  20.         List<StudentVO> list = new ArrayList<StudentVO>();  
  21.   
  22.         StudentVO vo = new StudentVO();  
  23.         vo.setId(1);  
  24.         vo.setName("李坤");  
  25.         vo.setAge(26);  
  26.         vo.setClazz("五期提高班");  
  27.         vo.setCompany("天融信");  
  28.         list.add(vo);  
  29.   
  30.         StudentVO vo2 = new StudentVO();  
  31.         vo2.setId(2);  
  32.         vo2.setName("曹贵生");  
  33.         vo2.setClazz("五期提高班");  
  34.         vo2.setCompany("中银");  
  35.         list.add(vo2);  
  36.   
  37.         StudentVO vo3 = new StudentVO();  
  38.         vo3.setId(3);  
  39.         vo3.setName("柳波");  
  40.         vo3.setClazz("五期提高班");  
  41.         list.add(vo3);  
  42.   
  43.         FileOutputStream out = null;  
  44.         try {  
  45.             out = new FileOutputStream("d:\\success3.xls");  
  46.         } catch (FileNotFoundException e) {  
  47.             e.printStackTrace();  
  48.         }  
  49.         ExcelUtil<StudentVO> util = new ExcelUtil<StudentVO>(StudentVO.class);// 创建工具类.  
  50.         util.exportExcel(list, "学生信息"65536, out);// 导出  
  51.         System.out.println("----执行完毕----------");  
  52.     }  
  53.   
  54. }  

(2)导入

[java]  view plain  copy
  1. package com.tgb.lk.test03;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5. import java.util.List;  
  6.   
  7. import com.tgb.lk.util.ExcelUtil;  
  8.   
  9. public class ImportTest03 {  
  10.     public static void main(String[] args) {  
  11.         FileInputStream fis = null;  
  12.         try {  
  13.             fis = new FileInputStream("d:\\success3.xls");  
  14.             ExcelUtil<StudentVO> util = new ExcelUtil<StudentVO>(  
  15.                     StudentVO.class);// 创建excel工具类  
  16.             List<StudentVO> list = util.importExcel("学生信息0", fis);// 导入  
  17.             System.out.println(list);  
  18.         } catch (FileNotFoundException e) {  
  19.             e.printStackTrace();  
  20.         }  
  21.   
  22.     }  
  23. }  

 

看完使用步骤一定对封装的类迫不及待了吧,请继续往下看:

(1)注解实现类:

[java]  view plain  copy
  1. package com.tgb.lk.util;  
  2.   
  3. import java.lang.annotation.Retention;  
  4. import java.lang.annotation.RetentionPolicy;  
  5. import java.lang.annotation.Target;  
  6.   
  7. @Retention(RetentionPolicy.RUNTIME)  
  8. @Target( { java.lang.annotation.ElementType.FIELD })  
  9. public @interface ExcelVOAttribute {  
  10.   
  11.     /** 
  12.      * 导出到Excel中的名字. 
  13.      */  
  14.     public abstract String name();  
  15.   
  16.     /** 
  17.      * 配置列的名称,对应A,B,C,D.... 
  18.      */  
  19.     public abstract String column();  
  20.   
  21.     /** 
  22.      * 提示信息 
  23.      */  
  24.     public abstract String prompt() default "";  
  25.   
  26.     /** 
  27.      * 设置只能选择不能输入的列内容. 
  28.      */  
  29.     public abstract String[] combo() default {};  
  30.   
  31.     /** 
  32.      * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. 
  33.      */  
  34.     public abstract boolean isExport() default true;  
  35.   
  36. }  

(2)导入导出封装类:

[java]  view plain  copy
  1. package com.tgb.lk.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.lang.reflect.Field;  
  7. import java.util.ArrayList;  
  8. import java.util.HashMap;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11.   
  12. import org.apache.poi.hssf.usermodel.DVConstraint;  
  13. import org.apache.poi.hssf.usermodel.HSSFCell;  
  14. import org.apache.poi.hssf.usermodel.HSSFDataValidation;  
  15. import org.apache.poi.hssf.usermodel.HSSFRow;  
  16. import org.apache.poi.hssf.usermodel.HSSFSheet;  
  17. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  18. import org.apache.poi.ss.util.CellRangeAddressList;  
  19.   
  20. /* 
  21.  * ExcelUtil工具类实现功能: 
  22.  * 导出时传入list<T>,即可实现导出为一个excel,其中每个对象T为Excel中的一条记录. 
  23.  * 导入时读取excel,得到的结果是一个list<T>.T是自己定义的对象. 
  24.  * 需要导出的实体对象只需简单配置注解就能实现灵活导出,通过注解您可以方便实现下面功能: 
  25.  * 1.实体属性配置了注解就能导出到excel中,每个属性都对应一列. 
  26.  * 2.列名称可以通过注解配置. 
  27.  * 3.导出到哪一列可以通过注解配置. 
  28.  * 4.鼠标移动到该列时提示信息可以通过注解配置. 
  29.  * 5.用注解设置只能下拉选择不能随意填写功能. 
  30.  * 6.用注解设置是否只导出标题而不导出内容,这在导出内容作为模板以供用户填写时比较实用. 
  31.  * 本工具类以后可能还会加功能,请关注我的博客: http://blog.csdn.net/lk_blog 
  32.  */  
  33. public class ExcelUtil<T> {  
  34.     Class<T> clazz;  
  35.   
  36.     public ExcelUtil(Class<T> clazz) {  
  37.         this.clazz = clazz;  
  38.     }  
  39.   
  40.     public List<T> importExcel(String sheetName, InputStream input) {  
  41.         List<T> list = new ArrayList<T>();  
  42.         try {  
  43.             HSSFWorkbook workbook = new HSSFWorkbook(input);  
  44.             HSSFSheet sheet = workbook.getSheet(sheetName);  
  45.             if (!sheetName.trim().equals("")) {  
  46.                 sheet = workbook.getSheet(sheetName);// 如果指定sheet名,则取指定sheet中的内容.  
  47.             }  
  48.             if (sheet == null) {  
  49.                 sheet = workbook.getSheetAt(0); // 如果传入的sheet名不存在则默认指向第1个sheet.  
  50.             }  
  51.             int rows = sheet.getPhysicalNumberOfRows();  
  52.   
  53.             if (rows > 0) {// 有数据时才处理  
  54.                 Field[] allFields = clazz.getDeclaredFields();// 得到类的所有field.  
  55.                 Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();// 定义一个map用于存放列的序号和field.  
  56.                 for (Field field : allFields) {  
  57.                     // 将有注解的field存放到map中.  
  58.                     if (field.isAnnotationPresent(ExcelVOAttribute.class)) {  
  59.                         ExcelVOAttribute attr = field  
  60.                                 .getAnnotation(ExcelVOAttribute.class);  
  61.                         int col = getExcelCol(attr.column());// 获得列号  
  62.                         // System.out.println(col + "====" + field.getName());  
  63.                         field.setAccessible(true);// 设置类的私有字段属性可访问.  
  64.                         fieldsMap.put(col, field);  
  65.                     }  
  66.                 }  
  67.                 for (int i = 1; i < rows; i++) {// 从第2行开始取数据,默认第一行是表头.  
  68.                     HSSFRow row = sheet.getRow(i);  
  69.                     int cellNum = row.getPhysicalNumberOfCells();  
  70.                     T entity = null;  
  71.                     for (int j = 0; j < cellNum; j++) {  
  72.                         HSSFCell cell = row.getCell(j);  
  73.                         if (cell == null) {  
  74.                             continue;  
  75.                         }  
  76.                         String c = cell.getStringCellValue();  
  77.                         System.out.println(c);  
  78.                         if (c.equals("")) {  
  79.                             continue;  
  80.                         }  
  81.                         entity = (entity == null ? clazz.newInstance() : entity);// 如果不存在实例则新建.  
  82.                         // System.out.println(cells[j].getContents());  
  83.                         Field field = fieldsMap.get(j);// 从map中得到对应列的field.  
  84.                         // 取得类型,并根据对象类型设置值.  
  85.                         Class<?> fieldType = field.getType();  
  86.                         if (String.class == fieldType) {  
  87.                             field.set(entity, String.valueOf(c));  
  88.                         } else if ((Integer.TYPE == fieldType)  
  89.                                 || (Integer.class == fieldType)) {  
  90.                             field.set(entity, Integer.parseInt(c));  
  91.                         } else if ((Long.TYPE == fieldType)  
  92.                                 || (Long.class == fieldType)) {  
  93.                             field.set(entity, Long.valueOf(c));  
  94.                         } else if ((Float.TYPE == fieldType)  
  95.                                 || (Float.class == fieldType)) {  
  96.                             field.set(entity, Float.valueOf(c));  
  97.                         } else if ((Short.TYPE == fieldType)  
  98.                                 || (Short.class == fieldType)) {  
  99.                             field.set(entity, Short.valueOf(c));  
  100.                         } else if ((Double.TYPE == fieldType)  
  101.                                 || (Double.class == fieldType)) {  
  102.                             field.set(entity, Double.valueOf(c));  
  103.                         } else if (Character.TYPE == fieldType) {  
  104.                             if ((c != null) && (c.length() > 0)) {  
  105.                                 field.set(entity, Character  
  106.                                         .valueOf(c.charAt(0)));  
  107.                             }  
  108.                         }  
  109.   
  110.                     }  
  111.                     if (entity != null) {  
  112.                         list.add(entity);  
  113.                     }  
  114.                 }  
  115.                 //以下内容为引用jxl-xx.jar时的代码,因为jxl对office2010不支持,所以改为使用poi读写方式.  
  116.                 // HSSFRow[] cells = sheet.getRow(i); // 得到一行中的所有单元格对象.  
  117.                 // T entity = null;  
  118.                 // for (int j = 0; j < cells.length; j++) {  
  119.                 // String c = cells[j].getContents();// 单元格中的内容.  
  120.                 // if (c.equals("")) {  
  121.                 // continue;  
  122.                 // }  
  123.                 // entity = (entity == null ? clazz.newInstance() : entity);//  
  124.                 // 如果不存在实例则新建.  
  125.                 // // System.out.println(cells[j].getContents());  
  126.                 // Field field = fieldsMap.get(j);// 从map中得到对应列的field.  
  127.                 // // 取得类型,并根据对象类型设置值.  
  128.                 // Class<?> fieldType = field.getType();  
  129.                 // if ((Integer.TYPE == fieldType)  
  130.                 // || (Integer.class == fieldType)) {  
  131.                 // field.set(entity, Integer.parseInt(c));  
  132.                 // } else if (String.class == fieldType) {  
  133.                 // field.set(entity, String.valueOf(c));  
  134.                 // } else if ((Long.TYPE == fieldType)  
  135.                 // || (Long.class == fieldType)) {  
  136.                 // field.set(entity, Long.valueOf(c));  
  137.                 // } else if ((Float.TYPE == fieldType)  
  138.                 // || (Float.class == fieldType)) {  
  139.                 // field.set(entity, Float.valueOf(c));  
  140.                 // } else if ((Short.TYPE == fieldType)  
  141.                 // || (Short.class == fieldType)) {  
  142.                 // field.set(entity, Short.valueOf(c));  
  143.                 // } else if ((Double.TYPE == fieldType)  
  144.                 // || (Double.class == fieldType)) {  
  145.                 // field.set(entity, Double.valueOf(c));  
  146.                 // } else if (Character.TYPE == fieldType) {  
  147.                 // if ((c != null) && (c.length() > 0)) {  
  148.                 // field.set(entity, Character  
  149.                 // .valueOf(c.charAt(0)));  
  150.                 // }  
  151.                 // }  
  152.                 //  
  153.                 // }  
  154.                 // if (entity != null) {  
  155.                 // list.add(entity);  
  156.                 // }  
  157.                 // }  
  158.             }  
  159.   
  160.         } catch (IOException e) {  
  161.             e.printStackTrace();  
  162.         } catch (InstantiationException e) {  
  163.             e.printStackTrace();  
  164.         } catch (IllegalAccessException e) {  
  165.             e.printStackTrace();  
  166.         } catch (IllegalArgumentException e) {  
  167.             e.printStackTrace();  
  168.         }  
  169.         return list;  
  170.     }  
  171.   
  172.     /** 
  173.      * 对list数据源将其里面的数据导入到excel表单 
  174.      *  
  175.      * @param sheetName 
  176.      *            工作表的名称 
  177.      * @param sheetSize 
  178.      *            每个sheet中数据的行数,此数值必须小于65536 
  179.      * @param output 
  180.      *            java输出流 
  181.      */  
  182.     public boolean exportExcel(List<T> list, String sheetName, int sheetSize,  
  183.             OutputStream output) {  
  184.   
  185.         Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段  
  186.         List<Field> fields = new ArrayList<Field>();  
  187.         // 得到所有field并存放到一个list中.  
  188.         for (Field field : allFields) {  
  189.             if (field.isAnnotationPresent(ExcelVOAttribute.class)) {  
  190.                 fields.add(field);  
  191.             }  
  192.         }  
  193.   
  194.         HSSFWorkbook workbook = new HSSFWorkbook();// 产生工作薄对象  
  195.   
  196.         // excel2003中每个sheet中最多有65536行,为避免产生错误所以加这个逻辑.  
  197.         if (sheetSize > 65536 || sheetSize < 1) {  
  198.             sheetSize = 65536;  
  199.         }  
  200.         double sheetNo = Math.ceil(list.size() / sheetSize);// 取出一共有多少个sheet.  
  201.         for (int index = 0; index <= sheetNo; index++) {  
  202.             HSSFSheet sheet = workbook.createSheet();// 产生工作表对象  
  203.             if (sheetNo == 0) {  
  204.                 workbook.setSheetName(index, sheetName);  
  205.             } else {  
  206.                 workbook.setSheetName(index, sheetName + index);// 设置工作表的名称.  
  207.             }  
  208.             HSSFRow row;  
  209.             HSSFCell cell;// 产生单元格  
  210.   
  211.             row = sheet.createRow(0);// 产生一行  
  212.             // 写入各个字段的列头名称  
  213.             for (int i = 0; i < fields.size(); i++) {  
  214.                 Field field = fields.get(i);  
  215.                 ExcelVOAttribute attr = field  
  216.                         .getAnnotation(ExcelVOAttribute.class);  
  217.                 int col = getExcelCol(attr.column());// 获得列号  
  218.                 cell = row.createCell(col);// 创建列  
  219.                 cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型  
  220.                 cell.setCellValue(attr.name());// 写入列名  
  221.   
  222.                 // 如果设置了提示信息则鼠标放上去提示.  
  223.                 if (!attr.prompt().trim().equals("")) {  
  224.                     setHSSFPrompt(sheet, "", attr.prompt(), 1100, col, col);// 这里默认设了2-101列提示.  
  225.                 }  
  226.                 // 如果设置了combo属性则本列只能选择不能输入  
  227.                 if (attr.combo().length > 0) {  
  228.                     setHSSFValidation(sheet, attr.combo(), 1100, col, col);// 这里默认设了2-101列只能选择不能输入.  
  229.                 }  
  230.             }  
  231.   
  232.             int startNo = index * sheetSize;  
  233.             int endNo = Math.min(startNo + sheetSize, list.size());  
  234.             // 写入各条记录,每条记录对应excel表中的一行  
  235.             for (int i = startNo; i < endNo; i++) {  
  236.                 row = sheet.createRow(i + 1 - startNo);  
  237.                 T vo = (T) list.get(i); // 得到导出对象.  
  238.                 for (int j = 0; j < fields.size(); j++) {  
  239.                     Field field = fields.get(j);// 获得field.  
  240.                     field.setAccessible(true);// 设置实体类私有属性可访问  
  241.                     ExcelVOAttribute attr = field  
  242.                             .getAnnotation(ExcelVOAttribute.class);  
  243.                     try {  
  244.                         // 根据ExcelVOAttribute中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.  
  245.                         if (attr.isExport()) {  
  246.                             cell = row.createCell(getExcelCol(attr.column()));// 创建cell  
  247.                             cell.setCellType(HSSFCell.CELL_TYPE_STRING);  
  248.                             cell.setCellValue(field.get(vo) == null ? ""  
  249.                                     : String.valueOf(field.get(vo)));// 如果数据存在就填入,不存在填入空格.  
  250.                         }  
  251.                     } catch (IllegalArgumentException e) {  
  252.                         e.printStackTrace();  
  253.                     } catch (IllegalAccessException e) {  
  254.                         e.printStackTrace();  
  255.                     }  
  256.                 }  
  257.             }  
  258.   
  259.         }  
  260.         try {  
  261.             output.flush();  
  262.             workbook.write(output);  
  263.             output.close();  
  264.             return true;  
  265.         } catch (IOException e) {  
  266.             e.printStackTrace();  
  267.             System.out.println("Output is closed ");  
  268.             return false;  
  269.         }  
  270.   
  271.     }  
  272.   
  273.     /** 
  274.      * 将EXCEL中A,B,C,D,E列映射成0,1,2,3 
  275.      *  
  276.      * @param col 
  277.      */  
  278.     public static int getExcelCol(String col) {  
  279.         col = col.toUpperCase();  
  280.         // 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。  
  281.         int count = -1;  
  282.         char[] cs = col.toCharArray();  
  283.         for (int i = 0; i < cs.length; i++) {  
  284.             count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);  
  285.         }  
  286.         return count;  
  287.     }  
  288.   
  289.     /** 
  290.      * 设置单元格上提示 
  291.      *  
  292.      * @param sheet 
  293.      *            要设置的sheet. 
  294.      * @param promptTitle 
  295.      *            标题 
  296.      * @param promptContent 
  297.      *            内容 
  298.      * @param firstRow 
  299.      *            开始行 
  300.      * @param endRow 
  301.      *            结束行 
  302.      * @param firstCol 
  303.      *            开始列 
  304.      * @param endCol 
  305.      *            结束列 
  306.      * @return 设置好的sheet. 
  307.      */  
  308.     public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle,  
  309.             String promptContent, int firstRow, int endRow, int firstCol,  
  310.             int endCol) {  
  311.         // 构造constraint对象  
  312.         DVConstraint constraint = DVConstraint  
  313.                 .createCustomFormulaConstraint("DD1");  
  314.         // 四个参数分别是:起始行、终止行、起始列、终止列  
  315.         CellRangeAddressList regions = new CellRangeAddressList(firstRow,  
  316.                 endRow, firstCol, endCol);  
  317.         // 数据有效性对象  
  318.         HSSFDataValidation data_validation_view = new HSSFDataValidation(  
  319.                 regions, constraint);  
  320.         data_validation_view.createPromptBox(promptTitle, promptContent);  
  321.         sheet.addValidationData(data_validation_view);  
  322.         return sheet;  
  323.     }  
  324.   
  325.     /** 
  326.      * 设置某些列的值只能输入预制的数据,显示下拉框. 
  327.      *  
  328.      * @param sheet 
  329.      *            要设置的sheet. 
  330.      * @param textlist 
  331.      *            下拉框显示的内容 
  332.      * @param firstRow 
  333.      *            开始行 
  334.      * @param endRow 
  335.      *            结束行 
  336.      * @param firstCol 
  337.      *            开始列 
  338.      * @param endCol 
  339.      *            结束列 
  340.      * @return 设置好的sheet. 
  341.      */  
  342.     public static HSSFSheet setHSSFValidation(HSSFSheet sheet,  
  343.             String[] textlist, int firstRow, int endRow, int firstCol,  
  344.             int endCol) {  
  345.         // 加载下拉列表内容  
  346.         DVConstraint constraint = DVConstraint  
  347.                 .createExplicitListConstraint(textlist);  
  348.         // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列  
  349.         CellRangeAddressList regions = new CellRangeAddressList(firstRow,  
  350.                 endRow, firstCol, endCol);  
  351.         // 数据有效性对象  
  352.         HSSFDataValidation data_validation_list = new HSSFDataValidation(  
  353.                 regions, constraint);  
  354.         sheet.addValidationData(data_validation_list);  
  355.         return sheet;  
  356.     }  
  357. }  

工具类修订版(2013-10-23):

[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.io.OutputStream;  
  4. import java.lang.reflect.Field;  
  5. import java.util.ArrayList;  
  6. import java.util.HashMap;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9.   
  10. import org.apache.poi.hssf.usermodel.DVConstraint;  
  11. import org.apache.poi.hssf.usermodel.HSSFCell;  
  12. import org.apache.poi.hssf.usermodel.HSSFCellStyle;  
  13. import org.apache.poi.hssf.usermodel.HSSFDataValidation;  
  14. import org.apache.poi.hssf.usermodel.HSSFRow;  
  15. import org.apache.poi.hssf.usermodel.HSSFSheet;  
  16. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  17. import org.apache.poi.hssf.util.HSSFColor;  
  18. import org.apache.poi.ss.util.CellRangeAddressList;  
  19.   
  20. /* 
  21.  * ExcelUtil工具类实现功能: 
  22.  * 导出时传入list<T>,即可实现导出为一个excel,其中每个对象T为Excel中的一条记录. 
  23.  * 导入时读取excel,得到的结果是一个list<T>.T是自己定义的对象. 
  24.  * 需要导出的实体对象只需简单配置注解就能实现灵活导出,通过注解您可以方便实现下面功能: 
  25.  * 1.实体属性配置了注解就能导出到excel中,每个属性都对应一列. 
  26.  * 2.列名称可以通过注解配置. 
  27.  * 3.导出到哪一列可以通过注解配置. 
  28.  * 4.鼠标移动到该列时提示信息可以通过注解配置. 
  29.  * 5.用注解设置只能下拉选择不能随意填写功能. 
  30.  * 6.用注解设置是否只导出标题而不导出内容,这在导出内容作为模板以供用户填写时比较实用. 
  31.  * 本工具类以后可能还会加功能,请关注我的博客: http://blog.csdn.net/lk_blog 
  32.  */  
  33. public class ExcelUtil2<T> {  
  34.     Class<T> clazz;  
  35.   
  36.     public ExcelUtil2(Class<T> clazz) {  
  37.         this.clazz = clazz;  
  38.     }  
  39.   
  40.     public List<T> importExcel(String sheetName, InputStream input) {  
  41.         int maxCol = 0;  
  42.         List<T> list = new ArrayList<T>();  
  43.         try {  
  44.             HSSFWorkbook workbook = new HSSFWorkbook(input);  
  45.             HSSFSheet sheet = workbook.getSheet(sheetName);  
  46.             if (!sheetName.trim().equals("")) {  
  47.                 sheet = workbook.getSheet(sheetName);// 如果指定sheet名,则取指定sheet中的内容.  
  48.             }  
  49.             if (sheet == null) {  
  50.                 sheet = workbook.getSheetAt(0); // 如果传入的sheet名不存在则默认指向第1个sheet.  
  51.             }  
  52.             int rows = sheet.getPhysicalNumberOfRows();  
  53.   
  54.             if (rows > 0) {// 有数据时才处理  
  55.                 // Field[] allFields = clazz.getDeclaredFields();// 得到类的所有field.  
  56.                 List<Field> allFields = getMappedFiled(clazz, null);  
  57.   
  58.                 Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();// 定义一个map用于存放列的序号和field.  
  59.                 for (Field field : allFields) {  
  60.                     // 将有注解的field存放到map中.  
  61.                     if (field.isAnnotationPresent(ExcelVOAttribute.class)) {  
  62.                         ExcelVOAttribute attr = field  
  63.                                 .getAnnotation(ExcelVOAttribute.class);  
  64.                         int col = getExcelCol(attr.column());// 获得列号  
  65.                         maxCol = Math.max(col, maxCol);  
  66.                         // System.out.println(col + "====" + field.getName());  
  67.                         field.setAccessible(true);// 设置类的私有字段属性可访问.  
  68.                         fieldsMap.put(col, field);  
  69.                     }  
  70.                 }  
  71.                 for (int i = 1; i < rows; i++) {// 从第2行开始取数据,默认第一行是表头.  
  72.                     HSSFRow row = sheet.getRow(i);  
  73.                     // int cellNum = row.getPhysicalNumberOfCells();  
  74.                     // int cellNum = row.getLastCellNum();  
  75.                     int cellNum = maxCol;  
  76.                     T entity = null;  
  77.                     for (int j = 0; j < cellNum; j++) {  
  78.                         HSSFCell cell = row.getCell(j);  
  79.                         if (cell == null) {  
  80.                             continue;  
  81.                         }  
  82.                         int cellType = cell.getCellType();  
  83.                         String c = "";  
  84.                         if (cellType == HSSFCell.CELL_TYPE_NUMERIC) {  
  85.                             c = String.valueOf(cell.getNumericCellValue());  
  86.                         } else if (cellType == HSSFCell.CELL_TYPE_BOOLEAN) {  
  87.                             c = String.valueOf(cell.getBooleanCellValue());  
  88.                         } else {  
  89.                             c = cell.getStringCellValue();  
  90.                         }  
  91.                         if (c == null || c.equals("")) {  
  92.                             continue;  
  93.                         }  
  94.                         entity = (entity == null ? clazz.newInstance() : entity);// 如果不存在实例则新建.  
  95.                         // System.out.println(cells[j].getContents());  
  96.                         Field field = fieldsMap.get(j);// 从map中得到对应列的field.  
  97.                         if (field==null) {  
  98.                             continue;  
  99.                         }  
  100.                         // 取得类型,并根据对象类型设置值.  
  101.                         Class<?> fieldType = field.getType();  
  102.                         if (String.class == fieldType) {  
  103.                             field.set(entity, String.valueOf(c));  
  104.                         } else if ((Integer.TYPE == fieldType)  
  105.                                 || (Integer.class == fieldType)) {  
  106.                             field.set(entity, Integer.parseInt(c));  
  107.                         } else if ((Long.TYPE == fieldType)  
  108.                                 || (Long.class == fieldType)) {  
  109.                             field.set(entity, Long.valueOf(c));  
  110.                         } else if ((Float.TYPE == fieldType)  
  111.                                 || (Float.class == fieldType)) {  
  112.                             field.set(entity, Float.valueOf(c));  
  113.                         } else if ((Short.TYPE == fieldType)  
  114.                                 || (Short.class == fieldType)) {  
  115.                             field.set(entity, Short.valueOf(c));  
  116.                         } else if ((Double.TYPE == fieldType)  
  117.                                 || (Double.class == fieldType)) {  
  118.                             field.set(entity, Double.valueOf(c));  
  119.                         } else if (Character.TYPE == fieldType) {  
  120.                             if ((c != null) && (c.length() > 0)) {  
  121.                                 field.set(entity, Character  
  122.                                         .valueOf(c.charAt(0)));  
  123.                             }  
  124.                         }  
  125.   
  126.                     }  
  127.                     if (entity != null) {  
  128.                         list.add(entity);  
  129.                     }  
  130.                 }  
  131.             }  
  132.   
  133.         } catch (IOException e) {  
  134.             e.printStackTrace();  
  135.         } catch (InstantiationException e) {  
  136.             e.printStackTrace();  
  137.         } catch (IllegalAccessException e) {  
  138.             e.printStackTrace();  
  139.         } catch (IllegalArgumentException e) {  
  140.             e.printStackTrace();  
  141.         }  
  142.         return list;  
  143.     }  
  144.   
  145.     /** 
  146.      * 对list数据源将其里面的数据导入到excel表单 
  147.      *  
  148.      * @param sheetName 
  149.      *            工作表的名称 
  150.      * @param output 
  151.      *            java输出流 
  152.      */  
  153.     public boolean exportExcel(List<T> lists[], String sheetNames[],  
  154.             OutputStream output) {  
  155.         if (lists.length != sheetNames.length) {  
  156.             System.out.println("数组长度不一致");  
  157.             return false;  
  158.         }  
  159.   
  160.         HSSFWorkbook workbook = new HSSFWorkbook();// 产生工作薄对象  
  161.   
  162.         for (int ii = 0; ii < lists.length; ii++) {  
  163.             List<T> list = lists[ii];  
  164.             String sheetName = sheetNames[ii];  
  165.   
  166.             List<Field> fields = getMappedFiled(clazz, null);  
  167.   
  168.             HSSFSheet sheet = workbook.createSheet();// 产生工作表对象  
  169.   
  170.             workbook.setSheetName(ii, sheetName);  
  171.   
  172.             HSSFRow row;  
  173.             HSSFCell cell;// 产生单元格  
  174.             HSSFCellStyle style = workbook.createCellStyle();  
  175.             style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);  
  176.             style.setFillBackgroundColor(HSSFColor.GREY_40_PERCENT.index);  
  177.             row = sheet.createRow(0);// 产生一行  
  178.             // 写入各个字段的列头名称  
  179.             for (int i = 0; i < fields.size(); i++) {  
  180.                 Field field = fields.get(i);  
  181.                 ExcelVOAttribute attr = field  
  182.                         .getAnnotation(ExcelVOAttribute.class);  
  183.                 int col = getExcelCol(attr.column());// 获得列号  
  184.                 cell = row.createCell(col);// 创建列  
  185.                 cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型  
  186.                 cell.setCellValue(attr.name());// 写入列名  
  187.   
  188.                 // 如果设置了提示信息则鼠标放上去提示.  
  189.                 if (!attr.prompt().trim().equals("")) {  
  190.                     setHSSFPrompt(sheet, "", attr.prompt(), 1100, col, col);// 这里默认设了2-101列提示.  
  191.                 }  
  192.                 // 如果设置了combo属性则本列只能选择不能输入  
  193.                 if (attr.combo().length > 0) {  
  194.                     setHSSFValidation(sheet, attr.combo(), 1100, col, col);// 这里默认设了2-101列只能选择不能输入.  
  195.                 }  
  196.                 cell.setCellStyle(style);  
  197.             }  
  198.   
  199.             int startNo = 0;  
  200.             int endNo = list.size();  
  201.             // 写入各条记录,每条记录对应excel表中的一行  
  202.             for (int i = startNo; i < endNo; i++) {  
  203.                 row = sheet.createRow(i + 1 - startNo);  
  204.                 T vo = (T) list.get(i); // 得到导出对象.  
  205.                 for (int j = 0; j < fields.size(); j++) {  
  206.                     Field field = fields.get(j);// 获得field.  
  207.                     field.setAccessible(true);// 设置实体类私有属性可访问  
  208.                     ExcelVOAttribute attr = field  
  209.                             .getAnnotation(ExcelVOAttribute.class);  
  210.                     try {  
  211.                         // 根据ExcelVOAttribute中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.  
  212.                         if (attr.isExport()) {  
  213.                             cell = row.createCell(getExcelCol(attr.column()));// 创建cell  
  214.                             cell.setCellType(HSSFCell.CELL_TYPE_STRING);  
  215.                             cell.setCellValue(field.get(vo) == null ? ""  
  216.                                     : String.valueOf(field.get(vo)));// 如果数据存在就填入,不存在填入空格.  
  217.                         }  
  218.                     } catch (IllegalArgumentException e) {  
  219.                         e.printStackTrace();  
  220.                     } catch (IllegalAccessException e) {  
  221.                         e.printStackTrace();  
  222.                     }  
  223.                 }  
  224.             }  
  225.         }  
  226.   
  227.         try {  
  228.             output.flush();  
  229.             workbook.write(output);  
  230.             output.close();  
  231.             return true;  
  232.         } catch (IOException e) {  
  233.             e.printStackTrace();  
  234.             System.out.println("Output is closed ");  
  235.             return false;  
  236.         }  
  237.   
  238.     }  
  239.   
  240.     /** 
  241.      * 对list数据源将其里面的数据导入到excel表单 
  242.      *  
  243.      * @param sheetName 
  244.      *            工作表的名称 
  245.      * @param sheetSize 
  246.      *            每个sheet中数据的行数,此数值必须小于65536 
  247.      * @param output 
  248.      *            java输出流 
  249.      */  
  250.     public boolean exportExcel(List<T> list, String sheetName,  
  251.             OutputStream output) {  
  252.         List<T>[] lists = new ArrayList[1];  
  253.         lists[0] = list;  
  254.   
  255.         String[] sheetNames = new String[1];  
  256.         sheetNames[0] = sheetName;  
  257.   
  258.         return exportExcel(lists, sheetNames, output);  
  259.     }  
  260.   
  261.     /** 
  262.      * 将EXCEL中A,B,C,D,E列映射成0,1,2,3 
  263.      *  
  264.      * @param col 
  265.      */  
  266.     public static int getExcelCol(String col) {  
  267.         col = col.toUpperCase();  
  268.         // 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。  
  269.         int count = -1;  
  270.         char[] cs = col.toCharArray();  
  271.         for (int i = 0; i < cs.length; i++) {  
  272.             count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);  
  273.         }  
  274.         return count;  
  275.     }  
  276.   
  277.     /** 
  278.      * 设置单元格上提示 
  279.      *  
  280.      * @param sheet 
  281.      *            要设置的sheet. 
  282.      * @param promptTitle 
  283.      *            标题 
  284.      * @param promptContent 
  285.      *            内容 
  286.      * @param firstRow 
  287.      *            开始行 
  288.      * @param endRow 
  289.      *            结束行 
  290.      * @param firstCol 
  291.      *            开始列 
  292.      * @param endCol 
  293.      *            结束列 
  294.      * @return 设置好的sheet. 
  295.      */  
  296.     public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle,  
  297.             String promptContent, int firstRow, int endRow, int firstCol,  
  298.             int endCol) {  
  299.         // 构造constraint对象  
  300.         DVConstraint constraint = DVConstraint  
  301.                 .createCustomFormulaConstraint("DD1");  
  302.         // 四个参数分别是:起始行、终止行、起始列、终止列  
  303.         CellRangeAddressList regions = new CellRangeAddressList(firstRow,  
  304.                 endRow, firstCol, endCol);  
  305.         // 数据有效性对象  
  306.         HSSFDataValidation data_validation_view = new HSSFDataValidation(  
  307.                 regions, constraint);  
  308.         data_validation_view.createPromptBox(promptTitle, promptContent);  
  309.         sheet.addValidationData(data_validation_view);  
  310.         return sheet;  
  311.     }  
  312.   
  313.     /** 
  314.      * 设置某些列的值只能输入预制的数据,显示下拉框. 
  315.      *  
  316.      * @param sheet 
  317.      *            要设置的sheet. 
  318.      * @param textlist 
  319.      *            下拉框显示的内容 
  320.      * @param firstRow 
  321.      *            开始行 
  322.      * @param endRow 
  323.      *            结束行 
  324.      * @param firstCol 
  325.      *            开始列 
  326.      * @param endCol 
  327.      *            结束列 
  328.      * @return 设置好的sheet. 
  329.      */  
  330.     public static HSSFSheet setHSSFValidation(HSSFSheet sheet,  
  331.             String[] textlist, int firstRow, int endRow, int firstCol,  
  332.             int endCol) {  
  333.         // 加载下拉列表内容  
  334.         DVConstraint constraint = DVConstraint  
  335.                 .createExplicitListConstraint(textlist);  
  336.         // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列  
  337.         CellRangeAddressList regions = new CellRangeAddressList(firstRow,  
  338.                 endRow, firstCol, endCol);  
  339.         // 数据有效性对象  
  340.         HSSFDataValidation data_validation_list = new HSSFDataValidation(  
  341.                 regions, constraint);  
  342.         sheet.addValidationData(data_validation_list);  
  343.         return sheet;  
  344.     }  
  345.   
  346.     /** 
  347.      * 得到实体类所有通过注解映射了数据表的字段 
  348.      *  
  349.      * @param map 
  350.      * @return 
  351.      */  
  352.     private List<Field> getMappedFiled(Class clazz, List<Field> fields) {  
  353.         if (fields == null) {  
  354.             fields = new ArrayList<Field>();  
  355.         }  
  356.   
  357.         Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段  
  358.         // 得到所有field并存放到一个list中.  
  359.         for (Field field : allFields) {  
  360.             if (field.isAnnotationPresent(ExcelVOAttribute.class)) {  
  361.                 fields.add(field);  
  362.             }  
  363.         }  
  364.         if (clazz.getSuperclass() != null  
  365.                 && !clazz.getSuperclass().equals(Object.class)) {  
  366.             getMappedFiled(clazz.getSuperclass(), fields);  
  367.         }  
  368.   
  369.         return fields;  
  370.     }  
  371. }  





您是否有这样的需求呢:
1.实体类中存放的值是一个编码,而导出的文件中需要把编码转成有意义的文字.例如:实体类中性别用0,1表示,而希望导出的excel文件中是"男","女".
2.想对导入的内容加一些逻辑,例如:判断某些值不能为空.或判断年龄不能小于0且不能大于100.

这篇文章写的有点长了,上述需求实现请看下篇文章:http://blog.csdn.net/lk_blog/article/details/8007837

 

实现一个配置简单功能强大的excel工具类搞定excel导入导出
http://blog.csdn.net/lk_blog/article/details/8007777
http://blog.csdn.net/lk_blog/article/details/8007837

 

 代码下载: http://download.csdn.net/detail/lk_blog/4588280

猜你喜欢

转载自blog.csdn.net/qq_36871364/article/details/76649044
今日推荐