java怎么操作excel?java操作excel的几种方式

excel是我们工作最常见的应用,不管是对于文档打印还是操作都很方便,并且在开发java中,也可以对excel进行操作,那java怎么操作excel?下面来我们就来给大家讲解一下java操作excel的几种方式。

Java操作Excel三种方式POI、Hutool、EasyExcel。

1.ApachePOI

Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。

ApachePOI功能结构:

HSSF [1] - 提供读写Microsoft Excel XLS格式档案的功能。
XSSF [1] - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
HWPF [1] - 提供读写Microsoft Word DOC格式档案的功能。
HSLF [1] - 提供读写Microsoft PowerPoint格式档案的功能。
HDGF [1] - 提供读Microsoft Visio格式档案的功能。
HPBF [1] - 提供读Microsoft Publisher格式档案的功能。
HSMF [1] - 提供读Microsoft Outlook格式档案的功能。

2.Hutool简介

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;

Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。

3.EasyExcel简介

EasyExcel是阿里巴巴开源的一款Excel操作工具,简单易用,功能强大,节省内存,性能彪悍。

HutoolExcel实现验证

Mave依赖配置

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.0.5</version>
        </dependency>

EasyExcel批量添加批注

ByteToInputStreamUtil

package com.zrj.easyexcel.excel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
/**
 * 输入流与字节转换
 *
 * @author zrj
 * @since 2021/12/27
 **/
public class ByteToInputStreamUtil
{
    /**
     * 字节转输入流
     *
     * @param buf
     * @return java.io.InputStream
     */
    public static InputStream byte2Input(byte[] buf)
    {
        return new ByteArrayInputStream(buf);
    }
    /**
     * 输入流转字节
     *
     * @param inStream
     * @return byte[]
     */
    public static byte[] input2byte(InputStream inStream) throws Exception
    {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0)
        {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }
}

CommentWriteHandler

package com.zrj.easyexcel.excel;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.write.handler.AbstractRowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * 批注处理器
 *
 * @author zrj
 * @since 2021/12/29
 **/
