java实现excel导入(导入数据List<M<String,Object>>对象,获取到数据后逻辑看你自业务),导出(无需单独配置)
regulartypeone这个是必传的(导入、导出都一样)规则,key是excel的中文名(英文也行),value是数据对象里面的字段名(就比如Tyes这个数据对象的yue、lian就是value)。1.此方法非常简易,只需要配置 一个Map<String, String>,key是你导出、或者导入的中文字段名,value是你字段对应的英文名称,也就是代码里面的命名。3.导入的时候有一些不常见时
·
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>

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