博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于SSM框架的Excel工具类
阅读量:7101 次
发布时间:2019-06-28

本文共 18974 字,大约阅读时间需要 63 分钟。

hot3.png

前言

  • 本次提供Excel工具类导入和导出的功能,是本人在借鉴网上的部分代码的基础上搭出一个公用化的工具。如有不妥之处,麻烦指明,本人不胜感激。

Excel导出

实现思路

  • 通过Apache提供POI包读取Excel信息,首先读取指定字段名表头,其次从指定行数开始读取数据,然和对应的字段名映射到Map,最后返回一个List<Map>。在获取读取结果后通过调用Map映射到实体类工具,将Map中对应的值映射到实体中。这样子,只要规定好Excel模板和指定好表头读取行数和数据读取开始索引,就可以达到一个公用化的目的了。

实现步骤

  • 导入Maven依赖
org.apache.poi
poi
3.17
org.apache.poi
poi-ooxml
3.17
org.apache.poi
poi-ooxml-schemas
3.17
org.apache.poi
poi-excelant
3.17
org.apache.poi
poi-examples
3.17
  • 定义上传Excel格式 这里写图片描述
  • 接收MultiPartFile类型的数据
  • 调用ExcelUtil 工具
ExcelUtils utils = new ExcelUtils();//字段名读取开始索引utils.setFieldReadIndex(4);//数据读取开始索引utils.setDataReadIndex(6);List maps = utils.getExcelInfo(file.getOriginalFilename(), file);
  • 接收到List<Map>结果在MapToBeanUtils中映射。