public class CommentWriteHandler extends AbstractRowWriteHandler
{
    /**
     * sheet名称KEY
     */
    public static final String SHEETNAME_NAME = "sheetName";
    /**
     * 文档后缀名
     */
    private String extension;
    /**
     * 列索引key
     */
    public static final String COLINDEX_NAME = "colIndex";
    /**
     * 行索引key
     */
    public static final String ROWINDEX_NAME = "rowIndex";
    /**
     * 批注内容key
     */
    public static final String COMMENTCONTENT_NAME = "commentContent";
    /**
     * sheet页名称列表
     */
    private List < String > sheetNameList;
    /**
     * 批注集合
     */
    List < Map < String, String >> commentList = new ArrayList < > (10);
    /**
     * CommentWriteHandler
     *
     * @param commentList
     * @param extension
     */
    public CommentWriteHandler(List < Map < String, String >> commentList, String extension)
    {
        this.commentList = commentList != null && commentList.size() > 0 ?
            commentList.stream()
            .filter(x - >
                x.keySet()
                .contains(SHEETNAME_NAME) == true && x.get(SHEETNAME_NAME) != null && StrUtil.isNotBlank(x.get(SHEETNAME_NAME)
                    .toString()) &&
                x.keySet()
                .contains(COLINDEX_NAME) == true && x.get(COLINDEX_NAME) != null && StrUtil.isNotBlank(x.get(COLINDEX_NAME)
                    .toString()) &&
                x.keySet()
                .contains(ROWINDEX_NAME) == true && x.get(ROWINDEX_NAME) != null && StrUtil.isNotBlank(x.get(ROWINDEX_NAME)
                    .toString()) &&
                x.keySet()
                .contains(COMMENTCONTENT_NAME) == true && x.get(COMMENTCONTENT_NAME) != null && StrUtil.isNotBlank(x.get(COMMENTCONTENT_NAME)
                    .toString())
            )
            .collect(Collectors.toList()) : new ArrayList < > ();
        sheetNameList = this.commentList.stream()
            .map(x - > x.get(SHEETNAME_NAME)
                .toString())
            .collect(Collectors.toList());
        this.extension = extension;
    }
    /**
     * 生成批注信息
     *
     * @param sheetName      sheet页名称
     * @param rowIndex       行号
     * @param columnIndex    列号
     * @param commentContent 批注内容
     * @return
     */
    public static Map < String, String > createCommentMap(String sheetName, int rowIndex, int columnIndex, String commentContent)
    {
        Map < String, String > map = new HashMap < > ();
        //sheet页名称
        map.put(SHEETNAME_NAME, sheetName);
        //行号
        map.put(ROWINDEX_NAME, rowIndex + "");
        //列号
        map.put(COLINDEX_NAME, columnIndex + "");
        //批注内容
        map.put(COMMENTCONTENT_NAME, commentContent);
        return map;
    }
    /**
     * 功能描述
     * @param writeSheetHolder
     * @param writeTableHolder
     * @param row
     * @param relativeRowIndex
     * @param isHead
     * @return void
     */
    @Override
    public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row
        , Integer relativeRowIndex, Boolean isHead)
    {
        Sheet sheet = writeSheetHolder.getSheet();
        //不需要添加批注,或者当前sheet页不需要添加批注
        if (commentList == null || commentList.size() <= 0 || sheetNameList.contains(sheet.getSheetName()) == false)
        {
            return;
        }
        //获取当前行的批注信息
        List < Map < String, String >> rowCommentList = commentList.stream()
            .filter(x - >
                StrUtil.equals(x.get(SHEETNAME_NAME)
                    .toString(), sheet.getSheetName()) &&
                relativeRowIndex == Integer.parseInt(x.get(ROWINDEX_NAME)))
            .collect(Collectors.toList());
        //当前行没有批注信息
        if (rowCommentList == null || rowCommentList.size() <= 0)
        {
            return;
        }
        List < String > colIndexList = rowCommentList.stream()
            .map(x - > x.get(COLINDEX_NAME))
            .distinct()
            .collect(Collectors.toList());
        for (String colIndex: colIndexList)
        {
            //同一单元格的批注信息
            List < Map < String, String >> cellCommentList = rowCommentList.stream()
                .filter(x - >
                    StrUtil.equals(colIndex, x.get(COLINDEX_NAME)))
                .collect(Collectors.toList());
            if (CollectionUtil.isEmpty(cellCommentList))
            {
                continue;
            }
            //批注内容拼成一条
            String commentContent = cellCommentList.stream()
                .map(x - > x.get(COMMENTCONTENT_NAME))
                .collect(Collectors.joining());
            Cell cell = row.getCell(Integer.parseInt(colIndex));
            addComment(cell, commentContent, extension);
        }
        //删除批注信息
        commentList.remove(rowCommentList);
        //重新获取要添加的sheet页姓名
        sheetNameList = commentList.stream()
            .map(x - > x.get(SHEETNAME_NAME)
                .toString())
            .collect(Collectors.toList());
    }
    /**
     * 给Cell添加批注
     *
     * @param cell      单元格
     * @param value     批注内容
     * @param extension 扩展名
     */
    public static void addComment(Cell cell, String value, String extension)
    {
        Sheet sheet = cell.getSheet();
        cell.removeCellComment();
        if ("xls".equals(extension))
        {
            ClientAnchor anchor = new HSSFClientAnchor();
            // 关键修改
            anchor.setDx1(0);
            anchor.setDx2(0);
            anchor.setDy1(0);
            anchor.setDy2(0);
            anchor.setCol1(cell.getColumnIndex());
            anchor.setRow1(cell.getRowIndex());
            anchor.setCol2(cell.getColumnIndex() + 5);
            anchor.setRow2(cell.getRowIndex() + 6);
            // 结束
            Drawing drawing = sheet.createDrawingPatriarch();
            Comment comment = drawing.createCellComment(anchor);
            // 输入批注信息
            comment.setString(new HSSFRichTextString(value));
            // 将批注添加到单元格对象中
            cell.setCellComment(comment);
        }
        else if ("xlsx".equals(extension))
        {
            ClientAnchor anchor = new XSSFClientAnchor();
            // 关键修改
            anchor.setDx1(0);
            anchor.setDx2(0);
            anchor.setDy1(0);
            anchor.setDy2(0);
            anchor.setCol1(cell.getColumnIndex());
            anchor.setRow1(cell.getRowIndex());
            anchor.setCol2(cell.getColumnIndex() + 5);
            anchor.setRow2(cell.getRowIndex() + 6);
            // 结束
            Drawing drawing = sheet.createDrawingPatriarch();
            Comment comment = drawing.createCellComment(anchor);
            // 输入批注信息
            comment.setString(new XSSFRichTextString(value));
            // 将批注添加到单元格对象中
            cell.setCellComment(comment);
        }
    }
}

