一个基于POI的通用excel导入导出工具类的简单实现及使用方法

Posted BLUENESSG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个基于POI的通用excel导入导出工具类的简单实现及使用方法相关的知识,希望对你有一定的参考价值。

前言:

最近PM来了一个需求,简单来说就是在录入数据时一条一条插入到系统显得非常麻烦,让我实现一个直接通过excel导入的方法一次性录入所有数据。网上关于excel导入导出的例子很多,但大多相互借鉴。经过思考,认为一百个客户在录入excel的时候,就会有一百个格式版本,所以在实现这个功能之前,所以要统一excel的格式。于是提供了一个通用excel模版的下载功能。当所有客户用模版录入好数据再上传到系统,后端对excel进行解析,然后再持久化到数据库。

概述:

   此工具类的几大特点

   1、基本导入导出

   2、提供excel模版自动生成及下载功能

   3、创建模版过程简单通用,只需要在实体类上进行注解

   4、springMVC框架

   5、模版可以生成下拉框选择列

废话不多说,上代码......

一、引入poi相关依赖(及spring上传文件相关配置,不再解释)

 1 <!-- apache poi start -->
 2         <poi.version>3.14</poi.version>
 3         <dependency>
 4             <groupId>org.apache.poi</groupId>
 5             <artifactId>poi</artifactId>
 6             <version>${poi.version}</version>
 7         </dependency>
 8 
 9         <dependency>
10             <groupId>org.apache.poi</groupId>
11             <artifactId>poi-scratchpad</artifactId>
12             <version>${poi.version}</version>
13         </dependency>
14 
15         <dependency>
16             <groupId>org.apache.poi</groupId>
17             <artifactId>poi-ooxml</artifactId>
18             <version>${poi.version}</version>
19         </dependency>
20 <!-- apache poi end -->

