首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 導出數據到 Excel:文件存在判斷、追加寫入、獲取最後行號完整方案

     編輯:程式設計疑難解答

需求分析

  • 查詢訂單數據導出 Excel
  • 文件不存在 → 新建並寫入表頭 + 數據
  • 文件存在 → 追加數據到現有文件末尾(保留原數據)
  • 關鍵難點:判斷文件存在、獲取最後行號、追加寫入不覆蓋

技術選型:Apache POI

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId> 
    <version>5.2.3</version>
</dependency>

核心工具類實現

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;
import java.util.List;

public class ExcelExporter {
    
    /**
     * 導出數據到 Excel,支持新建/追加
     * @param filePath 文件完整路徑
     * @param headers 表頭數組
     * @param dataList 數據列表,每行為 Object[]
     */
    public static void export(String filePath, String[] headers, List<Object[]> dataList) {
        File file = new File(filePath);
        Workbook workbook;
        Sheet sheet;
        int startRow;
        
        try {
            if (file.exists()) {
                // 1. 文件存在:讀取現有工作簿
                try (FileInputStream fis = new FileInputStream(file)) {
                    workbook = new XSSFWorkbook(fis);
                }
                sheet = workbook.getSheetAt(0);
                startRow = sheet.getLastRowNum() + 1; // 關鍵:獲取最後行號 + 1
                System.out.println("文件存在,從第 " + startRow + " 行開始追加");
            } else {
                // 2. 文件不存在:創建新工作簿
                workbook = new XSSFWorkbook();
                sheet = workbook.createSheet("訂單數據");
                startRow = 0;
                
                // 寫入表頭
                Row headerRow = sheet.createRow(0);
                for (int i = 0; i < headers.length; i++) {
                    Cell cell = headerRow.createCell(i);
                    cell.setCellValue(headers[i]);
                    // 可選:設置表頭樣式
                }
                startRow = 1; // 數據從第 1 行開始(第 0 行是表頭)
            }
            
            // 3. 追加數據
            CellStyle dataStyle = createDataStyle(workbook);
            for (int i = 0; i < dataList.size(); i++) {
                Row row = sheet.createRow(startRow + i);
                Object[] rowData = dataList.get(i);
                for (int j = 0; j < rowData.length; j++) {
                    Cell cell = row.createCell(j);
                    setCellValue(cell, rowData[j]);
                    cell.setCellStyle(dataStyle);
                }
            }
            
            // 4. 自動調整列寬(可選)
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }
            
            // 5. 寫入文件(覆蓋寫入,因為 workbook 已包含舊數據)
            try (FileOutputStream fos = new FileOutputStream(file)) {
                workbook.write(fos);
            }
            
            workbook.close();
            System.out.println("導出成功:" + filePath);
            
        } catch (IOException e) {
            throw new RuntimeException("Excel 導出失敗", e);
        }
    }
    
    private static CellStyle createDataStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }
    
    private static void setCellValue(Cell cell, Object value) {
        if (value == null) {
            cell.setCellValue("");
        } else if (value instanceof Number) {
            cell.setCellValue(((Number) value).doubleValue());
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value);
        } else {
            cell.setCellValue(value.toString());
        }
    }
}

調用示例

public class OrderExportDemo {
    public static void main(String[] args) {
        String filePath = "C:/Users/Admin/Desktop/orders.xlsx";
        String[] headers = {"訂單號", "客戶", "金額", "下單時間"};
        
        // 模擬第一次導出
        List<Object[]> batch1 = List.of(
            new Object[]{"ORD001", "張三", 100.50, "2024-01-15 10:30"},
            new Object[]{"ORD002", "李四", 200.00, "2024-01-15 11:00"}
        );
        ExcelExporter.export(filePath, headers, batch1);
        
        // 模擬第二次導出(追加)
        List<Object[]> batch2 = List.of(
            new Object[]{"ORD003", "王五", 150.75, "2024-01-15 14:20"}
        );
        ExcelExporter.export(filePath, headers, batch2);
    }
}

關鍵技術點總結

需求實現關鍵
判斷文件存在file.exists()
讀取現有文件new XSSFWorkbook(fis) 從輸入流構建
獲取最後行號sheet.getLastRowNum() 返回最後一行索引(0-based)
追加寫入createRow(lastRowNum + 1) 創建新行
保留原數據讀取 → 內存修改 → 整體覆蓋寫入

大數據量優化建議

  • 使用 SXSSFWorkbook(流式寫入,低內存)替代 XSSFWorkbook
  • 批量刷新:workbook.write(fos) 前調用 sheet.flushRows(100) 保留 100 行內存
  • 關閉自動列寬調整:autoSizeColumn 極耗性能,改用預估寬度

參考資源

Apache POI 官方指南:Quick Guide

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved