Java Excel的数据导入导出

news2024/12/26 10:51:17

引入依赖

<!-- EasyExcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.7</version>
</dependency>

<!--csv文件操作-->
<dependency>
    <groupId>net.sourceforge.javacsv</groupId>
    <artifactId>javacsv</artifactId>
    <version>2.0</version>
</dependency>

数据读取监听

导入数据时,程序解析和读取数据用,必须要!!!

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
/**
 * Excel数据解析监听器, 数据解析方法异步执行
 * @param <T>   Excel中数据的类型
 */
@Getter
@Setter
@NoArgsConstructor
public class ExcelListener<T> extends AnalysisEventListener<T> {
    // 加入一个判断标签,判断数据是否已经读取完
    private volatile boolean retryLock = false;
 
    // 解析完成后的数据集合, 监听对象初始化之后,立即初始化集合对象
    private final List<T> dataList = new ArrayList<>();
 
    // 每次最多导入条数
    private final int batchSize = 2000;
 
 
    /**
     * 获取解析后的数据集合, 如果数据还没有被解析完成,会对读取该集合的线程进行阻塞,直到数据读取完成之后,进行解锁。
     * 如果一次导入数据超过batchSize条,则以抛异常的形式阻止导入数据
     * @return  解析后的数据集合
     */
    public List<T> getDataList() {
        while (true){
            if (retryLock){
                if (dataList.size() > batchSize){
                    // 手动清空数据内存数据,减少内存消耗
                    dataList.clear();
                    throw new RuntimeException("一次最多导入"+ batchSize +"条数据");
                } else {
                    return dataList;
                }
            }
        }
    }
 
    /**
     * Excel每解析一行数据,就会调用一次该方法
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     *            analysis context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        dataList.add(data);
    }
 
    /**
     * 读取表头内容
     * @param headMap   表头部数据
     * @param context   数据解析上下文
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        //System.out.println("表头:" + headMap);
    }
 
    /**
     * 流中的数据解析完成之后,就会调用此方法
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 数据解析完成,解锁
        retryLock = true;
    }
 
    /**
     * 解析过程如果发生异常,会调用此方法
     * @param exception
     * @param context
     */
    @Override
    public void onException(Exception exception, AnalysisContext context){
        throw new RuntimeException("Excel数据异常,请检查或联系管理员!");
    }
}

Excel工具类

根据EasyExcel Model 导出工具类,CSV支持获取ExcelPropert

package net.demo.excel.common.util;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.csvreader.CsvWriter;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @desc: 根据EasyExcel Model 导出工具类
 * @Author: Swift
 * @Date: 2019-08-26 15:18

*/
public class ExportUtil {

    /**
     * 获取ExcelProperty Value
     * @return
     */
    public static <T extends BaseRowModel> String[] getFieldNames(Class<T> tClass) {
        Field[] fields = tClass.getDeclaredFields();
        List<String> headers = new ArrayList<>();
        for (Field field: fields) {
            ExcelProperty property = field.getAnnotation(ExcelProperty.class);
            if (property != null) {
                String[] s = property.value();
                if (s.length > 0) {
                    headers.add(s[0]);
                }
            }
        }
        String[] strings = new String[headers.size()];
        headers.toArray(strings);
        return strings;
    }

    /**
     * 获取filedName
     * @param vo
     * @param <T>
     * @return
     */
    public static <T extends BaseRowModel>  String[] getFields(T vo) {
        Field[] fields = vo.getClass().getDeclaredFields();
        List<String> columns = new ArrayList<>();
        for (Field field: fields) {
            ExcelProperty property = field.getAnnotation(ExcelProperty.class);
            if (property != null) {
                try {
                    field.setAccessible(true);
                    columns.add(field.get(vo)==null ? "" : field.get(vo).toString());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw new RuntimeException("写入内容到csv失败!");
                }
            }
        }

        String[] strings = new String[columns.size()];
        columns.toArray(strings);
        return strings;
    }