二、excel导入导出工具类的实现

  1 /**
  2  * @Description
  3  * @author zhaomin E-mail:min.zhao@mljr.com
  4  * @date 创建时间:2017年2月14日 下午2:13:30
  5  * @version 1.0
  6  */
  7 public class ImportExcelUtil {
  8     final static String notnullerror = "请填入第{0}行的{1},{2}不能为空";
  9     final static String errormsg = "第{0}行的{1}数据导入错误";
 10 
 11     /**
 12      * 导入Excel
 13      * 
 14      * @param clazz
 15      * @param xls
 16      * @return
 17      * @throws Exception
 18      */
 19     @SuppressWarnings("rawtypes")
 20     public static List importExcel(Class<?> clazz, InputStream xls) throws Exception {
 21         try {
 22             // 取得Excel
 23             HSSFWorkbook wb = new HSSFWorkbook(xls);
 24             HSSFSheet sheet = wb.getSheetAt(0);
 25             Field[] fields = clazz.getDeclaredFields();
 26             List<Field> fieldList = new ArrayList<Field>(fields.length);
 27             for (Field field : fields) {
 28                 if (field.isAnnotationPresent(ModelProp.class)) {
 29                     ModelProp modelProp = field.getAnnotation(ModelProp.class);
 30                     if (modelProp.colIndex() != -1) {
 31                         fieldList.add(field);
 32                     }
 33                 }
 34             }
 35             EmployeeDTO employee = new EmployeeDTO();
 36             // 行循环
 37             List<ImportModel> modelList = new ArrayList<ImportModel>(sheet.getPhysicalNumberOfRows() * 2);
 38             for (int i = 2; i < sheet.getPhysicalNumberOfRows(); i++) {
 39                 // 数据模型
 40                 ImportModel model = (ImportModel) clazz.newInstance();
 41                 int nullCount = 0;
 42                 Exception nullError = null;
 43                 for (Field field : fieldList) {
 44                     ModelProp modelProp = field.getAnnotation(ModelProp.class);
 45                     HSSFCell cell = sheet.getRow(i).getCell(modelProp.colIndex());
 46                     try {
 47                         if (cell == null || cell.toString().length() == 0) {
 48                             nullCount++;
 49                             if (!modelProp.nullable()) {
 50                                 nullError = new Exception(StringUtil.format(notnullerror,
 51                                         new String[] { "" + (1 + i), modelProp.name(), modelProp.name() }));
 52 
 53                             }
 54                         } else if (field.getType().equals(Date.class)) {
 55                             if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
 56                                 BeanUtils.setProperty(model, field.getName(), new Date(parseDate(parseString(cell))));
 57                             } else {
 58                                 BeanUtils.setProperty(model, field.getName(),
 59                                         new Date(cell.getDateCellValue().getTime()));
 60 
 61                             }
 62                         } else if (field.getType().equals(Timestamp.class)) {
 63                             if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
 64                                 BeanUtils.setProperty(model, field.getName(),
 65                                         new Timestamp(parseDate(parseString(cell))));
 66                             } else {
 67                                 BeanUtils.setProperty(model, field.getName(),
 68                                         new Timestamp(cell.getDateCellValue().getTime()));
 69                             }
 70 
 71                         } else if (field.getType().equals(java.sql.Date.class)) {
 72                             if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
 73                                 BeanUtils.setProperty(model, field.getName(),
 74                                         new java.sql.Date(parseDate(parseString(cell))));
 75                             } else {
 76                                 BeanUtils.setProperty(model, field.getName(),
 77                                         new java.sql.Date(cell.getDateCellValue().getTime()));
 78                             }
 79                         } else if (field.getType().equals(java.lang.Integer.class)) {
 80                             if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) {
 81                                 BeanUtils.setProperty(model, field.getName(), (int) cell.getNumericCellValue());
 82                             } else if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
 83                                 BeanUtils.setProperty(model, field.getName(), Integer.parseInt(parseString(cell)));
 84                             }
 85                         } else if (field.getType().equals(java.math.BigDecimal.class)) {
 86                             if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) {
 87                                 BeanUtils.setProperty(model, field.getName(),
 88                                         new BigDecimal(cell.getNumericCellValue()));
 89                             } else if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
 90                                 BeanUtils.setProperty(model, field.getName(), new BigDecimal(parseString(cell)));
 91                             }
 92                         } else {
 93                             if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) {
 94                                 BeanUtils.setProperty(model, field.getName(),
 95                                         new BigDecimal(cell.getNumericCellValue()));
 96                             } else if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
 97                                 BeanUtils.setProperty(model, field.getName(), parseString(cell));
 98                             }
 99                         }
