java中excel导入导出工具类

Posted newandhui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中excel导入导出工具类相关的知识,希望对你有一定的参考价值。

1.导入工具

  1 package com.linrain.jcs.test;
  2 
  3 
  4 import jxl.Cell;
  5 import jxl.Sheet;
  6 import jxl.Workbook;
  7 import jxl.write.Label;
  8 import jxl.write.WritableSheet;
  9 
 10 import java.io.InputStream;
 11 import java.lang.reflect.Field;
 12 import java.text.SimpleDateFormat;
 13 import java.util.*;
 14 
 15 
 16 /**
 17  * @Description: 导入excel工具类
 18  * @CreateDate: 2019/1/24/0024$ 19:39$
 19  * @Version: 1.0
 20  */
 21 public class ImportExcelUtil {
 22 
 23 
 24     /**
 25      * @param in           :承载着Excel的输入流
 26      * @param :要导入的工作表序号
 27      * @param entityClass  :List中对象的类型(Excel中的每一行都要转化为该类型的对象)
 28      * @param fieldMap     :Excel中的中文列头和类的英文属性的对应关系Map
 29      * @param uniqueFields :指定业务主键组合(即复合主键),这些列的组合不能重复
 30      * @return :List
 31      * @throws ExcelException
 32      * @MethodName : excelToList
 33      * @Description : 将Excel转化为List
 34      */
 35     public static <T> List<T> excelToList(InputStream in, String sheetName, Class<T> entityClass,
 36                                           LinkedHashMap<String, String> fieldMap, String[] uniqueFields) throws ExcelException {
 37 
 38         //定义要返回的list
 39         List<T> resultList = new ArrayList<T>();
 40 
 41         try {
 42 
 43             //根据Excel数据源创建WorkBook
 44             Workbook wb = Workbook.getWorkbook(in);
 45             //获取工作表
 46             Sheet sheet = wb.getSheet(sheetName);
 47 
 48             //获取工作表的有效行数
 49             int realRows = 0;
 50             for (int i = 0; i < sheet.getRows(); i++) {
 51 
 52                 int nullCols = 0;
 53                 for (int j = 0; j < sheet.getColumns(); j++) {
 54                     Cell currentCell = sheet.getCell(j, i);
 55                     if (currentCell == null || "".equals(currentCell.getContents().toString())) {
 56                         nullCols++;
 57                     }
 58                 }
 59 
 60                 if (nullCols == sheet.getColumns()) {
 61                     break;
 62                 } else {
 63                     realRows++;
 64                 }
 65             }
 66 
 67 
 68             //如果Excel中没有数据则提示错误
 69             if (realRows <= 1) {
 70                 throw new ExcelException("Excel文件中没有任何数据");
 71             }
 72 
 73 
 74             Cell[] firstRow = sheet.getRow(0);
 75 
 76             String[] excelFieldNames = new String[firstRow.length];
 77 
 78             //获取Excel中的列名
 79             for (int i = 0; i < firstRow.length; i++) {
 80                 excelFieldNames[i] = firstRow[i].getContents().toString().trim();
 81             }
 82 
 83             //判断需要的字段在Excel中是否都存在
 84             boolean isExist = true;
 85             List<String> excelFieldList = Arrays.asList(excelFieldNames);
 86             for (String cnName : fieldMap.keySet()) {
 87                 if (!excelFieldList.contains(cnName)) {
 88                     isExist = false;
 89                     break;
 90                 }
 91             }
 92 
 93             //如果有列名不存在,则抛出异常,提示错误
 94             if (!isExist) {
 95                 throw new ExcelException("Excel中缺少必要的字段,或字段名称有误");
 96             }
 97 
 98 
 99             //将列名和列号放入Map中,这样通过列名就可以拿到列号
100             LinkedHashMap<String, Integer> colMap = new LinkedHashMap<String, Integer>();
101             for (int i = 0; i < excelFieldNames.length; i++) {
102                 colMap.put(excelFieldNames[i], firstRow[i].getColumn());
103             }
104 
105 
106             //判断是否有重复行
107             //1.获取uniqueFields指定的列
108             Cell[][] uniqueCells = new Cell[uniqueFields.length][];
109             for (int i = 0; i < uniqueFields.length; i++) {
110                 int col = colMap.get(uniqueFields[i]);
111                 uniqueCells[i] = sheet.getColumn(col);
112             }
113 
114             //2.从指定列中寻找重复行
115             for (int i = 1; i < realRows; i++) {
116                 int nullCols = 0;
117                 for (int j = 0; j < uniqueFields.length; j++) {
118                     String currentContent = uniqueCells[j][i].getContents();
119                     Cell sameCell = sheet.findCell(currentContent,
120                             uniqueCells[j][i].getColumn(),
121                             uniqueCells[j][i].getRow() + 1,
122                             uniqueCells[j][i].getColumn(),
123                             uniqueCells[j][realRows - 1].getRow(),
124                             true);
125                     if (sameCell != null) {
126                         nullCols++;
127                     }
128                 }
129 
130                 if (nullCols == uniqueFields.length) {
131                     throw new ExcelException("Excel中有重复行,请检查");
132                 }
133             }
134 
135             //将sheet转换为list
136             for (int i = 1; i < realRows; i++) {
137                 //新建要转换的对象
138                 T entity = entityClass.newInstance();
139 
140                 //给对象中的字段赋值
141                 for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
142                     //获取中文字段名
143                     String cnNormalName = entry.getKey();
144                     //获取英文字段名
145                     String enNormalName = entry.getValue();
146                     //根据中文字段名获取列号
147                     int col = colMap.get(cnNormalName);
148 
149                     //获取当前单元格中的内容
150                     String content = sheet.getCell(col, i).getContents().toString().trim();
151 
152                     //给对象赋值
153                     setFieldValueByName(enNormalName, content, entity);
154                 }
155 
156                 resultList.add(entity);
157             }
158         } catch (Exception e) {
159             e.printStackTrace();
160             //如果是ExcelException,则直接抛出
161             if (e instanceof ExcelException) {
162                 throw (ExcelException) e;
163 
164                 //否则将其它异常包装成ExcelException再抛出
165             } else {
166                 e.printStackTrace();
167                 throw new ExcelException("导入Excel失败");
168             }
169         }
170         return resultList;
171     }
172 
173     /**
174      * 根据字段名给对象的字段赋值
175      *
176      * @param fieldName  字段名
177      * @param fieldValue 字段值
178      * @param o          对象
179      * @throws Exception 异常
180      */
181     public static void setFieldValueByName(String fieldName, Object fieldValue, Object o) throws Exception {
182 
183         Field field = getFieldByName(fieldName, o.getClass());
184         if (field != null) {
185             field.setAccessible(true);
186             // 获取字段类型
187             Class<?> fieldType = field.getType();
188 
189             // 根据字段类型给字段赋值
190             if (String.class == fieldType) {
191                 field.set(o, String.valueOf(fieldValue));
192             } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
193                 field.set(o, Integer.parseInt(fieldValue.toString()));
194             } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
195                 field.set(o, Long.valueOf(fieldValue.toString()));
196             } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
197                 field.set(o, Float.valueOf(fieldValue.toString()));
198             } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
199                 field.set(o, Short.valueOf(fieldValue.toString()));
200             } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
201                 field.set(o, Double.valueOf(fieldValue.toString()));
202             } else if (Character.TYPE == fieldType) {
203                 if ((fieldValue != null) && (fieldValue.toString().length() > 0)) {
204                     field.set(o, Character.valueOf(fieldValue.toString().charAt(0)));
205                 }
206             } else if (Date.class == fieldType) {
207                 if (!fieldValue.toString().isEmpty()) {
208                     if (fieldValue.toString().length() > 10) {
209 
210                         field.set(o, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(fieldValue.toString()));
211                     } else {
212                         field.set(o, new SimpleDateFormat("yyyy-MM-dd").parse(fieldValue.toString()));
213                     }
214                 }
215             } else {
216                 field.set(o, fieldValue);
217             }
218         } else {
219             throw new ExcelException(o.getClass().getSimpleName() + "类不存在字段名 " + fieldName);
220         }
221     }
222 
223     /**
224      * @param sourceSheet
225      * @param eSheet      错误列表
226      * @param errorMap    错误原因
227      * @throws Exception
228      * @MethodName : addErrorRow
229      * @Description : 添加一行错误列表
230      */
231     private void addErrorRow(Sheet sourceSheet, WritableSheet eSheet, LinkedHashMap<Integer, String> errorMap) throws Exception {
232 
233         // 复制错误的数据到错误列表
234         for (Map.Entry<Integer, String> entry : errorMap.entrySet()) {
235             int errorNo = entry.getKey();
236             String reason = entry.getValue();
237             int rows = eSheet.getRows();
238             for (int i = 0; i < sourceSheet.getColumns(); i++) {
239                 System.out.println("错误列表当前列号" + i);
240                 eSheet.addCell(new Label(i, rows, sourceSheet.getCell(i, errorNo).getContents()));
241             }
242 
243             // 添加错误原因和所在行号
244             eSheet.addCell(new Label(sourceSheet.getColumns(), rows, reason));
245             eSheet.addCell(new Label(sourceSheet.getColumns() + 1, rows, String.valueOf(errorNo + 1)));
246 
247         }
248 
249     }
250 
251     /**
252      * 设置工作表自动列宽和首行加粗
253      *
254      * @param ws        要设置格式的工作表
255      * @param extraWith 额外的宽度
256      */
257     public static void setColumnAutoSize(WritableSheet ws, int extraWith) {
258         // 获取本列的最宽单元格的宽度
259         for (int i = 0; i < ws.getColumns(); i++) {
260             int colWith = 0;
261             for (int j = 0; j < ws.getRows(); j++) {
262                 String content = ws.getCell(i, j).getContents().toString();
263                 int cellWith = content.length();
264                 if (colWith < cellWith) {
265                     colWith = cellWith;
266                 }
267             }
268             // 设置单元格的宽度为最宽宽度+额外宽度
269             ws.setColumnView(i, colWith + extraWith);
270         }
271 
272     }
273 
274     /**
275      * 根据字段名获取字段
276      *
277      * @param fieldName 字段名
278      * @param clazz     包含该字段的类
279      * @return 字段
280      */
281     public static Field getFieldByName(String fieldName, Class<?> clazz) {
282         // 拿到本类的所有字段
283         Field[] selfFields = clazz.getDeclaredFields();
284 
285         // 如果本类中存在该字段,则返回
286         for (Field field : selfFields) {
287             if (field.getName().equals(fieldName)) {
288                 return field;
289             }
290         }
291 
292         // 否则,查看父类中是否存在此字段,如果有则返回
293         Class<?> superClazz = clazz.getSuperclass();
294         if (superClazz != null && superClazz != Object.class) {
295             return getFieldByName(fieldName, superClazz);
296         }
297 
298         // 如果本类和父类都没有,则返回空
299         return null;
300     }
301 
302     /**
303      * 根据实体拿到该实体的所有属性
304      *
305      * @param clazz 实体
306      * @return 返回属性的list集合
307      */
308     public static List<String> getSuperClassFieldByClass(Class<?> clazz) {
309 
310         List<String> list = new ArrayList<String>();
311 
312         // 否则,查看父类中是否存在此字段,如果有则返回
313         Class<?> superClazz = clazz.getSuperclass();
314 
315         Field[] superFields = superClazz.getDeclaredFields();
316         for (Field field : superFields) {
317             list.add(field.getName());
318         }
319 
320         // 如果父类没有,则返回空
321         return list;
322     }
323 
324 
325     /**
326      * @param clazz       :对象对应的类
327      * @param equalFields :复合业务主键对应的map
328      * @return 查询到的对象
329      * @MethodName : getObjByFields
330      * @Description :根据复合业务主键查询对象
331      */
332     private <T> T getObjByFields(Class<T> clazz, LinkedHashMap<Object, Object> equalFields) {
333 
334         List<T> list = null;
335         if (equalFields.size() != 0) {
336             // list=commonBean.findResultListByEqual(clazz, equalFields);
337         }
338 
339         return list == null || list.size() == 0 ? null : list.get(0);
340     }
341 
342     /**
343      * @param normalFieldMap 普通字段Map
344      * @param referFieldMap  引用字段Map
345      * @return 组合后的Map
346      * @MethodName : combineFields
347      * @Description : 组合普通和引用中英文字段Map
348      */
349     private LinkedHashMap<String, String> combineFields(LinkedHashMap<String, String> normalFieldMap, LinkedHashMap<LinkedHashMap<String, Class<?>>, LinkedHashMap<String, String>> referFieldMap) {
350 
351         LinkedHashMap<String, String> combineMap = new LinkedHashMap<String, String>();
352 
353         // 如果存在普通字段,则添加之
354         if (normalFieldMap != null && normalFieldMap.size() != 0) {
355             combineMap.putAll(normalFieldMap);
356         }
357 
358         // 如果存在引用字段,则添加之
359         if (referFieldMap != null && referFieldMap.size() != 0) {
360 
361             // 组建引用中英文字段Map
362             LinkedHashMap<String, String> simpleReferFieldMap = new LinkedHashMap<String, String>();
363             for (Map.Entry<LinkedHashMap<String, Class<?>>, LinkedHashMap<String, String>> entry : referFieldMap.entrySet()) {
364                 LinkedHashMap<String, Class<?>> keyMap = entry.getKey();
365                 LinkedHashMap<String, String> valueMap = entry.getValue();
366 
367                 // 获取引用中文字段名
368                 String referField = "";
369                 for (Map.Entry<String, Class<?>> keyEntry : keyMap.entrySet()) {
370                     referField = keyEntry.getKey();
371                     break;
372                 }
373 
374                 for (Map.Entry<String, String> valueEntry : valueMap.entrySet()) {
375                     String enField = valueEntry.getValue();
376                     String cnField = valueEntry.getKey();
377                     // 拼接英文引用字段
378                     String fullEnField = referField + "." + enField;
379 
380                     // 放入simpleReferFieldMap
381                     simpleReferFieldMap.put(cnField, fullEnField);
382                 }
383 
384             }
385 
386             // 放入combineMap
387             combineMap.putAll(simpleReferFieldMap);
388         }
389 
390         return combineMap;
391 
392     }
393 
394 
395 }

 