    public static <T extends BaseRowModel> void export(String type, List<T> vos, HttpServletResponse response, Class<T> t
    ) throws IOException {

        Boolean isCsv = "csv".equals(type);
        String fileName = "data" + CalendarUtils.getCurrentTime();
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        if (isCsv) {
            fileName += ".csv";
        } else {
            fileName += ".xlsx";
        }
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        ServletOutputStream outputStream = response.getOutputStream();

        if (isCsv) {
            CsvWriter csvWriter = new CsvWriter(outputStream, ',', Charset.forName("GBK"));
            csvWriter.writeRecord(getFieldNames(t));
            for (T vo : vos) {
                String[] fields = getFields(vo);
                csvWriter.writeRecord(fields);
            }
            csvWriter.close();
        } else {
            ExcelWriter excelWriter = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX, true);

            Sheet sheet = new Sheet(1, 0, t);
            excelWriter.write(vos, sheet);
            sheet.setAutoWidth(true);
            excelWriter.finish();
        }
        outputStream.flush();
    }

    public static <T extends BaseRowModel> void export(String type,String fileName, List<T> vos, HttpServletResponse response, Class<T> t
    ) throws IOException {

        Boolean isCsv = "csv".equals(type);
//        String fileName = "data" + CalendarUtils.getCurrentTime();
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        if (isCsv) {
            fileName += ".csv";
        } else {
            fileName += ".xlsx";
        }
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        ServletOutputStream outputStream = response.getOutputStream();

        if (isCsv) {
            CsvWriter csvWriter = new CsvWriter(outputStream, ',', Charset.forName("GBK"));
            csvWriter.writeRecord(getFieldNames(t));
            for (T vo : vos) {
                String[] fields = getFields(vo);
                csvWriter.writeRecord(fields);
            }
            csvWriter.close();
        } else {
            ExcelWriter excelWriter = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX, true);

            Sheet sheet = new Sheet(1, 0, t);
            excelWriter.write(vos, sheet);
            sheet.setAutoWidth(true);
            excelWriter.finish();
        }
        outputStream.flush();
    }

    /**
     * 根据Excel模板,批量导入数据
     * @param file  导入的Excel
     * @param clazz 解析的类型
     * @return  解析完成的数据
     */
    public static List<?> importExcel(MultipartFile file, Class<?> clazz){
        if (file == null || file.isEmpty()){
            throw new RuntimeException("没有文件或者文件内容为空!");
        }
        List<Object> dataList = null;
        BufferedInputStream ipt = null;
        try {
            InputStream is = file.getInputStream();
            // 用缓冲流对数据流进行包装
            ipt = new BufferedInputStream(is);
            // 数据解析监听器
            ExcelListener<Object> listener = new ExcelListener<>();
            // 读取数据
            EasyExcel.read(ipt, clazz,listener).sheet().doRead();
            // 获取去读完成之后的数据
            dataList = listener.getDataList();
        } catch (Exception e){
            log.error(String.valueOf(e));
            throw new RuntimeException("数据导入失败!" + e);
        }
        return dataList;
    }
}

WriterFactory

导出工厂实现了xlsx与csv 两种方式

package net.demo.excel.common.export;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.demo.excel.common.constants.Constants;
import net.demo.excel.common.constants.ExportTypeEnum;
import net.demo.excel.common.export.csv.CsvExport;
import net.demo.excel.common.export.excel.ExcelExport;


/**
 * 导出工厂
 */
@Data
@Slf4j
public class WriterFactory {