100                     } catch (Exception e) {
101                         e.printStackTrace();
102                         throw new Exception(StringUtil.format(errormsg, new String[] { "" + (1 + i), modelProp.name() })
103                                 + "," + e.getMessage());
104                     }
105                 }
106                 if (nullCount == fieldList.size()) {
107                     break;
108                 }
109                 if (nullError != null) {
110                     throw nullError;
111                 }
112                 modelList.add(model);
113             }
114             return modelList;
115 
116         } finally {
117             xls.close();
118         }
119     }
120 
121     private final static int colsizeN = 630;
122     private final static int colsizeM = 1000;
123 
124     /**
125      * 下载Excel模版
126      * 
127      * @param clazz
128      * @param map
129      * @param rowSize
130      * @return
131      */
132     public static InputStream excelModelbyClass(Class<?> clazz, Map<Integer, String[]> map, Integer rowSize) {
133         try {
134             if (!clazz.isAnnotationPresent(ModelTitle.class)) {
135                 throw new Exception("请在此类型中加上ModelTitle注解");
136             }
137             if (rowSize == null) {
138                 rowSize = 1000;
139             }
140             HSSFWorkbook wb = new HSSFWorkbook();
141             HSSFSheet sheet = wb.createSheet();
142             /**
143              * 设置标题样式
144              */
145             HSSFCellStyle titleStyle = wb.createCellStyle();
146             titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
147             HSSFFont font = wb.createFont();
148             font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
149             font.setFontHeight((short) 400);
150             titleStyle.setFont(font);
151             HSSFCell titleCell = sheet.createRow(0).createCell(0); // 创建第一行,并在该行创建单元格,设置内容,做为标题行
152             /**
153              * 获取标题
154              */
155             ModelTitle modelTitle = clazz.getAnnotation(ModelTitle.class);
156             titleCell.setCellValue(new HSSFRichTextString(modelTitle.name()));
157             titleCell.setCellStyle(titleStyle);
158 
159             Field[] fields = clazz.getDeclaredFields();
160             HSSFRow headRow = sheet.createRow(1);
161             int colSzie = 0;
162             /**
163              * 设置表头样式
164              */
165             HSSFCellStyle headStyle = wb.createCellStyle();
166             headStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
167             HSSFFont headFont = wb.createFont();
168             headFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
169             headFont.setFontHeight((short) 240);
170             headStyle.setFont(headFont);
171             List<Integer> cells = new ArrayList<Integer>();
172 
173             for (Field field : fields) {
174                 if (field.isAnnotationPresent(ModelProp.class)) {
175                     ModelProp modelProp = field.getAnnotation(ModelProp.class);
176                     if (modelProp.colIndex() == -1)
177                         continue;
178                     cells.add(modelProp.colIndex());
179                     HSSFCell cell = headRow.createCell(modelProp.colIndex());
180                     cell.setCellValue(new HSSFRichTextString(modelProp.name()));
181                     cell.setCellStyle(headStyle);
182                     colSzie++;
183                     sheet.autoSizeColumn((short) modelProp.colIndex());
184                     sheet.setColumnWidth(modelProp.colIndex(), modelProp.name().length() * colsizeN + colsizeM);
185 
186                     // 设置列为下拉框格式
187                     if (map != null && map.get(new Integer(modelProp.colIndex())) != null) {
188                         DVConstraint constraint = DVConstraint
189                                 .createExplicitListConstraint(map.get(modelProp.colIndex()));
190                         CellRangeAddressList regions = new CellRangeAddressList(2, rowSize, modelProp.colIndex(),
191                                 modelProp.colIndex());
192                         HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
193                         sheet.addValidationData(dataValidation);
194                     }
195                 }
196             }
197             HSSFCellStyle cellStyle = wb.createCellStyle();
198             HSSFDataFormat format = wb.createDataFormat();
199             cellStyle.setDataFormat(format.getFormat("@"));
200             for (int i = 2; i < rowSize; i++) {
201                 HSSFRow row = sheet.createRow(i);
202                 for (Integer integer : cells) {
203                     HSSFCell cell = row.createCell(integer);
204                     cell.setCellStyle(cellStyle);
205                 }
206             }
207             sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, colSzie - 1));
208             if (map != null) {
209                 for (Integer colIndex : map.keySet()) {
210                     DVConstraint constraint = DVConstraint.createExplicitListConstraint(map.get(colIndex));
211                     CellRangeAddressList regions = new CellRangeAddressList(2, 1000, colIndex, colIndex);
212                     HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
213                     sheet.addValidationData(dataValidation);
214                 }
215             }
216 
217             ByteArrayOutputStream os = new ByteArrayOutputStream();
218             try {
219                 wb.write(os);
220             } catch (IOException e) {
221                 e.printStackTrace();
222             }
223 
224             byte[] b = os.toByteArray();
225 
226             ByteArrayInputStream in = new ByteArrayInputStream(b);
227             return in;
228         } catch (Exception e) {
229             e.printStackTrace();
230             return null;
231         }
232     }
233 
234     private static String parseString(HSSFCell cell) {
235         return String.valueOf(cell).trim();
236     }
237 
238     private static long parseDate(String dateString) throws ParseException {
239         if (dateString.indexOf("/") == 4) {
240             return new SimpleDateFormat("yyyy/MM/dd").parse(dateString).getTime();
241         } else if (dateString.indexOf("-") == 4) {
242             return new SimpleDateFormat("yyyy-MM-dd").parse(dateString).getTime();
243         } else if (dateString.indexOf("年") == 4) {
244             return new SimpleDateFormat("yyyy年MM月dd").parse(dateString).getTime();
245         } else if (dateString.length() == 8) {
246             return new SimpleDateFormat("yyyyMMdd").parse(dateString).getTime();
247         } else {
248             return new Date().getTime();
249         }
250     }
251 
252 }

 三、自定义spring注解

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.FIELD)
3 public @interface ModelProp{
4     public String name();
5     public int colIndex() default -1;
6     public boolean nullable() default true;
7     public String interfaceXmlName() default "";
8 }
1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.TYPE)
3 public @interface ModelTitle{
4     public String name();
5 }