for(Map map :maps){    //这里Bean是要用来接收的自定义实体类    Bean obj = MapToBeanUtils.getModel(map,Bean.class);    //处理相关业务逻辑    }

Excel导出

实现思路

  • 借助自定义注解在导出实体类的字段标注该字段对应的表头名称,再通过ExcelUtils工具解析实体类数据和其字段注解来生成Excel。

实现步骤

  • 导入Maven依赖
org.apache.poi
poi
3.17
org.apache.poi
poi-ooxml
3.17
org.apache.poi
poi-ooxml-schemas
3.17
org.apache.poi
poi-excelant
3.17
org.apache.poi
poi-examples
3.17
  • 自定义注解
@Target(ElementType.FIELD)@Documented@Retention(RetentionPolicy.RUNTIME)public @interface ExcelColumn {    String title();}
  • 导出实体类引用注解形式
@ExcelColumn(title="uuid")    private String uuid;
  • 引用工具类
//这里Bean是要用来导出的自定义实体类ExcelUtils.export(Bean.class, list, DateUtil.format(new Date(),DateUtil.INT_STRING_FORMAT), response);

源码

ExcelUtils.java

package com.demo.util;import com.andacx.core.log.LogFactory;import com.andacx.tool.Asserts;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.hssf.util.HSSFColor;import org.apache.poi.ss.usermodel.*;import org.apache.poi.ss.util.CellUtil;import org.apache.poi.xssf.streaming.SXSSFSheet;import org.apache.poi.xssf.streaming.SXSSFWorkbook;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.slf4j.Logger;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.lang.reflect.Field;import java.util.*;/** * 

@description:【Excel写入和导出工具】

*

@author:【Boomer】

*

@date:【2018/1/11 11:18】

**/public class ExcelUtils { private static final Logger LOGGER = LogFactory.get(ExcelUtils.class); /*** 总行数 **/ private int totalRows = 0; /*** 总条数 **/ private int totalCells = 0; /*** 数据读取开始索引 **/ private int dataReadIndex = 3; /*** 字段名读取开始索引 **/ private int fieldReadIndex = 2; public ExcelUtils() { } public int getTotalRows() { return totalRows; } public int getTotalCells() { return totalCells; } public int getDataReadIndex() { return dataReadIndex; } public void setDataReadIndex(int dataReadIndex) { this.dataReadIndex = dataReadIndex; } public int getFieldReadIndex() { return fieldReadIndex; } public void setFieldReadIndex(int fieldReadIndex) { this.fieldReadIndex = fieldReadIndex; } /** *

Description:【验证EXCEL文件】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param filePath * @return **/ public boolean validateExcel(String filePath) { Asserts.notNull(filePath, "文件名不是excel格式"); Asserts.isTrue((isExcel2003(filePath) || isExcel2007(filePath)), "文件名不是excel格式"); return true; } /** *

Description:【是否是2003的excel,返回true是2003】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param filePath * @return **/ public static boolean isExcel2003(String filePath) { return filePath.matches("^.+.(xls)$"); } /** *

Description:【是否是2007的excel,返回true是2007】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param filePath * @return **/ public static boolean isExcel2007(String filePath) { return filePath.matches("^.+.(xlsx)$"); } /** *

Description:【读EXCEL文件,获取客户信息集合】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param fileName * @param Mfile * @return **/ public List getExcelInfo(String fileName, MultipartFile Mfile) { //把spring文件上传的MultipartFile转换成CommonsMultipartFile类型 CommonsMultipartFile cf = (CommonsMultipartFile) Mfile; //获取本地存储路径 File fileFolder = new File(Sysutils.getUploadFilePath()); if (!fileFolder.exists()) { fileFolder.mkdirs(); } //新建一个文件 File uploadFile = new File(Sysutils.getUploadFilePath() + System.currentTimeMillis() + ".xlsx"); //将上传的文件写入新建的文件中 try { cf.getFileItem().write(uploadFile); } catch (Exception e) { e.printStackTrace(); } //初始化信息的集合 List list = new ArrayList<>(); //初始化输入流 InputStream is = null; try { //验证文件名是否合格 if (!validateExcel(fileName)) { return null; } //根据新建的文件实例化输入流 is = new FileInputStream(uploadFile); //根据excel里面的内容读取客户信息 list = getExcelInfo(is, isExcel2003(fileName)); is.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return list; } /** *

Description:【根据excel里面的内容读取客户信息】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param is 输入流 * @param isExcel2003 excel是2003还是2007版本 * @return * @throws IOException **/ public List getExcelInfo(InputStream is, boolean isExcel2003) { List list; try { /** 根据版本选择创建Workbook的方式 */ Workbook wb; //当excel是2003时 if (isExcel2003) { wb = new HSSFWorkbook(is); } else {//当excel是2007时 wb = new XSSFWorkbook(is); } //读取Excel里面客户的信息 list = readExcelValue(wb); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } catch (NumberFormatException e) { throw new RuntimeException("读取错误,请确认Excel是否包含错误字符"); } return list; } /** *

Description:【读取Excel里面客户的信息】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param wb * @return **/ private List readExcelValue(Workbook wb) { //得到第一个shell Sheet sheet = wb.getSheetAt(0); //得到Excel的行数 this.totalRows = sheet.getPhysicalNumberOfRows(); //得到Excel的列数(前提是有行数) if (totalRows >= this.dataReadIndex && sheet.getRow(0) != null) { this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } List list = new ArrayList<>(); Map tempMap; //获取列数据对应的字段 Row title = sheet.getRow(this.fieldReadIndex); List
header = new ArrayList<>(); //循环Excel的列 for (int c = 0; c < this.totalCells; c++) { Cell cell = title.getCell(c); header.add(cell.getStringCellValue()); } //循环Excel行数,从第二行开始。标题不入库 for (int r = this.dataReadIndex; r < totalRows; r++) { Row row = sheet.getRow(r); if (row == null) { continue; } tempMap = new HashMap(this.totalCells); //循环Excel的列 for (int c = 0; c < this.totalCells; c++) { Cell cell = row.getCell(c); if (null != cell) { cell.setCellType(CellType.STRING); tempMap.put(header.get(c), cell.getStringCellValue()); } } //添加客户 list.add(tempMap); } return list; } /** *

Description:【导出到file】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param clz * @param data * @param filePath * @param
* @throws IOException **/ public static
void export(Class
clz, List
data, String filePath) throws IOException { FileOutputStream out = new FileOutputStream(filePath); getBook(clz, data).write(out); out.close(); } /** *

Description:【导出到httpServletResponse】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param clz * @param data * @param fileName * @param response * @param
**/ public static
void export(Class
clz, List
data, String fileName, HttpServletResponse response) { try { response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-disposition", "attachment;filename=\"" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xlsx" + "\""); getBook(clz, data).write(response.getOutputStream()); } catch (Exception e) { throw new RuntimeException("系统异常"); } finally { try { response.getOutputStream().close(); } catch (IOException e) { LOGGER.error("流关闭异常:" + e.getMessage()); } } } /** *

Description:【生成Excel】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param clz * @param data * @return **/ private static
SXSSFWorkbook getBook(Class
clz, List
data) { if (null == clz || null == data || data.size() <= 0) { throw new RuntimeException("参数异常"); } XSSFWorkbook workbook = new XSSFWorkbook(); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook, 100); //第一个工作本 SXSSFSheet sheet = sxssfWorkbook.createSheet(); sheet.trackAllColumnsForAutoSizing(); //表头 Row header = sheet.createRow(0); //读取类字段、注解信息 Field[] fields = clz.getDeclaredFields(); //写入表头 int invalidFieldNum = 0; for (Field field : fields) { ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class); if (excelColumn == null) { continue; } Cell headerCell = header.createCell(invalidFieldNum++); headerCell.setCellStyle(headerCellStyle(sxssfWorkbook)); headerCell.setCellValue(excelColumn.title()); } //写入数据 for (int i = 0; i < data.size(); i++) { //第0行为表头 Row row = sheet.createRow(i + 1); //循环读取字段 int cellIndex = 0; for (int j = 0; j < fields.length; j++) { Field field = fields[j]; field.setAccessible(true); Object cellValue; ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class); if (null == excelColumn) { continue; } Object o; try { o = field.get(data.get(i)); cellValue = o; } catch (Exception e) { throw new RuntimeException("系统异常"); } CellUtil.createCell(row, cellIndex++, String.valueOf(cellValue)); } } //自适应宽度 for (int i = 0; i < invalidFieldNum; i++) { sheet.autoSizeColumn(i); } return sxssfWorkbook; } /** *

Description:【设置Excel表头样式】

*

Author:【Boomer】

*

Date:【2018/1/11 14:07】

* @param wb * @return **/ public static CellStyle headerCellStyle(Workbook wb) { CellStyle style = wb.createCellStyle(); Font font = wb.createFont(); font.setFontName("宋体"); //设置字体大小 font.setFontHeightInPoints((short) 12); //加粗 font.setBold(true); // 设置背景色 style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.SKY_BLUE.getIndex()); style.setFillPattern(FillPatternType.SOLID_FOREGROUND); //让单元格居中 style.setAlignment(HorizontalAlignment.CENTER_SELECTION); // 左右居中 style.setAlignment(HorizontalAlignment.CENTER); // 上下居中 style.setVerticalAlignment(VerticalAlignment.CENTER); //设置自动换行 style.setWrapText(true); style.setFont(font); return style; }}

map转实体工具类

package com.andacx.lbs.util;import com.andacx.tool.StringUtil;import org.apache.commons.collections.MapUtils;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * Created by Boomer on 2017/5/19. * @author Boomer */public class MapToBeanUtils {    /**     * 获取类类型的所有Field包括父类中的Field     *     * @param clazz 类类型     * @return 返回类类型的所有Field包括父类中的Field     */    public static Field[] getAllFields(Class clazz) {        Map
map = new HashMap
(); for (Field field : clazz.getDeclaredFields()) { Class fieldType = field.getType(); String fieldName = field.getName(); if(isBaseType(fieldType)){ try { map.put(fieldName, field); } catch (Exception e) { e.printStackTrace(); } } } while (clazz.getSuperclass() != null) { clazz = clazz.getSuperclass(); if (clazz == Object.class) { break; } for (Field field : clazz.getDeclaredFields()) { if (!map.containsKey(field.getName())) { map.put(field.getName(), field); } } } return map.values().toArray(new Field[map.size()]); } /** *

Description:【判断是否是基本类型】

*

Author:【Boomer】

*

Date:【2018/1/8 16:13】

* @param fieldType * @return **/ public static Boolean isBaseType(Class fieldType){ if (fieldType == String.class) { return true; } else if (fieldType == double.class || fieldType == Double.class) { return true; } else if (fieldType == int.class || fieldType == Integer.class) { return true; } else if (fieldType == Boolean.class || fieldType == boolean.class) { return true; } else if (fieldType == Date.class) { return true; } return false; } /** *

Description:【将首字母转换为大写】

*

Author:【Boomer】

*

Date:【2018/1/5 15:54】

* * @param a * @return **/ public static String firstCharToUpper(String a) { return (new StringBuilder()).insert(0, a.substring(0, 1).toUpperCase()).append(a.substring(1)).toString(); } /** *

Description:【将map隐射到实体类】

*

Author:【Boomer】

*

Date:【2018/1/5 16:27】

* * @param map * @param model * @return **/ public static
T getModel(Map map, Class
model) { Field[] fields = getAllFields(model); String value; Method method; T obj; try { obj = model.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } for (Field field : fields) { int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) { continue; } //根据传入的获取str来判断用哪个字符串获取参数 value = MapUtils.getString(map, field.getName()); if (StringUtil.isEmpty(value)) { if (field.getType() == String.class) { try { method = model.getMethod("get" + firstCharToUpper(field.getName())); Object invokeValue = method.invoke(obj); if (invokeValue != null) { value = invokeValue.toString(); } } catch (Exception e) { if (field.getType() == Boolean.class || field.getType() == boolean.class) { try { String fieldName = field.getName(); method = model.getMethod("get" + firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName)); Object invokeValue = method.invoke(obj); if (invokeValue != null) { value = invokeValue.toString(); } } catch (Exception e1) { System.out.println(e1.getMessage()); } } else { System.out.println(e.getMessage()); } } } } if (StringUtil.isNotEmpty(value)) { invokeMethod(model, obj, value, field.getName(), field.getType()); } } return obj; } /** *

Description:【调用方法】

*

Author:【Boomer】

*

Date:【2018/1/5 16:26】

* * @param modelClass * @param object * @param value * @param fieldName * @param fieldType * @return **/ private static
void invokeMethod(Class
modelClass, T object, String value, String fieldName, Class fieldType) { Method method = null; try { method = modelClass.getMethod("set" + firstCharToUpper(fieldName), fieldType); } catch (NoSuchMethodException e) { if (fieldType == Boolean.class || fieldType == boolean.class) { try { method = modelClass.getMethod("set" + firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName), fieldType); } catch (NoSuchMethodException e1) { } } else { } } try { if (null != method) { if (fieldType == String.class) { method.invoke(object, value); } else if (fieldType == double.class || fieldType == Double.class) { try { method.invoke(object, Double.parseDouble(value)); } catch (NumberFormatException e) { e.printStackTrace(); } } else if (fieldType == int.class || fieldType == Integer.class) { try { method.invoke(object, Integer.parseInt(value)); } catch (NumberFormatException e) { e.printStackTrace(); } } else if (fieldType == Boolean.class || fieldType == boolean.class) { try { method.invoke(object, Boolean.parseBoolean(value)); } catch (Exception e) { e.printStackTrace(); } } else if (fieldType == Date.class) { try { SimpleDateFormat sdf = (value.length() == 10 ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); method.invoke(object, sdf.parse(value)); } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } }}
  • 20180122 这个工具也可以用以下方法实现
public static 
List
mapToBean(List
maps, Class
obj) throws IllegalAccessException, InstantiationException { List
list = new ArrayList<>(); for (Map
map : maps) { T module = obj.newInstance(); BeanWrapper wapper = new BeanWrapperImpl(module); for (Map.Entry entry : map.entrySet()) { if (wapper.isWritableProperty(entry.getKey().toString())) { wapper.setPropertyValue(entry.getKey().toString(), entry.getValue().toString()); } } list.add(module); } return list; }

后语

  • 源码中可能掺杂一些个人工具类源码,各位可自行更改,不影响功能实现。如果问题请留言。

转载于:https://my.oschina.net/u/3413394/blog/1606054

你可能感兴趣的文章
Rommel - C# 浅谈 接口(Interface)的作用
查看>>
Debian下Apache配置多域名访问
查看>>
关于git的个人开发终端命令行
查看>>
一位前辈写的HTML规范
查看>>
删除字符串第一个byte
查看>>
从字符集发展史看Unicode和UTF-8的区别
查看>>
随笔杂记
查看>>
第一章
查看>>
值对象和引用对象
查看>>
@GetMapping和@PostMapping 和@RequestMapping区别
查看>>
asp.net上传图片
查看>>
Python连接MySQL数据库—pymysql模块
查看>>
无法在要求对象展开的函数中使用 __try
查看>>
《Spring实战》系列之Bean的装配-Days02
查看>>
javascript函数的递归调用问题
查看>>
.net core swagger汉化
查看>>
R语言基础2
查看>>
do while 有例句体会循环的真正原理
查看>>
CSS学习
查看>>
linux后台执行命令:&和nohup
查看>>