  /**
   * 返回文件流方式
   *
   * @param key
   * @param fileName
   * @param response
   * @return
   */
  public static ExportWriter getExportWriter(String key, String fileName,
      HttpServletResponse response) {
    ExportWriter exportWriter = null;
    try {
      OutputStream os = response.getOutputStream();
      ExportTypeEnum exportTypeEnum = ExportTypeEnum.findByType(key);
      fileName = fileName + exportTypeEnum.getSuffix();
      exportWriter = generateExportWriter(exportTypeEnum, os);
      response.setContentType("application/force-download");
      // 设置文件名
      response.addHeader("Content-Disposition",
          "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
    } catch (UnsupportedEncodingException e) {
      log.error("UnsupportedEncoding:", e);
    } catch (IOException e) {
      log.error("IOException:", e);
    }
    return exportWriter;
  }

  /**
   * 输出到文件方式
   *
   * @param key
   * @param fileName
   * @return
   */
  public static ExportWriter getExportWriter(String key, String fileName)
      throws FileNotFoundException {
    ExportTypeEnum exportTypeEnum = ExportTypeEnum.findByType(key);
    String filePath =
        Constants.EXPORT_TMP_DIR + File.separator + fileName + exportTypeEnum.getSuffix();
    File file = new File(filePath);
    OutputStream os = new FileOutputStream(file);
    ExportWriter exportWriter = generateExportWriter(exportTypeEnum, os);
    exportWriter.setFilePath(filePath);
    return exportWriter;
  }

  private static ExportWriter generateExportWriter(ExportTypeEnum exportTypeEnum, OutputStream os) {
    ExportWriter exportWriter = null;
    switch (exportTypeEnum) {
      case EXCEL:
        exportWriter = new ExcelExport(os);
        break;
      case CSV:
        exportWriter = new CsvExport(os);
        break;
      default:
    }
    return exportWriter;
  }
}

ExportModel抽象类

package net.demo.excel.common.export.model;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.csvreader.CsvWriter;

/**
 * 抽象实体
 */
public abstract class ExportModel {

  public abstract ExcelWriter getExcelWriter();

  public abstract Sheet getSheet();

  public abstract CsvWriter getCsvWriter();
}

CsvModel 实体类 

package net.demo.excel.common.export.csv.model;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.csvreader.CsvWriter;
import lombok.Data;
import net.demo.excel.common.export.model.ExportModel;

/**
 * csv相关实体
 */
@Data
public class CsvModel extends ExportModel {

  private CsvWriter csvWriter;

  @Override
  public ExcelWriter getExcelWriter() {
    return null;
  }

  @Override
  public Sheet getSheet() {
    return null;
  }

  @Override
  public CsvWriter getCsvWriter() {
    return csvWriter;
  }

  public CsvModel(CsvWriter csvWriter) {
    this.csvWriter = csvWriter;
  }
}

ExcelModel 实体类 

package net.demo.excel.common.export.excel.model;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.csvreader.CsvWriter;
import lombok.Data;
import net.demo.excel.common.export.model.ExportModel;

/**
 * excel,csv相关实体
 */
@Data
public class ExcelModel extends ExportModel {

  private ExcelWriter excelWriter;

  private Sheet sheet;

  @Override
  public ExcelWriter getExcelWriter() {
    return excelWriter;
  }

  @Override
  public Sheet getSheet() {
    return sheet;
  }

  @Override
  public CsvWriter getCsvWriter() {
    return null;
  }

  public ExcelModel(ExcelWriter excelWriter, Sheet sheet) {
    this.excelWriter = excelWriter;
    this.sheet = sheet;
  }
}

ExportWriter接口

package net.demo.excel.common.export;

import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.fastjson.JSONArray;
import java.util.List;
import net.demo.excel.common.bean.Column;

/**
 * 导出接口
 */
public interface ExportWriter {

  public static final int EXPORT_PAGE_SIZE = 5000;

  /**
   * 写入表头 结构为{"code":"字段名","title":"显示名"}
   *
   * @param columnList
   */
  public void writeTitle(List<Column> columnList);

  public <T extends BaseRowModel> void writeTitle(Class<T> t);

  /**
   * 添加内容 data的Map结构为{"字段名":"字段值"}
   *
   * @param dataList
   * @param columnList
   */
  public void appendContent(JSONArray dataList, List<Column> columnList);

  public <T extends BaseRowModel> void appendContent(List<T> vos, Class<T> t);

  /**
   * 关闭文件流
   */
  public void close();

  public String getFilePath();

  public void setFilePath(String filePath);

}

Column

package net.demo.excel.common.bean;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Column {

  /**
   * 英文名称
   */
  private String code;

  /**
   * 中文名称
   */
  private String title;
}

ExcelExport实现类

package net.demo.excel.common.export.excel;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.demo.excel.common.bean.Column;
import net.demo.excel.common.export.ExportWriter;
import net.demo.excel.common.export.excel.model.ExcelModel;
import net.demo.excel.common.export.model.ExportModel;
import net.demo.excel.common.util.ExportUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * excel具体实现
 */
@Slf4j
@Data
public class ExcelExport implements ExportWriter {

	private ExportModel model;

	private OutputStream os;

	private String filePath;

