You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI+Java:实现Excel工作表追加写入及存在性判断(避免覆盖)

解决Apache POI写入Excel不覆盖原有数据的问题

嗨,我来帮你搞定这个问题~你的代码现在每次都会新建空白工作簿和工作表,直接覆盖了原有文件,而且没处理已有数据的写入位置,所以才会出现删除原有内容、只能写一行的情况。咱们这样调整:

关键修改点

  • 读取已有工作簿:不再直接创建新工作簿,先尝试读取现有文件,文件不存在时才新建。
  • 复用已有工作表:遍历工作簿中的工作表,找到目标表就复用,找不到再新建。
  • 定位空白行:获取已有数据的最后一行索引,从下一行开始写入新数据。
  • 正确保存修改:基于读取到的完整工作簿修改后,再写回原文件,保证原有数据不丢失。

修改后的完整代码

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ApachePOIExcelWrite {
    private static final String FILE_NAME = "c:/viagem.xlsx";
    private static final String SHEET_NAME = "Viagem";

    public static void main(String[] args) {
        XSSFWorkbook workbook = null;
        XSSFSheet sheet = null;

        try {
            // 1. 尝试读取已有Excel文件
            File excelFile = new File(FILE_NAME);
            if (excelFile.exists()) {
                FileInputStream fis = new FileInputStream(excelFile);
                workbook = new XSSFWorkbook(fis);
                fis.close();

                // 2. 检查目标工作表是否存在
                boolean sheetExists = false;
                for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                    if (workbook.getSheetName(i).equals(SHEET_NAME)) {
                        sheet = workbook.getSheetAt(i);
                        sheetExists = true;
                        break;
                    }
                }
                // 不存在则新建工作表
                if (!sheetExists) {
                    sheet = workbook.createSheet(SHEET_NAME);
                }
            } else {
                // 文件不存在时新建工作簿和工作表
                workbook = new XSSFWorkbook();
                sheet = workbook.createSheet(SHEET_NAME);
            }

            // 3. 获取最后一行的索引,下一行就是新数据的起始行
            int lastRowNum = sheet.getLastRowNum();
            // 如果工作表是空的,lastRowNum是-1,所以起始行设为0
            int startRow = lastRowNum == -1 ? 0 : lastRowNum + 1;

            // 示例数据(可以替换成你的实际数据)
            Object[][] data = {
                    {"张三", "北京", "2024-05-20"},
                    {"李四", "上海", "2024-05-21"}
            };

            // 4. 写入数据到新行
            for (Object[] rowData : data) {
                XSSFRow row = sheet.createRow(startRow++);
                int colNum = 0;
                for (Object cellData : rowData) {
                    XSSFCell cell = row.createCell(colNum++);
                    if (cellData instanceof String) {
                        cell.setCellValue((String) cellData);
                    }
                    // 可以根据数据类型扩展,比如数字、日期等
                }
            }

            // 5. 保存修改到文件
            FileOutputStream fos = new FileOutputStream(FILE_NAME);
            workbook.write(fos);
            fos.close();
            System.out.println("数据写入成功,原有内容未被覆盖!");

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭工作簿资源
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

代码说明

  • 读取已有文件:通过FileInputStream读取现有Excel,保证原有数据被加载到工作簿对象中。
  • 工作表检查:遍历工作簿的所有工作表,避免重复创建,复用已有工作表。
  • 空白行定位:sheet.getLastRowNum()返回最后一行的索引,空表时返回-1,所以处理后得到新数据的起始行。
  • 数据写入:循环写入多行数据,每次创建新行并填充单元格,不会覆盖原有行。
  • 资源关闭:在finally块中关闭工作簿,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Paulo Roberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:30:48