程序中很多时候会出现表格的读写操作,这里做一个总结,方便后续查找
poi总结
依赖
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>2.11.0</version> </dependency>
代码总结
package com.isi.utils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
public class PoiUtils {
/**
*第一行和字段名保持一致
* @param datas 写入数据
* @param fields 写入的字段名
* @param filePath 输出文件名
* @param overwirte 是否覆盖
* @param <T>
* @return
*/
public static <T> boolean commonDataToExcel(List<T> datas, String[] fields, String filePath, boolean overwirte) {
filePath = checkFile(filePath);
boolean flag = false;
//创建HSSFWorkbook对象(excel的文档对象)
XSSFWorkbook wb = new XSSFWorkbook();
XSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
// 建立新的sheet对象(excel的表单)
XSSFSheet sheet = wb.createSheet();
for (int j = 0; j < datas.size(); j++) {
Map map = objectToMap(datas.get(j));
// 在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
XSSFRow row0 = sheet.createRow(0);
for (int i = 0; i < fields.length; i++) {
row0.createCell(i).setCellValue(fields[i]);
}
XSSFRow row = sheet.createRow(j + 1);
for (int i = 0; i < fields.length; i++) {
Object oldValue = map.get(fields[i]);
String cellValue = null;
if (oldValue != null && oldValue instanceof Date) {
cellValue =format((Date) oldValue, "yyyy-MM-dd HH:mm:ss");
} else {
cellValue = nullToEmpty(oldValue);
}
//避免 The maximum length of cell contents (text) is 32767 characters异常
if (cellValue.length() > 32767) {
cellValue = cellValue.substring(0, 32767);
}
row.createCell(i).setCellValue(cellValue);
}
System.out.println(j + " to cell");
}
//输出Excel文件1
FileOutputStream output = null;
try {
if (overwirte) {
new File(filePath).delete();
}
output = new FileOutputStream(filePath);
wb.write(output);//写入磁盘
flag = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("data size is " + datas.size() + " to path===" + filePath);
return flag;
}
private static String checkFile(String filePath) {
if (!filePath.endsWith(".xlsx") || !filePath.endsWith(".xls")) {
filePath = filePath + ".xlsx";
}
File file = new File(filePath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
return filePath;
}
/**
* 读取表格到map key是列下标(从0 开始)
* @param path 文件名
* @param columns 读取的列
* @param skipFirst 是否跳过第一行
* @return
*/
public static List<Map<Integer,Object>> read2IndexMap(String path, Integer[] columns, boolean skipFirst) {
InputStream inputStream = null;
List<Map<Integer,Object>> datas=new ArrayList<>();
try {
inputStream = new FileInputStream(path);
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
int rowNum = row.getRowNum();
if (rowNum == 0 && skipFirst) {
continue;
}
Map<Integer,Object> map=new HashMap<>();
for (Integer column : columns) {
Cell cell = row.getCell(column);
Object value = getCellValue(cell);
map.put(column,value);
}
datas.add(map);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return datas;
}
private static Object getCellValue(Cell cell) {
Object value = null;
if(cell==null){
return null;
}
CellType cellType = cell.getCellType();
if(cell!=null){
if(cellType.equals(CellType.STRING)){
value = cell.getRichStringCellValue().getString();
}else if(cellType.equals(CellType.NUMERIC)){
if (DateUtil.isCellDateFormatted(cell)) { // 如果是date类型则 ,获取该cell的date值
value = cell.getDateCellValue();
// System.out.println(cell.getDateCellValue());
} else {// 纯数字
value = cell.getNumericCellValue();
// System.out.println(cell.getNumericCellValue());
}
}else if(cellType.equals(CellType.BOOLEAN)){
value = cell.getBooleanCellValue();
} else if(cellType.equals(CellType.FORMULA)){
value = cell.getCellFormula();
} else if(cellType.equals(CellType.BLANK)){
} else if(cellType.equals(CellType.ERROR)){
}
}
return value;
}
private static Integer getNum(char ch) {
return Integer.valueOf(ch) - 65;
}
private static String nullToEmpty(Object obj) {
return obj == null ? "" : obj.toString();
}
/***
* 将对象转换为map对象
* @param thisObj 对象
* @return
*/
public static Map objectToMap(Object thisObj) {
Map map = new HashMap();
if(thisObj instanceof Map){
return (Map) thisObj;
}
Class c;
try {
c = Class.forName(thisObj.getClass().getName());
//获取所有的方法
Method[] m = c.getMethods();
for (int i = 0; i < m.length; i++) { //获取方法名
String method = m[i].getName();
//获取get开始的方法名
if (method.startsWith("get") && !method.contains("getClass")) {
try {
//获取对应对应get方法的value值
Object value = m[i].invoke(thisObj);
if (value != null) {
//截取get方法除get意外的字符 如getUserName-->UserName
String key = method.substring(3);
//将属性的第一个值转为小写
key = key.substring(0, 1).toLowerCase() + key.substring(1);
//将属性key,value放入对象
map.put(key, value);
}
} catch (Exception e) {
// TODO: handle exception
System.out.println("error:" + method);
}
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return map;
}
/**
* 获取属性名数组
*/
public static String[] getFiledName(Object o) {
Field[] fields = o.getClass().getDeclaredFields();
String[] fieldNames = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
fieldNames[i] = fields[i].getName();
System.out.println(fieldNames[i]);
}
return fieldNames;
}
private static String format(Date date, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(date);
}
/**
*自定义第一行
* @param datas
* @param fields 选中的字段
* @param names 选中字段对应写入的名称
* @param filePath
* @param overwirte
* @param <T>
* @return
*/
public static <T> boolean commonDataToExcel(List<T> datas, String[] fields, String[] names, String filePath, boolean overwirte) {
if (!filePath.endsWith(".xlsx") || !filePath.endsWith(".xls")) {
filePath = filePath + ".xlsx";
}
/* File file = new File(filePath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}*/
boolean flag = false;
//创建HSSFWorkbook对象(excel的文档对象)
XSSFWorkbook wb = new XSSFWorkbook();
XSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
// 建立新的sheet对象(excel的表单)
XSSFSheet sheet = wb.createSheet();
for (int j = 0; j < datas.size(); j++) {
Map map = objectToMap(datas.get(j));
// 在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
XSSFRow row0 = sheet.createRow(0);
for (int i = 0; i < names.length; i++) {
row0.createCell(i).setCellValue(names[i]);
}
XSSFRow row = sheet.createRow(j + 1);
for (int i = 0; i < fields.length; i++) {
Object oldValue = map.get(fields[i]);
String cellValue = null;
if (oldValue != null && oldValue instanceof Date) {
cellValue = format((Date) oldValue, "yyyy-MM-dd HH:mm:ss");
} else {
cellValue = nullToEmpty(oldValue);
}
//避免 The maximum length of cell contents (text) is 32767 characters 异常
if (cellValue.length() > 32767) {
cellValue = cellValue.substring(0, 32767);
}
row.createCell(i).setCellValue(cellValue);
}
System.out.println(j + " to cell");
}
//输出Excel文件1
FileOutputStream output = null;
try {
if (overwirte) {
new File(filePath).delete();
}
output = new FileOutputStream(filePath);
wb.write(output);//写入磁盘
flag = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("data size is " + datas.size() + " to path===" + filePath);
return flag;
}
/**
* 多个 sheet写入
* @param datasMap key是sheet名称,value是 写入的数据
* @param fields 读取数据的字段名
* @param names 输出数据的列名
* @param filePath 数据文件名
* @param overwirte
* @param <T>
* @return
*/
public static <T> boolean MultcommonDataToExcel(Map<String,List<T>> datasMap, Object[] fields, String[] names, String filePath, boolean overwirte) {
if (!filePath.endsWith(".xlsx") || !filePath.endsWith(".xls")) {
filePath = filePath + ".xlsx";
}
/* File file = new File(filePath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}*/
boolean flag = false;
//创建HSSFWorkbook对象(excel的文档对象)
XSSFWorkbook wb = new XSSFWorkbook();
XSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
// 建立新的sheet对象(excel的表单)
for (Map.Entry<String, List<T>> entry : datasMap.entrySet()) {
String sheetName = entry.getKey();
List<T> datas = entry.getValue();
XSSFSheet sheet = wb.createSheet(sheetName);
for (int j = 0; j < datas.size(); j++) {
Map map = objectToMap(datas.get(j));
// 在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
XSSFRow row0 = sheet.createRow(0);
for (int i = 0; i < names.length; i++) {
row0.createCell(i).setCellValue(names[i]);
}
XSSFRow row = sheet.createRow(j + 1);
for (int i = 0; i < fields.length; i++) {
Object oldValue = map.get(fields[i]);
String cellValue = null;
if (oldValue != null && oldValue instanceof Date) {
cellValue = format((Date) oldValue, "yyyy-MM-dd HH:mm:ss");
} else {
cellValue = nullToEmpty(oldValue);
}
//避免 The maximum length of cell contents (text) is 32767 characters异常
if (cellValue.length() > 32767) {
cellValue = cellValue.substring(0, 32767);
}
row.createCell(i).setCellValue(cellValue);
}
System.out.println(j + " to cell");
}
}
//输出Excel文件1
FileOutputStream output = null;
try {
if (overwirte) {
new File(filePath).delete();
}
output = new FileOutputStream(filePath);
wb.write(output);//写入磁盘
flag = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("data save to path===" + filePath);
return flag;
}
/**
* 数据输出
* @param datas 数据
* @param fields 输出字段
* @param names 输出字段对应的名称
* @param filePath 数据文件
* @param overwirte 是否覆盖
* @param <T>
* @return
*/
public static <T> boolean multCommonDataToExcel(List<T> datas, Object[] fields, String[] names, String filePath, boolean overwirte) {
if (!filePath.endsWith(".xlsx") || !filePath.endsWith(".xls")) {
filePath = filePath + ".xlsx";
}
/* File file = new File(filePath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}*/
boolean flag = false;
//创建HSSFWorkbook对象(excel的文档对象)
XSSFWorkbook wb = new XSSFWorkbook();
XSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
// 建立新的sheet对象(excel的表单)
XSSFSheet sheet = wb.createSheet();
for (int j = 0; j < datas.size(); j++) {
Map map = objectToMap(datas.get(j));
// 在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
XSSFRow row0 = sheet.createRow(0);
for (int i = 0; i < names.length; i++) {
row0.createCell(i).setCellValue(names[i]);
}
XSSFRow row = sheet.createRow(j + 1);
for (int i = 0; i < fields.length; i++) {
Object oldValue = map.get(fields[i]);
String cellValue = null;
if (oldValue != null && oldValue instanceof Date) {
cellValue = format((Date) oldValue, "yyyy-MM-dd HH:mm:ss");
} else {
cellValue = nullToEmpty(oldValue);
}
//避免 The maximum length of cell contents (text) is 32767 characters 异常
if (cellValue.length() > 32767) {
cellValue = cellValue.substring(0, 32767);
}
row.createCell(i).setCellValue(cellValue);
}
System.out.println(j + " to cell");
}
//输出Excel文件1
FileOutputStream output = null;
try {
if (overwirte) {
new File(filePath).delete();
}
output = new FileOutputStream(filePath);
wb.write(output);//写入磁盘
flag = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("data size is " + datas.size() + " to path===" + filePath);
return flag;
}
}
csv使用总结
依赖
<dependency> <groupId>net.sourceforge.javacsv</groupId> <artifactId>javacsv</artifactId> <version>2.0</version> </dependency>
代码总结
import com.csvreader.CsvReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CsvUtil {
//读取csv文件
public static List<String[]> readCsv(String filePath) throws Exception {
List<String[]> csvList = new ArrayList<String[]>();
if (isCsv(filePath)) {
CsvReader reader = new CsvReader(filePath, ',', Charset.forName("gbk"));
reader.readHeaders(); // 跳过表头 如果需要表头的话,不要写这句。
while (reader.readRecord()) { //逐行读入除表头的数据
csvList.add(reader.getValues());
}
reader.close();
} else {
System.out.println("此文件不是CSV文件!");
}
return csvList;
}
/**
* 更易读,但是有个弊端 列数最大到 Z
* @param filePath
* @return
* @throws Exception
*/
public static List<Map<Character,Object>> read2charMap(String filePath) throws Exception {
List<Map<Character,Object>> csvList = new ArrayList<Map<Character,Object>>();
if (isCsv(filePath)) {
CsvReader reader = new CsvReader(filePath, ',', Charset.forName("gbk"));
reader.readHeaders(); // 跳过表头 如果需要表头的话,不要写这句。
while (reader.readRecord()) { //逐行读入除表头的数据
String[] datas = reader.getValues();
Map<Character,Object> map=new HashMap<>();
for (int i = 0; i < datas.length; i++) {
char code = getcode(i+1);
map.put(code,datas[i]);
}
csvList.add(map);
}
reader.close();
} else {
System.out.println("此文件不是CSV文件!");
}
return csvList;
}
/**
* 读取列所在游标作为key的map
* @param filePath
* @return
* @throws Exception
*/
public static List<Map<Integer,Object>> read2indexMap(String filePath) throws Exception {
List<Map<Integer,Object>> csvList = new ArrayList<Map<Integer,Object>>();
if (isCsv(filePath)) {
CsvReader reader = new CsvReader(filePath, ',', Charset.forName("gbk"));
reader.readHeaders(); // 跳过表头 如果需要表头的话,不要写这句。
while (reader.readRecord()) { //逐行读入除表头的数据
String[] datas = reader.getValues();
Map<Integer,Object> map=new HashMap<>();
for (int i = 0; i < datas.length; i++) {
map.put(i,datas[i]);
}
csvList.add(map);
}
reader.close();
} else {
System.out.println("此文件不是CSV文件!");
}
return csvList;
}
//判断是否是csv文件
private static boolean isCsv(String fileName) {
return fileName.matches("^.+\\.(?i)(csv)$");
}
//方法测试
public static void main(String[] args) throws Exception {
String filepath = "C:\\Users\\76204\\Documents\\WXWork\\1688850802899381\\Cache\\File\\2022-05\\出入境项目(1)\\出入境项目\\tw\\tw_article.csv";
CsvUtil su = new CsvUtil();
List<String[]> list = su.readCsv(filepath);
for (int r = 0; r < list.size(); r++) {
for (int c = 0; c < list.get(r).length; c++) {
String cell = list.get(r)[c];
System.out.print(cell + "\t");
}
System.out.print("\n");
}
}
public static char getcode(int i){
return (char) (i+64);
}
}
easyexcel总结
依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.32</version> </dependency>
读取
PageReadListener
@Test
public void pageReadTest(){
// 写法1:JDK8+ ,不用额外写一个DemoDataListener
// since: 3.0.0-beta1
String fileName = "./xls/demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
// 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
EasyExcel.read(fileName, DemoData.class, new PageReadListener<DemoData>(dataList -> {
for (DemoData demoData : dataList) {
// log.info("读取到一条数据{}", JSON.toJSONString(demoData));
System.out.println(demoData);
}
})).sheet() //可以选择sheet,默认第一个
.doRead();
}
public class DemoData {
@ExcelProperty("name") //输出的列名
private String string;
@ExcelProperty("birthday")
private Date date;
@ExcelProperty("percent")
private Double doubleData;
//get set 省略
}
自定义DataListener
@Test
public void test(){
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
// 写法3:
String fileName = "./xls/demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet()
//.doReadSync(); //同步的返回,不推荐使用,如果数据量大会把数据放到内存里面
.doRead();
}
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import easy.data.DemoData;
import lombok.extern.slf4j.Slf4j;
/**
* 模板的读取类
*
* @author Jiaju Zhuang
*/
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {
/**
* 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 100;
/**
* 缓存的数据
*/
private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
// private DemoDAO demoDAO;
public DemoDataListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
// demoDAO = new DemoDAO();
}
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param demoDAO
*/
/* public DemoDataListener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}*/
/**
* 这个每一条数据解析都会来调用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
// log.info("解析到一条数据:{}", JSON.toJSONString(data));
cachedDataList.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
// log.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
/* log.info("{}条数据,开始存储数据库!", cachedDataList.size());
demoDAO.save(cachedDataList);
log.info("存储数据库成功!");*/
for (DemoData demoData : cachedDataList) {
System.out.println("save "+demoData);
}
System.out.println("--------------------------------");
}
}
指定下标或者列名读取
public class IndexOrNameData {
/**
* 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
*/
@ExcelProperty(index = 2)
private Double doubleData;
/**
* 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
*/
@ExcelProperty("name")
private String string;
@ExcelProperty("birthday")
private Date date;
//...
}
非正常表头位置
设置headRowNumber
/**
* 针对表头不在第一行的数据
*/
@Test
public void indexOrNameRead2() {
String fileName = "./xls/demo-3.xlsx";
// 这里默认读取第一个sheet
EasyExcel.read(fileName, IndexOrNameData.class, new IndexOrNameDataListener()).headRowNumber(2).sheet().doRead();
}
/**
* 针对没有表头的数据
*/
@Test
public void indexRead2() {
String fileName = "./xls/demo-2.xlsx";
// 这里默认读取第一个sheet
EasyExcel.read(fileName, IndexData.class, new IndexDataListener()).headRowNumber(0).sheet().doRead();
}
不创建对象的读
/**
* 不创建对象的读
*/
@Test
public void noModelRead() throws FileNotFoundException, UnsupportedEncodingException {
String fileName = "./xls/demo.xlsx";
// 这里 只要,然后读取第一个sheet 同步读取会自动finish
FileInputStream inputStream = new FileInputStream(fileName);
EasyExcel.read(inputStream, new NoModelDataListener())
.sheet()
.doRead();
}
csv读取
/**
* csv读取
*/
@Test
public void csvRead() throws FileNotFoundException, UnsupportedEncodingException {
String fileName="C:\\Users\\76204\\Documents\\WXWork\\1688850802899381\\Cache\\File\\2022-05\\出入境项目(1)\\出入境项目 - 副本\\tw\\tw_article.csv";
FileInputStream inputStream = new FileInputStream(fileName);
EasyExcel.read(inputStream, new NoModelDataListener())
.excelType(ExcelTypeEnum.CSV) //用流读取时候需要设置格式
.charset(Charset.forName("gbk")) //设置编码
.sheet()
.doRead();
}
写入
数据量不大的情况下写入
@Test
public void test1(){
// 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
// 写法1 JDK8+
// since: 3.0.0-beta1
String fileName = "./xls/demo_write.xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, DemoData.class)
.sheet("模板")
.doWrite(() -> {
// 分页查询数据
return data();
});
}
private List<DemoData> data() {
List<DemoData> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
数据量大的情况下写入
/**
* 重复多次写入
* <p>
* 1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
* <p>
* 2. 使用{@link ExcelProperty}注解指定复杂的头
* <p>
* 3. 直接调用二次写入即可
*/
@Test
public void repeatedWrite() {
// 方法1.1: 如果写到同一个sheet 使用 try-with-resources @since 3.1.0
String fileName = "./xls/demo_write9.xlsx";
// 这里 需要指定写用哪个class去写
try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
// 这里注意 如果同一个sheet只要创建一次
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
for (int i = 0; i < 5; i++) {
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
}
}
多sheet输出
/**
* 多sheet输出
*/
@Test
public void test3(){
// 写法3:使用 try-with-resources @since 3.1.0
String fileName = "./xls/demo_write3.xlsx";
// 这里 需要指定写用哪个class去写
try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class)
.build()) {
WriteSheet writeSheet = EasyExcel.writerSheet("模板1").build();
excelWriter.write(data(), writeSheet);
WriteSheet writeSheet2 = EasyExcel.writerSheet("模板2").build();
excelWriter.write(data(), writeSheet2);
}
}
排除自己需要的列
/**
* 根据参数只导出指定列
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 根据自己或者排除自己需要的列
* <p>
* 3. 直接写即可
*
* @since 2.1.1
*/
@Test
public void excludeOrIncludeWrite() {
String fileName = "./xls/demo_write5.xlsx";
// 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。
// 根据用户传入字段 假设我们要忽略 date
Set<String> excludeColumnFieldNames = new HashSet<>();
excludeColumnFieldNames.add("date");
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).excludeColumnFieldNames(excludeColumnFieldNames).sheet("模板")
.doWrite(data());
}
只加入自己需要的列
@Test
public void test6(){
String fileName = "./xls/demo_write6.xlsx";
// 根据用户传入字段 假设我们只要导出 date
Set<String> includeColumnFieldNames = new HashSet<>();
includeColumnFieldNames.add("date");
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).includeColumnFieldNames(includeColumnFieldNames).sheet("模板")
.doWrite(data());
}
指定写入的列
public class IndexData {
/**
* 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
*/
@ExcelProperty(index = 2)
private Double doubleData;
/**
* 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
*/
@ExcelProperty(index = 0)
private String string;
@ExcelProperty(index = 1)
private Date date;
//...
}
复杂头写入
public class ComplexHeadData {
@ExcelProperty({"主标题", "字符串标题"})
private String string;
@ExcelProperty({"主标题", "日期标题"})
private Date date;
@ExcelProperty({"主标题", "数字标题"})
private Double doubleData;
//...
}
自定义格式转换
/**
* 日期、数字或者自定义格式转换
* <p>
* 1. 创建excel对应的实体对象 参照{@link ConverterData}
* <p>
* 2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解
* <p>
* 3. 直接写即可
*/
@Test
public void converterWrite() {
String fileName = "./xls/demo_write11.xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());
}
public class ConverterData {
/**
* 我想所有的 字符串起前面加上"自定义:"三个字
*/
@ExcelProperty(value = "字符串标题")
private String string;
/**
* 我想写到excel 用年月日的格式
*/
@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
@ExcelProperty("日期标题")
private Date date;
/**
* 我想写到excel 用百分比表示
*/
@NumberFormat("#.##%")
@ExcelProperty(value = "数字标题")
private Double doubleData;
}
指定单元格宽高
@ContentRowHeight(20)
@HeadRowHeight(20)
@ColumnWidth(25)
public class WidthAndHeightData {
@ExcelProperty("字符串标题")
private String string;
@ColumnWidth(50)
@ExcelProperty("日期标题")
private Date date;
/**
* 宽度为50
*/
@ColumnWidth(20)
@ExcelProperty("数字标题")
private Double doubleData;
}
合并单元格
public class DemoMergeData {
// 这一列 每隔2行 合并单元格
@ContentLoopMerge(eachRow = 2)
@ExcelProperty("字符串标题")
private String string;
@ColumnWidth(25)
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
}
不创建对象写
/**
* 不创建对象的写
*/
@Test
public void noModelWrite() {
// 写法1
String fileName = "./xls/demo_write15.xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName)
.head(head()) //自定义表头
.sheet("模板")
.doWrite(dataList());
}
private List<List<String>> head() {
List<List<String>> list = ListUtils.newArrayList();
List<String> head0 = ListUtils.newArrayList();
head0.add("字符串" + System.currentTimeMillis());
List<String> head1 = ListUtils.newArrayList();
head1.add("数字" + System.currentTimeMillis());
List<String> head2 = ListUtils.newArrayList();
head2.add("日期" + System.currentTimeMillis());
list.add(head0);
list.add(head1);
list.add(head2);
return list;
}
private List<List<Object>> dataList() {
List<List<Object>> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) {
List<Object> data = ListUtils.newArrayList();
data.add("字符串" + i);
data.add(new Date());
data.add(0.56);
list.add(data);
}
return list;
}
填充
/**
* 最简单的填充
*
* @since 2.1.1
*/
@Test
public void simpleFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
String templateFileName = "./xls/simple.xlsx";
// 方案1 根据对象填充
String fileName = "./xls/demo_write16.xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);
}
来源