1.此方法非常简易,只需要配置 一个Map<String, String>,key是你导出、或者导入的中文字段名,value是你字段对应的英文名称,也就是代码里面的命名。

2.该方法不支持分sheet,百万级数据需要自己改造了。

3.导入的时候有一些不常见时间格式的数据可能有点坑,需要个人去修改我里面有一小段的代码逻辑,我文中会指出。

4.该项目基于springboot框架

        
        主要依赖
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.1</version>
        </dependency>

一、一些配置的通用方法,下面有引用

(1)该方法把数据对象转成Map<Sring,Object>类型

import com.google.common.collect.Lists;
import org.apache.logging.log4j.util.Strings;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class LittleTools {

    /**
     * 遍历实体数据
     *
     * @param t
     * @param <T>
     * @return
     * @throws IllegalAccessException
     */
    public static <T> List<String> entityTraverse(T t) throws IllegalAccessException {

        List<String> oneData = Lists.newLinkedList();
        Class cls = t.getClass();
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            //获取实体的所有属性字段
//            String key = declaredField.getName();
            //获取所有字段属性值
            String value = declaredField.get(t).toString();
            if (Strings.isBlank(value)) {
                value = "NaN";
            }
            oneData.add(value);
        }
        return oneData;
    }

    //批量存储数据,1000条数据一个List
    public static <T> List<List<T>> circulationFunc(List<T> items, int size) {
        int a = items.size();
        int y = 0;
        List<List<T>> partAll = Lists.newLinkedList();
        while (y < a) {
            List<T> part = Lists.newLinkedList();
            for (int j = 0; j < size; j++) {
                T b = items.get(y);
                part.add(b);
                ++y;
                if (y == a) {
                    break;
                }
            }
            partAll.add(part);
        }
        return partAll;
    }

    /**
     * 实体对象转成Map
     *
     * @param obj 实体对象
     * @return
     */
    public static Map<String, Object> object2Map(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null) {
            return map;
        }
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                String typeName = field.getGenericType().getTypeName();
                if (typeName.startsWith("java.util")) {
                    map.put(field.getName(), String.valueOf(field.get(obj)));
                } else {
                    map.put(field.getName(), field.get(obj));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * Object 转 List
     */
    public static List<String> objectToList(Object obj) {
        List<String> result = new ArrayList<String>();
        if (obj instanceof ArrayList<?>) {
            for (Object o : (List<?>) obj) {
                result.add(String.class.cast(o));
            }
        }
        return result;
    }

    /**
     * Map转成实体对象
     *
     * @param map   实体对象包含属性
     * @param clazz 实体对象类型
     * @return
     */
    public static Object mapToObject(Map<String, Object> map, Class<?> clazz) {
        if (map == null) {
            return null;
        }
        Object obj = null;
        try {
            obj = clazz.newInstance();

            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                field.setAccessible(true);
                field.set(obj, map.get(field.getName()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    /**
     * json转map,且key转驼峰
     */
//    public static Map<String, Object> jsonToMap(JSONObject param) {
//
//        Map<String, Object> result = Maps.newHashMap();
//        Set<String> keys = param.keySet();
//        for (String key : keys) {
//            String keyCp = toTuoFengFun(key);
//            Object value = param.get(key);
//            result.put(keyCp, value);
//        }
//        return result;
//
//    }
    public static String toTuoFengFun(String str) {

        char[] cs = str.toCharArray();
        int n = 0;
        for (char c : cs) {
            if (c == '_') {
                cs[n + 1] -= 32;
            }
            n = n + 1;
        }
        String strAfter = String.valueOf(cs).replace("_", "");
        return strAfter;

    }

    public static String buildSetClause(Map<String, Object> tbFileEntityMap) {

        StringBuilder setCode = new StringBuilder("set ");
        for (String key : tbFileEntityMap.keySet()) {
            Object value = tbFileEntityMap.get(key);
            if (value != null && !key.equals("id")) {
                setCode.append("n.").append(key).append("='").append(value).append("',");
            }
        }
        setCode = new StringBuilder(setCode.substring(0, setCode.length() - 1));
        return setCode.toString();
    }

}

(2)判空方法

import java.util.List;
import java.util.Map;

public class ValidatedUtils {
    public static boolean isBlank(Object o) {
        boolean result = false;
        if(o == null) {
            result = true;
        } else {
            if(o instanceof String && o.equals("")||o instanceof String && o.equals("None")) {
                result = true;
            } else if(o instanceof List && ((List<?>) o).size() == 0) {
                result = true;
            } else if(o instanceof Map && ((Map<?, ?>) o).size() == 0) {
                result = true;
            }
        }
        return result;
    }

    public static  boolean isNotBlank(Object o) {
        return !isBlank(o);
    }

    public static String formatUidValue(String input) {
        input = input.replace("'","\'")
                .replace("\"","\\\"");
        return input;
    }
}

一、Service层

import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

public interface RxxService {

    void relistdownloadExcel(HttpServletResponse response, List<?> datas, Map<String, String> inform, String name) throws IOException;

    List<Map<String,Object>> upload(MultipartFile file,Map<String, String> tranfer) throws IOException;


}

二、实现Service层

import com.alibaba.excel.EasyExcel;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.shuai.secdkill.config.LittleTools;
import com.shuai.secdkill.config.ValidatedUtils;
import com.shuai.secdkill.service.RxxService;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RxxServiceimpl implements RxxService {




    @Override
    public void relistdownloadExcel(HttpServletResponse response, List<?> data, Map<String, String> inform, String name) throws IOException {

        List<Map<String,Object>> datas=new ArrayList<>();
        if(ValidatedUtils.isNotBlank(data)){
                datas=data.stream().map(s->{
                Map<String, Object> sig = LittleTools.object2Map(s);
                return sig;
            }).collect(Collectors.toList());
        }
        List<List<String>> headone=this.headone(inform);
        List<String> headjudge=this.headjudge(inform);
        ObjectMapper mapper = new ObjectMapper();
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            response.setHeader("Access-Control-Expose-Headers", "Content-disposition");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream()).autoCloseStream(Boolean.FALSE).head(headone).sheet("" + System.currentTimeMillis()).doWrite(dataListone(datas,headjudge,inform));
        } catch (Exception e) {
            Map<String,Object> infrom=new HashMap<>();
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().println(mapper.writeValueAsString(infrom.put("msg", "下载文件失败" + e.getMessage())));
        }

    }

    @Override
    public List<Map<String, Object>> upload(MultipartFile file,Map<String, String> tranfer) throws IOException {
        List<List<Object>> list = new ArrayList<>();
        if (null != file) {
            String fileName = file.getOriginalFilename();
            if(ValidatedUtils.isNotBlank(fileName)){
                if(!fileName.toLowerCase().matches("^.*(csv)$")&&fileName.toLowerCase().matches("^.*(xls|XLS|XLs|Xls|xlsx)$")){
                    String edition_2003 = "^.+\\.(?i)(xls)$";        // Excel_2003版本
                    String edition_2007 = "^.+\\.(?i)(xlsx)$";        // Excel_2007版本
                    Workbook wb = null;
                    if(fileName.equals(edition_2003)) {
                        wb = new HSSFWorkbook(file.getInputStream());
                    } else if (fileName.matches(edition_2007)) {
                        wb = new XSSFWorkbook(file.getInputStream());
                    }
                    if(null!=wb){
                        // 得到第一个shell
                        Sheet sheet = wb.getSheetAt(0);
                        // 得到Excel的行数
                        int totalRows = sheet.getPhysicalNumberOfRows();
                        // 得到Excel的列数(前提是有行数)
                        int totalCells = 0;
                        if (totalRows > 1 && sheet.getRow(0) != null) {
                            totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
                        }
                        for (int r = 0; r < totalRows; r++) {
                            Row row = sheet.getRow(r);
                            if (row == null) {
                                continue;
                            }
                            List<Object> line = new ArrayList<>();
                            for (int c = 0; c < totalCells; c++) {
                                Cell cell = row.getCell(c);

                                if(cell==null){
                                    line.add(null);
                                }else {
//                                  时间格式要是有问题在这修改 ,比如|| dataFormatter.formatCellValue(cell).contains("?")再加一种时间格式的判断情况
                                    DataFormatter dataFormatter = new DataFormatter();
                                    if(String.valueOf(cell.getCellType()).equals("NUMERIC")){
                                        if(dataFormatter.formatCellValue(cell).contains("/")||dataFormatter.formatCellValue(cell).contains(":")){
                                            Date d = cell.getDateCellValue();
                                            DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                            String dates = formater.format(d);
                                            line.add(dates);
                                        }else {
                                            line.add(dataFormatter.formatCellValue(cell));
                                        }
                                    }else {

                                        line.add(dataFormatter.formatCellValue(cell));
                                    }
                                }
                            }

                            if (line.size() > 0) {
                                list.add(line);
                            }
                        }
                    }
                }
            }
        }

        List<Map<String,Object>> data=new ArrayList<>();
        if(ValidatedUtils.isNotBlank(list)){
            List<Object> key=list.get(0);
            if(ValidatedUtils.isNotBlank(tranfer)){
                if(key.size()==tranfer.keySet().size()){
                    List<Object> news=new ArrayList<>();
                    for(Object sig:key){
                        news.add(tranfer.get(String.valueOf(sig)));
                    }
                    key=news;
                }
            }
            for (int i = 1; i < list.size(); i++) {
                List<Object> values=list.get(i);
                Map<String,Object> shuju=new HashMap<>();
                for (int a = 0; a < key.size(); a++) {
                    shuju.put(String.valueOf(key.get(a)),values.get(a));
                }
                data.add(shuju);
            }
        }
        return data;
    }



    private List<List<Object>> dataListone(List<Map<String,Object>> entities,List<String> headjudge,Map<String, String> inform) {
        List<List<Object>> list = Lists.newArrayList();
        for (int i = 0; i < entities.size(); i++) {
            Map<String,Object> ent = entities.get(i);
            List<Object> data = Lists.newArrayList();
            for(String head:headjudge){
                if(ValidatedUtils.isNotBlank(inform.get(head))){
                    data.add(ent.get(inform.get(head)));
                }else {
                    data.add("");
                }
            }
            list.add(data);
        }
        return list;
    }
    private List<List<String>> headone(Map<String, String> params) {
        List<List<String>> list = Lists.newArrayList();
        for(String head:params.keySet()){
            List<String> head0 = Lists.newArrayList();
            head0.add(head);
            list.add(head0);
        }
        return list;
    }
    private List<String> headjudge(Map<String, String> params) {
        List<String> list=new ArrayList<>();
        for(String head:params.keySet()){
            list.add(head);
        }
        return list;
    }

三、实现方法

1.数据对象举个例子

regulartypeone这个是必传的(导入、导出都一样)规则,key是excel的中文名(英文也行),value是数据对象里面的字段名(就比如Tyes这个数据对象的yue、lian就是value)。下面两个接口,第一个是导出,第二个是导入。
import lombok.Data;

@Data
public class Tyes {
    private String yue;
    private String lian;

}


import com.shuai.secdkill.entity.Tyes;


import com.shuai.secdkill.service.RxxService;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/testone")
public class ExcelController {
    
    
    private static Map<String, String> regulartypeone = new LinkedHashMap();
    static {
        regulartypeone.put("爱","yue");
        regulartypeone.put("清","lian");
    }

    @Autowired
    private RxxService rxxService;

    @PostMapping("downloadExcelnormall")
    public void normall(HttpServletResponse response) throws IOException {
        
        List<Tyes> data=new ArrayList<>();
        //data必须是List<Tyes>这种的数据对象,不能是List<Map<Sting,Object>>这种
        rxxService.relistdownloadExcel(response,data,regulartypeone,"表1");


    }

    @PostMapping("/uploadone")
    public synchronized List<List<Object>> upload(@RequestParam("file") MultipartFile file) throws Exception {
        try {
           List<Map<String,Object>> data= rxxService.upload(file,regulartypeone);

        }catch (Exception e){
            e.printStackTrace();
        }
        return null;

    }

    

}

导入的Post请求,这个Content-Type这需要注意一下,如果失败,可以改成我这种配置multipart/form-data; boundary=<calculated when request is sent>

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