四、定义实体类父类

1 public class ImportModel {
2 
3 }

五、定义实体类

 1 @ModelTitle(name="人员列表")
 2 public class EmployeeDTO extends ImportModel implements Serializable {
 3 
 4     private static final long serialVersionUID = -3434719712955859295L;
 5 
 6     private Long id;
 7     @ModelProp(name = "电话", colIndex = 1, nullable = false)
 8     private String telephone;
 9 
10     @ModelProp(name = "名称", colIndex = 0, nullable = false)
11     private String name;
12 
13     @ModelProp(name = "性别", colIndex = 2, nullable = false)
14     private Integer sex;
15 }

六、定义controller

 1 @RestController
 2 @RequestMapping("/api/excelOpera")
 3 public class ImportEmployeeController extends BaseController {
 4     
 5     private static Logger logger = LoggerFactory.getLogger(ImportEmployeeController.class);
 6     /**
 7      * 导入excel表
 8      * @version 1.0
 9      * @since 1.0
10      */
11     @RequestMapping(path = "/importEmployee", method = RequestMethod.POST)
12     public RespMsg uploadExcel(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
13         try{
14            
15             List<EmployeeDTO> employeeDTOList  = ImportExcelUtil.importExcel(EmployeeDTO.class, file.getInputStream());
16             //可做持久化操作,现只打印观察
17             for(EmployeeDTO employeeDTO : employeeDTOList){
18                 logger.info("name=" + employeeDTO.getName() + ",telephone=" + employeeDTO.getTelephone()+",sex=" + employeeDTO.getSex());
19             }
20         }catch(Exception e){
21             logger.error(e.getMessage());
22         }
23         return null;
24     }
25     /**
26      * 导出excel模版
27      * @version 1.0
28      * @since 1.0
29      */
30     @RequestMapping(path = "/downloadEmployeeModel", method = RequestMethod.GET)
31     public RespMsg downloadEmployeeModel(HttpServletResponse response) {
32         try{
33             response.setContentType("application/xls");
34             response.addHeader("Content-Disposition", "attachment;filename="+new String(("eeelist").getBytes("UTF-8"),"iso-8859-1")+".xls");
35             Map<Integer,String[]> paramMap = new HashMap<Integer,String[]>();
36             //excel第三行为下拉选择框
37             paramMap.put(2, new String[]{"man","women"});
38             BufferedInputStream input = new BufferedInputStream(ImportExcelUtil.excelModelbyClass(EmployeeDTO.class, paramMap, null));
39             byte buffBytes[] = new byte[1024];
40             OutputStream os = response.getOutputStream();
41             int read = 0;
42             while ((read = input.read(buffBytes)) != -1) {
43                 os.write(buffBytes, 0, read);
44             }
45             os.flush();
46             os.close();
47             input.close();
<

以上是关于一个基于POI的通用excel导入导出工具类的简单实现及使用方法的主要内容,如果未能解决你的问题,请参考以下文章

EXCEL终极总结分享基于NPOI扩展封装的简易操作工具类库(简单灵活易用,支持导出导入上传等常见操作)

poi和easyExcel基于Java操作Excel学习笔记

基于SSM的POI导入导出Excel实战第二篇-导入EXCEL

导入导出Excel的Java工具类ExcelUtil

POI导出excel

SpringBoot加Poi仿照EasyPoi实现Excel导出