poi和EasyExcel表格处理总结

程序中很多时候会出现表格的读写操作,这里做一个总结,方便后续查找

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);

    }

来源

EasyExcel · 语雀 

https://www.jb51.net/article/212115.htm 

java操作csv文件(读、写)_鲁肃小生的博客-CSDN博客_csv java 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值