	/**
	 * 初始化
	 *
	 * @param os
	 */
	public ExcelExport(OutputStream os) {
		ExcelWriter writer = new ExcelWriter(os, ExcelTypeEnum.XLSX);
		Sheet sheet = new Sheet(1, 0);
		sheet.setSheetName(String.valueOf(1));
		this.model = new ExcelModel(writer, sheet);
		this.os = os;
	}

	/**
	 * 写标题
	 *
	 * @param columnList
	 */
	@Override
	public void writeTitle(List<Column> columnList) {
		List<List<String>> dataList = new ArrayList<List<String>>();
		//组装标题行
		for (int i = 0; i < columnList.size(); i++) {
			List<String> titleList = new ArrayList<String>();
			Column column = columnList.get(i);
			String title = column.getTitle();
			titleList.add(title);
			dataList.add(titleList);
		}
		model.getSheet().setHead(dataList);
	}

	/**
	 * 写标题
	 */
	@Override
	public <T extends BaseRowModel> void writeTitle(Class<T> t) {
		List<List<String>> dataList = new ArrayList<List<String>>();
		String[] columns = ExportUtil.getFieldNames(t);
		//组装标题行
		for (int i = 0; i < columns.length; i++) {
			List<String> titleList = new ArrayList<String>();
			String title = columns[i];
			titleList.add(title);
			dataList.add(titleList);
		}
		model.getSheet().setHead(dataList);
	}

	/**
	 * 内容追加
	 *
	 * @param dataList
	 * @param columnList
	 */
	@Override
	public void appendContent(JSONArray dataList, List<Column> columnList) {
		List<List<String>> dataArray = new ArrayList<List<String>>();
		//组装数据行
		for (Object obj : dataList) {
			JSONObject json = (JSONObject) JSONObject.toJSON(obj);
			List<String> rowList = new ArrayList<>();
			for (int j = 0; j < columnList.size(); j++) {
				Column columnMap = columnList.get(j);
				String code = columnMap.getCode();
				Object value = json.get(code);
				String valueStr = value == null ? "" : value.toString();
				rowList.add(valueStr);
			}
			dataArray.add(rowList);
		}
		model.getExcelWriter().write1(dataArray, model.getSheet());
	}

	/**
	 * 追加内容
	 *
	 * @param vos
	 * @param t
	 * @param <T>
	 */
	@Override
	public <T extends BaseRowModel> void appendContent(List<T> vos, Class<T> t) {
		model.getExcelWriter().write(vos, model.getSheet());
		model.getSheet().setAutoWidth(true);
	}

	/**
	 * 关闭流
	 */
	@Override
	public void close() {
		ExcelWriter writer = model.getExcelWriter();
		try {
			if (writer != null) {
				writer.finish();
			}
			os.close();
		} catch (IOException e) {
			log.error("os close error", e);
		}
	}

	@Override
	public String getFilePath() {
		return filePath;
	}

	@Override
	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}
}

CsvExport实现类

package net.demo.excel.common.export.csv;

import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.csvreader.CsvWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.demo.excel.common.bean.Column;
import net.demo.excel.common.export.ExportWriter;
import net.demo.excel.common.export.csv.model.CsvModel;
import net.demo.excel.common.export.model.ExportModel;
import net.demo.excel.common.util.ExportUtil;

/**
 * csv具体实现
 */
@Slf4j
@Data
public class CsvExport implements ExportWriter {

	private ExportModel model;

	private OutputStream os;

	private String filePath;

	/**
	 * 初始化
	 *
	 * @param os
	 */
	public CsvExport(OutputStream os) {
		CsvWriter csvWriter = new CsvWriter(os, ',', Charset.forName("GBK"));
		this.model = new CsvModel(csvWriter);
		this.os = os;
	}

	/**
	 * 写标题
	 *
	 * @param columnList
	 */
	@Override
	public void writeTitle(List<Column> columnList) {
		String[] headers = new String[columnList.size()];
		for (int i = 0; i < columnList.size(); i++) {
			Column tmp = columnList.get(i);
			headers[i] = tmp.getTitle();
		}
		try {
			model.getCsvWriter().writeRecord(headers);
		} catch (IOException e) {
			log.error("写入标题到csv失败!", e);
			throw new RuntimeException("写入标题到csv失败!");
		}
	}