EasyExcelUtils

package com.zrj.easyexcel.excel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.zrj.easyexcel.entity.DemoData;
import com.zrj.easyexcel.excel.read.ReadTest;
import com.zrj.easyexcel.excel.write.WriteTest;
import org.junit.Test;
import java.io.File;
import java.util.*;
/**
 * EasyExcel测试类
 *
 * @author zrj
 * @since 2021/12/29
 **/
public class EasyExcelUtils
{
    /**
     * EasyExcel读写测试类
     */
    @Test
    public void easyExcelReadWriteTest()
    {
        //EasyExcel读测试类
        ReadTest readTest = new ReadTest();
        //EasyExcel写测试类
        WriteTest writeTest = new WriteTest();
    }
    /**
     * EasyExcel 批量添加批注
     */
    @Test
    public void batchAddCommentTest()
    {
        try
        {
            //构建数据
            List < DemoData > demoDataList = new ArrayList < > (10);
            demoDataList.add(DemoData.builder()
                .string("张三")
                .date(new Date())
                .doubleData(3.14)
                .build());
            demoDataList.add(DemoData.builder()
                .string("王五")
                .date(new Date())
                .doubleData(6.68)
                .build());
            demoDataList.add(DemoData.builder()
                .string("赵六")
                .date(new Date())
                .doubleData(8.32)
                .build());
            demoDataList.add(DemoData.builder()
                .string("李四")
                .date(new Date())
                .doubleData(8.66)
                .build());
            //定义文件路径
            String filepath = System.getProperty("user.dir") + File.separator + "excel" + File.separator + "EasyExcelCommentWriteTest3.xlsx";
            String sheetName = "批注模板";
            List < Map < String, String >> commentList = new ArrayList < > ();
            commentList.add(CommentWriteHandler.createCommentMap(sheetName, 0, 1, "第一条批注。"));
            commentList.add(CommentWriteHandler.createCommentMap(sheetName, 1, 1, "第二条批注。"));
            // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
            // 这里要注意inMemory 要设置为true,才能支持批注。目前没有好的办法解决 不在内存处理批注。这个需要自己选择。
            EasyExcel.write(filepath, DemoData.class)
                .inMemory(Boolean.TRUE)
                .registerWriteHandler(new CommentWriteHandler(commentList, "xlsx"))
                .sheet(sheetName)
                .doWrite(demoDataList);
            System.out.println("批注模板完成,模板地址:" + filepath);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Java操作Excel就是POI、Hutool以及EasyExcel这三种方式,我们可以选择任意一种进行操作,感兴趣的朋友可以自己尝试一下哦!最后大家如果想要了解更多java实例知识,敬请关注奇Q工具网。

推荐阅读:

qt怎么生成exe文件?qt如何自定义信号函数?

java程序员如何提升自己?怎样提高工作效率?

fastjson是哪个包?fastjson对象数组怎么转json?