java:excel文件读写三、poi读、写xls和xlsx

java:excel文件读写三、poi读、写xls和xlsx

1 依赖配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.4</version>
</parent>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
	<!--  xls  -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.1</version>
    </dependency>

	<!--  xlsx  -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.1</version>
    </dependency>

</dependencies>

2 使用

读取excel数据,去除空的列数据,并写入到其他excel文件中:

package com.xiaoxu.utils;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.swing.filechooser.FileSystemView;
import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author xiaoxu
 * @date 2022-03-13 13:26
 * spring_boot:com.xiaoxu.utils.ExcelUtil
 */
public class ExcelUtil {
    private static final String xlsSeparator = ".xls";
    private static final String xlsxSeparator = ".xlsx";
    private static final String separator = "\\";

    public static void createExcel(@NonNull String fileName){
        /*
         *fileName 文件名
         * */
        File deskUrl = FileSystemView.getFileSystemView().getHomeDirectory();
        List<String> splitArr = ExcelUtil.splitFileName(fileName);

        if(splitArr.size()==1){
            fileName = deskUrl+ separator + splitArr.get(0) +xlsSeparator;
        }else if(splitArr.size()==2){
            if(!(xlsxSeparator.equals(splitArr.get(1))||xlsSeparator.equals(splitArr.get(1)))){
                throw new RuntimeException("文件名后缀必须为.xls或者.xlsx");
            }
            StringBuilder sb = new StringBuilder();
            sb.append(deskUrl).append(separator);
            for (String s : splitArr) {
                sb.append(s);
            }
            fileName = sb.toString();
        }else{
            throw new RuntimeException("文件名不正确");
        }

        //例以前为:HSSFWorkbook和XSSFWorkbook
        Workbook wb;

        //创建xls(HSSF)和xlsx(XSSF)文件
        if(fileName.endsWith(".xls")){
            wb=new HSSFWorkbook();
        }else if(fileName.endsWith(".xlsx")){
            wb=new XSSFWorkbook();
        }else{
            throw new RuntimeException("文件后缀必须是xls或xlsx");
        }

        CreationHelper creationHelper = wb.getCreationHelper();
        //例以前为:HSSFSheet和XSSFSheet
        Sheet s = wb.createSheet("我是sheet1");
        //例以前为:HSSFRow和XSSFRow
        Row r;
        //例以前为:HSSFCell和XSSFCell
        Cell cell1;
        Cell cell2;

        //样式创建,以前为:HSSFCellStyle和XSSFCellStyle,以此类推
        CellStyle c1 = wb.createCellStyle();
        CellStyle c2 = wb.createCellStyle();
        DataFormat df = wb.createDataFormat();

        Font f1 =wb.createFont();
        Font f2 =wb.createFont();

        f1.setFontHeightInPoints((short) 14);
        f1.setColor(IndexedColors.SEA_GREEN.getIndex());
        f1.setBold(true);

        f2.setFontHeightInPoints((short) 10);
        f2.setColor(IndexedColors.DARK_RED.getIndex());
        f2.setBold(false);

        c1.setFont(f1);
        c1.setDataFormat(df.getFormat("#,##0.0"));

        c2.setFont(f2);
        c2.setDataFormat(df.getFormat("text"));
        c2.setBorderBottom(BorderStyle.DASH_DOT);

        for (int i=0;i<3;i++){
            r = s.createRow(i);
            for(int j=0;j<10;j+=2){
                cell1 = r.createCell(j);
                cell2 = r.createCell(j+1);
                cell1.setCellStyle(c1);
                cell2.setCellStyle(c2);

                cell1.setCellValue(i+((double)j/10));
                cell2.setCellValue(
                        creationHelper.createRichTextString("你好,"+j)
                );
            }
        }

        if(wb instanceof HSSFWorkbook){
            System.out.println("我是xls文件~");
        }else{
            System.out.println("我是xlsx文件~");
        }

        FileOutputStream fileOutputStream;
        try {
            fileOutputStream = new FileOutputStream(fileName);
            wb.write(fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
            wb.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException("文件路径未找到或进程无法访问:"+e.getMessage());
        }catch (IOException i){
            throw new RuntimeException("文件写入出错:"+i.getMessage());
        }
    }

    public static void checkExcelFileSuffix(@NonNull String fileName){
        if(!(fileName.endsWith(xlsSeparator)||fileName.endsWith(xlsxSeparator))){
            throw new IllegalArgumentException("文件后缀必须是xls或xlsx");
        }
    }

    /**
     * @param fileName
     * @param sheetIndex
     * @param newFileName
     */
    // 快捷方法参数:点击方法名,alt+enter:add javadoc
    @SuppressWarnings("rawtypes")
    public static void readAndWriteToExcel(@NonNull String fileName,int sheetIndex,@NonNull String newFileName){
        checkExcelFileSuffix(newFileName);
        Map<String,List> dataMap = readExcel(fileName,sheetIndex);
        System.out.println("parse map's data:"+dataMap);
        String excelFileName = getExcelFileName(newFileName);
        Workbook wb;
        //创建xls(HSSF)和xlsx(XSSF)文件
        if(excelFileName.endsWith(".xls")){
            wb=new HSSFWorkbook();
        }else if(excelFileName.endsWith(".xlsx")){
            wb=new XSSFWorkbook();
        }else{
            throw new RuntimeException("文件后缀必须是xls或xlsx");
        }
        CreationHelper creationHelper = wb.getCreationHelper();
        Sheet s = wb.createSheet("第一个sheet");
        List<Integer> len = new ArrayList<>();
        if(!CollectionUtils.isEmpty(dataMap)){
            dataMap.forEach((key,value) ->{
                len.add(value.size());
            });
            int maxRow = Collections.max(len);
            AtomicInteger ato = new AtomicInteger(0);
            for (int i = 0 ;i < maxRow; i++) {
                Row row = s.createRow(i);
                dataMap.forEach((key,value)->{
                    for(int j=0;j<value.size();j++){
                        if(ato.get()==j){
                            //System.out.println("开始设置列英文:"+key+";列索引 :"+CellReference.convertColStringToIndex(key));
                            Cell cell = row.createCell(CellReference.convertColStringToIndex(key));
                            setCellValueByClass(cell,value.get(j),creationHelper);
                        }
                    }
                });
                ato.addAndGet(1);
            }
        }
        FileOutputStream fileOutputStream;
        try {
            fileOutputStream = new FileOutputStream(excelFileName);
            wb.write(fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
            wb.close();
        } catch (IOException e) {
            throw new RuntimeException("文件写入出错:"+e.getMessage());
        }
    }

    public static void setCellValueByClass(Cell cell,Object obj,CreationHelper creationHelper){
        if(obj instanceof String){
            cell.setCellValue(creationHelper.createRichTextString((String) obj));
        }else if(obj instanceof Double){
            cell.setCellValue((double) obj);
        }else if(obj instanceof Boolean){
            cell.setCellValue((boolean) obj);
        }else if (obj instanceof Date){
            cell.setCellValue((Date) obj);
        }else {
            throw new RuntimeException("暂时只支持String、double、boolean、Date类型excel数据转换");
        }
    }

    public static List<String> splitFileName(String fileName){
        String suffix = null;
        String file;
        List<String> files = new ArrayList<>();
        int i;
        if(fileName!=null){
            i = fileName.lastIndexOf(".");
            if(i!=-1){
                file = fileName.substring(0,i);
                suffix = fileName.substring(i);
            }else{
                file = fileName;
            }
        }else{
            throw new NullPointerException("文件名不能为null");
        }
        files.add(file);
        files.add(suffix);
        return files.stream().filter(Objects::nonNull).collect(Collectors.toList());
    }


    /**
     * @param fileName 读取文件的名称
     * @param sheetIndex  sheet索引,0开始
     * @return 返回的map的key是A、B、D...
     */
    @SuppressWarnings(value = {"rawtypes"})
    public static Map<String,List> readExcel(@NonNull String fileName,int sheetIndex){
        String excelFileName = ExcelUtil.getExcelFileName(fileName);
        Map<String,List> dataMap = new HashMap<>();
        // Use an InputStream, needs more memory
        // new File(excelFileName)
        try(InputStream inputStream = new FileInputStream(excelFileName)){
            Workbook sheets = WorkbookFactory.create(inputStream);
            Sheet sheetAt;
            try {
                sheetAt = sheets.getSheetAt(sheetIndex);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                return new HashMap<>();
            }
            //DataFormatter dataFormatter = new DataFormatter();
            if(sheetAt!=null){
                for (Row cells : sheetAt) {
                    for (Cell cell : cells) {
                        CellReference cellReference = new CellReference(cells.getRowNum(), cell.getColumnIndex());
                        String colString = CellReference.convertNumToColString(cellReference.getCol());
                        //第一列代表A;第二列代表B;以次类推...
                        //System.out.println("行:"+cellReference.getRow()+"; 列:"+colString);
                        Object cellObj = getCellValue(cell);
                        //System.out.println("值:"+cellObj);
                        save(dataMap,colString,cellObj);
                    }
                }
            }
        } catch (IOException f){
            f.printStackTrace();
        }
        return dataMap;
    }
    
    /*
    * 针对单个key和value存入
    * 且不使用map.get():因为可能存在value为null的情况
    * */
    @SuppressWarnings(value = {"rawtypes","unchecked"})
    public static void save(Map<String,List> saveMap,String key,Object value){
        /*把读取的map中的value为null或者""的字符串去掉*/
        if(value instanceof String && !StringUtils.hasLength((String)value)){
            return;
        }
        if(!saveMap.containsKey(key)){
            List valList = new ArrayList();
            valList.add(value);
            saveMap.put(key,valList);
        }else{
            saveMap.get(key).add(value);
        }
    }
    
    /*
    * 存入map,不做去重操作
    * */
    @SuppressWarnings(value = {"rawtypes","unchecked"})
    public static void storeInMap(Map<String,List> emptyMap,Map<String,List> dataMap){
        for(Map.Entry<String,List> entry:dataMap.entrySet()){
            String key = entry.getKey();
            List value = entry.getValue();
            if(!emptyMap.containsKey(key)){
                emptyMap.put(key,value);
            }else{
                emptyMap.get(key).addAll(value);
            }
        }
    }


    /**
     * @param c cell对象
     * @return cell的content
     */
    //获取cell的值
    public static Object getCellValue(Cell c){
        switch(c.getCellType()){
            case NUMERIC:
                if(DateUtil.isCellDateFormatted(c)){
                    return c.getDateCellValue();
                }else{
                    return c.getNumericCellValue();
                }
            case STRING:
                return c.getRichStringCellValue().getString();
            /*公式*/
            case FORMULA:
                return c.getCellFormula();
            case BOOLEAN:
                return c.getBooleanCellValue();
            /*如果为blank类型,数据会是null,处理为空字符串*/
            case BLANK:
                return "";
            case _NONE:
            case ERROR:
            default:
                break;
        }
        return null;
    }

    public static String getExcelFileName(@NonNull String fileName){
        File deskUrl = FileSystemView.getFileSystemView().getHomeDirectory();
        List<String> splitArr = ExcelUtil.splitFileName(fileName);

        if(splitArr.size()==1){
            fileName = deskUrl+ separator + splitArr.get(0) +xlsSeparator;
        }else if(splitArr.size()==2){
            if(!(xlsxSeparator.equals(splitArr.get(1))||xlsSeparator.equals(splitArr.get(1)))){
                throw new RuntimeException("文件名后缀必须为.xls或者.xlsx");
            }
            StringBuilder sb = new StringBuilder();
            sb.append(deskUrl).append(separator);
            for (String s : splitArr) {
                sb.append(s);
            }
            fileName = sb.toString();
        }else{
            throw new RuntimeException("文件名不正确");
        }
        return fileName;
    }

    public static void main(String[] args) {
//        ExcelUtil.createExcel("test.xlsx");
//        ExcelUtil.readExcel("test123.xlsx", 0);
        ExcelUtil.readAndWriteToExcel("test123.xlsx",0,"new.xlsx");
//        ExcelUtil.readAndWriteToExcel("test456.xlsx",0,"new2.xlsx");
    }
}

2.1 情形1

test123.xlsx:
在这里插入图片描述
执行结果如下:

13:59:13.773 [main] DEBUG org.apache.poi.openxml4j.opc.PackageRelationshipCollection - Parsing relationship: /xl/_rels/workbook.xml.rels
13:59:13.800 [main] DEBUG org.apache.poi.openxml4j.opc.PackageRelationshipCollection - Parsing relationship: /xl/worksheets/_rels/sheet1.xml.rels
13:59:13.833 [main] DEBUG org.apache.poi.openxml4j.opc.PackageRelationshipCollection - Parsing relationship: /_rels/.rels
13:59:14.427 [main] DEBUG org.apache.poi.ooxml.POIXMLFactory - using default POIXMLDocumentPart for http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings
parse map's data:{A=[3.1232321E7], B=[2.13213421421421E24], C=[你好, 345.0], D=[hai, 中国来啦], E=[true], F=[Tue Apr 05 00:00:00 CST 2022], G=[哈哈], H=[1.0]}
13:59:14.870 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save core properties part
13:59:14.871 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save content types part
13:59:14.896 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save package relationships
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/app.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/core.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/sharedStrings.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/styles.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/workbook.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/worksheets/sheet1.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save content types part
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save package relationships
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/app.xml'
13:59:14.913 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/core.xml'
13:59:14.930 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/sharedStrings.xml'
13:59:14.931 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/styles.xml'
13:59:14.931 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/workbook.xml'
13:59:14.932 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/worksheets/sheet1.xml'

new.xlsx:
在这里插入图片描述
2.2 情形2
在这里插入图片描述
test456.xlsx:
在这里插入图片描述
执行结果如下:

14:03:27.883 [main] DEBUG org.apache.poi.openxml4j.opc.PackageRelationshipCollection - Parsing relationship: /xl/_rels/workbook.xml.rels
14:03:27.930 [main] DEBUG org.apache.poi.openxml4j.opc.PackageRelationshipCollection - Parsing relationship: /_rels/.rels
parse map's data:{A=[3.1232321E7], C=[你好, 345.0], D=[hai, 中国来啦], E=[true], F=[Tue Apr 05 00:00:00 CST 2022], G=[哈哈], H=[1.0], J=[2.0]}
14:03:28.688 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save core properties part
14:03:28.688 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save content types part
14:03:28.750 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save package relationships
14:03:28.750 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/app.xml'
14:03:28.750 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/core.xml'
14:03:28.766 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/sharedStrings.xml'
14:03:28.766 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/styles.xml'
14:03:28.766 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/workbook.xml'
14:03:28.766 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/worksheets/sheet1.xml'
14:03:28.782 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save content types part
14:03:28.782 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save package relationships
14:03:28.797 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/app.xml'
14:03:28.797 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'docProps/core.xml'
14:03:28.797 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/sharedStrings.xml'
14:03:28.797 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/styles.xml'
14:03:28.797 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/workbook.xml'
14:03:28.797 [main] DEBUG org.apache.poi.openxml4j.opc.ZipPackage - Save part 'xl/worksheets/sheet1.xml'

new2.xlsx:
在这里插入图片描述
2.3 情形3

如果需要对数据进行格式化写入,如日期,修改如下:

public static void setCellValueByClass(Cell cell,Object obj,CreationHelper creationHelper,Workbook wb){
    if(obj instanceof String){
        cell.setCellValue(creationHelper.createRichTextString((String) obj));
    }else if(obj instanceof Double){
        cell.setCellValue((double) obj);
    }else if(obj instanceof Boolean){
        cell.setCellValue((boolean) obj);
    }else if (obj instanceof Date){
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setDataFormat(
                creationHelper.createDataFormat().getFormat("yyyy-mm-dd hh:mm:ss")
        );
        cell.setCellValue((Date) obj);
        cell.setCellStyle(cellStyle);
    }else {
        throw new RuntimeException("暂时只支持String、double、boolean、Date类型excel数据转换");
    }
}
/**
 * @param fileName
 * @param sheetIndex
 * @param newFileName
 */
// 快捷方法参数:点击方法名,alt+enter:add javadoc
@SuppressWarnings("rawtypes")
public static void readAndWriteToExcel(@NonNull String fileName,int sheetIndex,@NonNull String newFileName){
    checkExcelFileSuffix(newFileName);
    Map<String,List> dataMap = readExcel(fileName,sheetIndex);
    System.out.println("parse map's data:"+dataMap);
    String excelFileName = getExcelFileName(newFileName);
    Workbook wb;
    //创建xls(HSSF)和xlsx(XSSF)文件
    if(excelFileName.endsWith(".xls")){
        wb=new HSSFWorkbook();
    }else if(excelFileName.endsWith(".xlsx")){
        wb=new XSSFWorkbook();
    }else{
        throw new RuntimeException("文件后缀必须是xls或xlsx");
    }
    CreationHelper creationHelper = wb.getCreationHelper();
    Sheet s = wb.createSheet("第一个sheet");
    List<Integer> len = new ArrayList<>();
    if(!CollectionUtils.isEmpty(dataMap)){
        dataMap.forEach((key,value) ->{
            len.add(value.size());
        });
        int maxRow = Collections.max(len);
        AtomicInteger ato = new AtomicInteger(0);
        for (int i = 0 ;i < maxRow; i++) {
            Row row = s.createRow(i);
            dataMap.forEach((key,value)->{
                for(int j=0;j<value.size();j++){
                    if(ato.get()==j){
                        //System.out.println("开始设置列英文:"+key+";列索引 :"+CellReference.convertColStringToIndex(key));
                        Cell cell = row.createCell(CellReference.convertColStringToIndex(key));
                        setCellValueByClass(cell,value.get(j),creationHelper,wb);
                    }
                }
            });
            ato.addAndGet(1);
        }
    }
    FileOutputStream fileOutputStream;
    try {
        fileOutputStream = new FileOutputStream(excelFileName);
        wb.write(fileOutputStream);
        fileOutputStream.flush();
        fileOutputStream.close();
        wb.close();
    } catch (IOException e) {
        throw new RuntimeException("文件写入出错:"+e.getMessage());
    }
}

重新执行效果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值