	@Override
	public <T extends BaseRowModel> void writeTitle(Class<T> t){
		try {
			model.getCsvWriter().writeRecord(ExportUtil.getFieldNames(t));
		} catch (IOException e) {
			log.error("写入标题到csv失败!", e);
			throw new RuntimeException("写入标题到csv失败!");
		}
	}

	/**
	 * 内容追加
	 *
	 * @param dataList
	 * @param columnList
	 */
	@Override
	public void appendContent(JSONArray dataList, List<Column> columnList) {
		String[] content = null;
		List<String> codeList = new ArrayList<String>();
		for (int i = 0; i < columnList.size(); i++) {
			Column tmp = columnList.get(i);
			String code = tmp.getCode();
			codeList.add(code);
		}
		try {
			for (Object obj : dataList) {
				JSONObject json = (JSONObject) JSONObject.toJSON(obj);
				content = new String[codeList.size()];
				for (int i = 0; i < codeList.size(); i++) {
					String code = codeList.get(i);
					Object value = json.get(code);
					content[i] = value == null ? "" : value.toString();
				}
				model.getCsvWriter().writeRecord(content);
			}
		} catch (Exception e) {
			log.error("写入内容到csv失败!", e);
			throw new RuntimeException("写入内容到csv失败!");
		}
	}

	@Override
	public <T extends BaseRowModel> void appendContent(List<T> vos, Class<T> t) {
		try {
			for (T vo : vos) {
				String[] fields = ExportUtil.getFields(vo);
				model.getCsvWriter().writeRecord(fields);
			}
		} catch (IOException e) {
			log.error("写入内容到csv失败!", e);
			throw new RuntimeException("写入内容到csv失败!");
		}
	}

	/**
	 * 关闭
	 */
	@Override
	public void close() {
		CsvWriter csvWriter = model.getCsvWriter();
		if (csvWriter != null) {
			csvWriter.close();
		}
		try {
			os.close();
		} catch (IOException e) {
			log.error("os close error", e);
		}
	}

	@Override
	public String getFilePath() {
		return filePath;
	}

	@Override
	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}
}

创建导入数据模板类

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import lombok.experimental.Accessors;
 
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
 
/**
 * 数据导入的Excel模板实体
 */
@Data
public class ImportExcelVo implements Serializable {
    private static final long serialVersionUID = 1L;
 
    @ColumnWidth(20)
    @ExcelProperty(value = "公司名称", index = 0)
    private String name;
 
    @ColumnWidth(20)
    @ExcelProperty(value = "公司联系电话", index = 1)
    private String phone;
 
    @ColumnWidth(28)
    @ExcelProperty(value = "公司统一社会信用代码", index = 2)
    private String creditCode;
 
    @ColumnWidth(15)
    @ExcelProperty(value = "区域", index = 3)
    private String province;
 
    @ColumnWidth(15)
    @ExcelProperty(value = "公司法人", index = 4)
    private String legalPerson;
 
    @ExcelProperty(value = "备注", index = 5)
    private String remark;
}

创建数据导出模板

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import lombok.experimental.Accessors;
 
import java.io.Serializable;
 
/**
 * 资质信息导出实体
 */
@Data   // Lombok注解,用于生成getter setter
@Accessors(chain = true) //Lombok注解,链式赋值使用
public class ExportExcelVo extends BaseRowModel {
    private static final long serialVersionUID = 1L;
 
    @ColumnWidth(25)
    @ExcelProperty(value = "企业名称", index = 0)
    private String name;
 
    @ColumnWidth(25)
    @ExcelProperty(value = "社会统一信用代码", index = 1)
    private String creditCode;
 
    @ColumnWidth(15)
    @ExcelProperty(value = "曾用名", index = 2, converter = NullConverter.class)
    private String formerName;
 
    @ColumnWidth(15)
    @ExcelProperty(value = "公司法人", index = 3)
    private String legalPerson;
 
    @ExcelProperty(value = "区域", index = 4)
    private String province;
 
    @ExcelProperty(value = "录入时间", index = 5)
    private String createTime;
 
    @ColumnWidth(15)
    @ExcelProperty(value = "公司股东", index = 6)
    private String stockholder;
 