2.导出工具

 1 package com.linrain.jcs.test;
 2 
 3 import org.apache.commons.lang.StringUtils;
 4 import org.apache.poi.hssf.usermodel.HSSFCell;
 5 import org.apache.poi.hssf.usermodel.HSSFRow;
 6 import org.apache.poi.hssf.usermodel.HSSFSheet;
 7 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 8 
 9 import javax.servlet.http.HttpServletResponse;
10 import java.io.*;
11 import java.util.List;
12 import java.util.Map;
13 
14 /**
15  * @Description: 导出excel工具类
16  * @CreateDate: 2019/1/24/ 17:18$
17  * @Version: 1.0
18  */
19 public class ExportExcelUtil {
20     /**
21      * 常用普通文件下载
22      * @param response
23      * @param fileName
24      * @param sheetName
25      * @param data
26      */
27     public static void down(HttpServletResponse response, String fileName, String sheetName, List<Map<String, Object>> data) {
28         // 生成提示信息,
29         response.setContentType("application/vnd.ms-excel");
30         if (StringUtils.isBlank(fileName)) {
31             fileName = Long.toString(System.currentTimeMillis());
32         }
33         OutputStream fOut = null;
34         try {
35             // 进行转码,使其支持中文文件名
36             fOut = response.getOutputStream();
37             String codedFileName = new String(fileName.getBytes("gbk"), "iso-8859-1");
38             response.setHeader("content-disposition", "attachment;filename=" + codedFileName + ".xls");
39             HSSFWorkbook workbook = new HSSFWorkbook();
40             // 产生工作表对象
41             HSSFSheet sheet = workbook.createSheet(sheetName);
42 
43             for (int i = 0; i < data.size(); i++) {
44                 HSSFRow row = sheet.createRow((int) i);
45                 Map<String, Object> map = data.get(i);
46 
47                 //遍历map中的值
48                 int j = 0;
49                 for (Object value : map.values()) {
50                     HSSFCell cell = row.createCell((int) j);
51                     cell.setCellType(HSSFCell.CELL_TYPE_STRING);
52                     if (value == null) {
53                         value = "";
54                     }
55                     cell.setCellValue(value.toString());
56                     j++;
57                 }
58             }
59             workbook.write(fOut);
60         } catch (Exception e) {
61             e.printStackTrace();
62         } finally {
63             try {
64                 fOut.flush();
65                 fOut.close();
66             } catch (IOException e) {
67             }
68         }
69     }
70 }

 

以上是关于java中excel导入导出工具类的主要内容,如果未能解决你的问题,请参考以下文章

导入导出Excel的Java工具类ExcelUtil

java里将从excel读到的数据用csv导出,代码怎么写

Java后端实现Excel导入导出功能

C#导入导出数据到Excel的通用类代码

配置简单功能强大的excel工具类搞定excel导入导出工具类

【springboot+easypoi】一行代码搞定excel导入导出