    @ExcelProperty(value = "企业联系方式", index = 7)
    private String contact;
 
}

使用方法

/**
 * Excel批量导入数据
 *
 * @param file 导入文件
 */
@RequestMapping(value = "/import", method = RequestMethod.POST)
public CommonResponse<String> importEvents(MultipartFile file) {
  try {
    List<?> list = ExportUtil.importExcel(file, ImportExcelVo.class);
    System.out.println(list);
    return CommonResponse.success("数据导入完成");
  } catch (Exception e) {
    return CommonResponse.error("数据导入失败!" + e.getMessage());
  }
}


//生成excel文件
try {
    exportWriter = WriterFactory.getExportWriter(
        dto.getExportType() == null ? "csv" : dto.getExportType(), fileName);
    exportWriter.writeTitle(PhoneExportVO.class);
    exportWriter.appendContent(list, PhoneExportVO.class);
} catch (Exception e) {
    log.error("导出失败", e);
    throw new BaseException("导出失败");
} finally {
    if (exportWriter != null) {
        exportWriter.close();
    }
}


ExportWriter exportWriter = WriterFactory.getExportWriter(exportType, fileName);
List<Column> columns = trunkAreaVOResp.getColumns();
exportWriter.writeTitle(columns);
JSONArray dataList = (JSONArray) JSON.toJSON(trunkAreaVOResp.getTrunkArea());
exportWriter.appendContent(dataList, columns);
exportWriter.close();

EasyExcel自定义转换器Converter

Timestamp 转换器

package com.yandype.util.easyExcel;
 
 
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
 
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
 
public class TimestampConverter implements Converter<Timestamp>{
 
	@Override
    public Class<Timestamp> supportJavaTypeKey() {
        return Timestamp.class;
    }
 
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
 
	@Override
	public WriteCellData<String> convertToExcelData(Timestamp timestamp, ExcelContentProperty contentProperty,
			GlobalConfiguration globalConfiguration) throws Exception {
		return new WriteCellData<String>(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp));
	}
 
}

NullConverter

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

public class NullConverter implements Converter<String> {

	/**
	 * 回到 Java 中的对象类型
	 *
	 * @return 支持 Java 类
	 */
	@Override
	public Class supportJavaTypeKey() {
		return String.class;
	}

	/**
	 * * 返回 excel 中的对象枚举
	 * * @return 支持 {@link Cell DataTypeEnum}
	 * */
	@Override
	public CellDataTypeEnum supportExcelTypeKey() {
		return CellDataTypeEnum.STRING;
	}

	/**
	 * 将excel对象转换为Java对象
	 *
	 * @param cellData
	 * Excel 单元格数据。NotNull。
	 * @param contentProperty
	 * 内容属性。可空。
	 * @param globalConfiguration
	 * 全局配置。NotNull。
	 * @return 要放入 Java 对象的数据
	 * @抛出异常
	 *             例外。
	 */
	@Override
	public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
		return "-".equals(cellData.getStringValue()) ? null : cellData.getStringValue();
	}

	/**
	 * 将 Java 对象转换为 excel 对象
	 *
	 * @参数值
	 * Java 数据.NotNull。
	 * @param contentProperty
	 * 内容属性。可空。
	 * @param globalConfiguration
	 * 全局配置。NotNull。
	 * @return 数据放入 Excel
	 * @抛出异常
	 *             例外。
	 */
	@Override
	public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
		return new CellData<>(null == value ? "-" : value);
	}
}

使用方法一

每个字段都要添加@ExcelProperty(converter = NullConverter.class)代码,如果遇到大量的数据字段去填充处理会增加很多工作量。转换器仅支持需要被处理的数据字段,也就是适用于从数据库查询出来已有的数据,如日期格式或性别字段做转换时才生效

使用方法二

File uploadFile = File.createTempFile("export", ".xlsx");
String templateFilePath = systemUrl + "/template/exportPublishShop.xlsx";
 
ExcelWriterSheetBuilder excelWriterSheetBuilder = 
EasyExcel.write(uploadFile).registerConverter(new TimestampConverter()).withTemplate(templateFilePath).sheet();
 
List<Map<String, String>> productList = 查询数据数据
 
// productList 如果数据量很大一定要做分页查询,避免占用内存过大
excelWriterSheetBuilder.doFill(productList);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将ChatGPT整合到Word中

引言自ChatGPT出现&#xff0c;各种基于它的软件扩展纷至沓来&#xff0c;目前Word支持ChatGPT的add-in有两款&#xff0c;可以通过:插入->获取加载项->搜索openai查看。其中Ghostwriter从介绍上看功能比较单一&#xff0c;而且软件需要购买&#xff0c;用自己的API-key&…

php5.6.9安装sqlsrv扩展(windows)

报错:Marning: PHP Startup: Unable to load dynamic 1library D:lphpstudy_prolExtensionslphpl(phps.6.9ntslextphp_ pdo_sqlsry 56 nts′找不到指定的模块。in Unknown on line 0 整整搞了一天才终于解决 我用的是phpstudy_pro&#xff08;也就是小皮v8.1版本&#xff09;&…

Twitter多账号想要做到防关联?还是得靠它

接着上一篇Twitter养号攻略的文章&#xff0c;这篇龙哥就来详细讲讲当批量注册和管理Twitter账号时需要怎么防关联。 Twitter作为海外最流行的社交网站之一&#xff0c;它拥有很庞大的用户量&#xff0c;所以很多跨境电商都会通过Twitter来投放广告、推广自己的产品、提高曝光度…

pdf生成为二维码

当今数字时代&#xff0c;人们越来越依赖在线工具来处理各种任务&#xff0c;比如合并、拆分和压缩PDF等。Mai File就是这样一个在线工具&#xff0c;它可以将PDF文件转换成在线链接&#xff0c;方便您和他人轻松地查看和共享文件。 Mai File的使用非常简单&#xff0c;您只需…

从GPT到chatGPT(三):GPT3(二)

GPT3&#xff08;二&#xff09; 前言 因为上一篇文章 从GPT到chatGPT&#xff08;三&#xff09;&#xff1a;GPT3&#xff08;一&#xff09;阅读量挺高&#xff0c;给了我继续更新对该论文进行解读的莫大动力。这篇文章主要讲原论文的第三章&#xff08;Results&#xff0…

Vue2快速入门(三)前端项目架构搭建、Axios、Vue-Router

文章目录VueCli 4.3搭建前端项目架构创建vue项目前端项目目录结构添加axios添加cube-ui依赖创建新目录http客户端Axios什么是Axios&#xff1f;GET请求方式POST请求方式Axios封装通用后端请求API模块Vue-Router开发前端项目路由什么是vue-router&#xff1f;配置项目路由VueCli…

Hive SQL语言:DDL建库、建表

Hive SQL语言&#xff1a;DDL建库、建表 Hive数据模型总览 Hive SQL之数据库与建库 SQL中DDL语法的作用 ⚫ 数据定义语言(Data Definition Language, DDL)&#xff0c;是SQL语言集中对数据库内部的对象结构进行创建&#xff0c;删除&#xff0c;修改等的操作语言&#xff…

《反电信网络诈骗法》实行,Galaxybase图平台成为电信反诈黑科技

电信网络诈骗在当前的数字化生活中始终是一个高频讨论词。 近年来&#xff0c;随着互联网技术发展迅速&#xff0c;线上交易趋于频繁化&#xff0c;以电信网络诈骗为代表的新型网络犯罪行为也变得越来越高发。根据中国信通院《新形势下电信网络诈骗治理研究报告&#xff08;20…

交互式推荐在外卖场景的探索与应用

外卖场景的用户停留时长低于传统电商&#xff0c;对用户实时需求的理解和反馈有更高的要求。针对业务问题&#xff0c;外卖推荐团队从2021年起开始持续投入&#xff0c;最终摸索出了一套适用于外卖场景的交互式推荐架构和策略&#xff0c;并取得了较好的收益。下文将详细介绍外…

论文:拖曳线列阵拖曳噪声抑制的试验研究,阅读笔记

目录摘要目前的噪声来源和抑制的方法1.来源2.抑制方法针对流致振动引起的间接噪声提出解决方法1.结构减振优化设计2.扩大水听器与护套的间距实验1.如何划分对象组2.实验装置实验结果实验组1&#xff1a;结构减振优化设计的效果实验组2&#xff1a;扩大水听器与护套的间距的效果…

跨境电商卖家敦煌、雅虎、乐天、亚马逊测评自养号的重要性!

作为亚马逊、敦煌、乐天、雅虎等跨境的卖家&#xff0c;这两年以来&#xff0c;面对流量越来越贵的现实&#xff0c;卖家需要更加珍惜每次访问listing页面的流量&#xff0c;把转化做好&#xff0c;把流量尽可能转化为更多的订单。 提升转化率的技巧 提升产品转化率&#xff0…

springsecurity最基础的授权过程

​ 在SpringSecurity中&#xff0c;会使用默认的FilterSecurityInterceptor来进行权限校验。在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication&#xff0c;然后获取其中的权限信息。当前用户是否拥有访问当前资源所需的权限。 ​ 所以我们在项…

【JAVA八股文】JVM虚拟机相关

JVM虚拟机相关1. JVM 内存结构2. JVM 内存参数3. JVM 垃圾回收4. 内存溢出5. 类加载6. 四种引用7. finalize1. JVM 内存结构 结合一段 java 代码的执行理解内存划分 执行 javac 命令编译源代码为字节码执行 java 命令 创建 JVM&#xff0c;调用类加载子系统加载 class&#xf…

使用 ChatGPT 、Stable Diffuison、React和NodeJS构建网站图库

本文译者为360奇舞团前端开发工程师原文标题&#xff1a;Building a website gallery with ChatGPT, Stable Diffusion, React and NodeJS原文作者&#xff1a;Nevo David原文地址&#xff1a;https://javascript.plainenglish.io/building-a-website-gallery-with-chatgpt-sta…

Apollo Planning规划算法仿真调试(15):使用Vscode断点调试apollo的方法更新版

前言 使用Vscode断点调试apollo的方法之前在该专栏写过一篇分享,后台很多粉丝留言希望写的更详细一点,所以更新一版,尽量将配置过程详细描述,并且附上完整的配置文档。 Vscode 作为轻量化的调试工具深受广大开发者的青睐,虽然大家都用它来看新闻逛论坛炒股,但是用它开发…

【郭东白架构课 模块一:生存法则】01|模块导学:是什么在影响架构活动的成败?

你好&#xff0c;我是郭东白。这节课是我们模块一的导入部分&#xff0c;我会先来介绍模块的主要内容&#xff0c;以及为什么我要讲生存法则这个话题。 一名软件架构师要为相对复杂的业务制定&#xff0c;并且引导实施一个结构化的软件方案。这个发现最终方案和推动实施的过程&…

智加科技上市箭在弦上,头部自动驾驶技术企业何去何从?

/ 导读 /受禾赛科技美股上市成功的影响&#xff0c;中国商用车自动驾驶技术公司智加科技也传出了即将拆分在美股上市的消息。其中&#xff0c;智加科技的中国部分据传将被满帮收购&#xff0c;并且将并入自动驾驶卡车公司挚途科技。至于美国部分&#xff0c;将寻求独立上市。对…

python切片总算搞明白了

不会python已久矣&#xff01; 简单切片 简单切片指的是这样的切片形式&#xff1a;a[start:stop]&#xff0c; 左闭右开 负索引可以直接代表那个值 >>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[2:3][2]>>> a[5:9][5, 6, 7, 8]>>> a[5…

电商导购CPS,拼多多(多多进宝)如何跟单实现用户和订单绑定

前言 大家好&#xff0c;我是小悟 做过自媒体的小伙伴都知道&#xff0c;不管是发图文还是发短视频&#xff0c;直播也好&#xff0c;可以带货。在你的内容里面挂上商品&#xff0c;你自己都不需要囤货&#xff0c;如果用户通过这个商品下单成交了&#xff0c;自媒体平台就会…

Cortex-M0中断控制和系统控制

目录1.NVIC和系统控制块特性2.中断使能和清除使能3.中断挂起和清除挂起4.中断优先级5.中断控制的通用汇编代码使能和禁止中断设置和清除中断挂起状态设置中断优先级6.异常屏蔽寄存器&#xff08;PRIMASK&#xff09;7.中断输入和挂起行为8.中断等待9.系统异常的控制寄存器10.系…