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

JXL 導出 Excel 僅有一行資料?缺少 Row 建立邏輯與 workbook.write() 位置錯誤雙重陷阱

     編輯:程式設計綜合問答

使用 JXL (jexcelapi) 導出 Excel 時,雖然迴圈正確跑完、sheet.addCell() 呼叫無誤,但輸出檔案只有一行資料。本文指出兩大核心錯誤:未顯式建立 Row 物件 (JXL 需手動管理列) 與 workbook.write() 放在迴圈內導致重複寫入/截斷,並提供修正後的完整代碼範例。

錯誤代碼關鍵片段

WritableSheet sheet = workbook.createSheet("Sheet1", 0);
int line = 0;
for (int i = 1; i <= 10; i++) {
    // ... 爬蟲取得資料 ...
    for (int j = 0; j < jsonArray.length(); j++) {
        // 建立 Cell
        Number rate = new Number(0, line, douRate); // 欄 0
        Label label = new Label(1, line, strComment); // 欄 1
        line++;
        sheet.addCell(rate);
        sheet.addCell(label);
        workbook.write(); // ❌ 錯誤:在迴圈內寫入
    }
}
workbook.close();

兩大核心問題詳解

1. JXL 不自動建立 Row,需手動管理列索引

  • JXL 的 WritableSheet 採用「座標式」API:new Label(col, row, value),不需 也 無法 顯式建立 Row 物件 (這是 Apache POI HSSF/XSSF 的做法)。
  • 原代碼 line++ 邏輯正確,問題在於 workbook.write() 位置錯誤導致資料未正常刷新。
  • 結論:JXL 不需要 呼叫 sheet.createRow(),直接指定 row 索引即可。

2. workbook.write() 必須在「所有資料寫入完成後」呼叫一次

  • workbook.write() 會將記憶體中完整的工作簿結構序列化寫入輸出流。
  • 放在迴圈內會導致:多次開啟同一檔案寫入、檔案截斷、效能極差、僅保留最後一次寫入的資料 (通常只有最後一行或標題列)。
  • 修正:移至雙重迴圈結束後、workbook.close() 之前。

修正後完整代碼範例

import jxl.*;
import jxl.write.*;
import java.io.File;
import java.util.Date;

public class JxlExportDemo {
    public static void main(String[] args) throws Exception {
        WritableWorkbook workbook = Workbook.createWorkbook(new File("export.xls"));
        WritableSheet sheet = workbook.createSheet("Comments", 0);

        // 1. 寫入標題列 (row = 0)
        Label hdrCol0 = new Label(0, 0, "Rating");
        Label hdrCol1 = new Label(1, 0, "Content");
        sheet.addCell(hdrCol0);
        sheet.addCell(hdrCol1);

        int line = 1; // 從第 1 列開始寫資料 (0 為標題)

        // 模擬資料來源迴圈
        for (int page = 1; page <= 3; page++) {
            // 假設從網路/資料庫取得 List
            List comments = fetchComments(page);
            for (Comment c : comments) {
                // 2. 建立 Cell,指定 (col, row)
                Number rateCell = new Number(0, line, c.rating);
                Label contentCell = new Label(1, line, c.content);
                sheet.addCell(rateCell);
                sheet.addCell(contentCell);
                line++;
            }
        }

        // 3. 所有資料加入完成後,統一寫入一次
        workbook.write();
        workbook.close();
        System.out.println("導出完成,共 " + (line - 1) + " 筆資料");
    }

    static class Comment { double rating; String content; }
    static List fetchComments(int page) { /* 略 */ return new ArrayList<>(); }
}

JXL vs Apache POI 關鍵差異對照

特性JXL (jexcelapi)Apache POI (HSSF/XSSF)
支援格式僅 .xls (BIFF8).xls + .xlsx
Row 管理隱式,由 Cell 座標決定顯式 sheet.createRow(rowIdx)
寫入觸發workbook.write() 一次性可串流 SXSSF 分批寫入
記憶體佔用全載入記憶體,不適合 > 10 萬列SXSSF 低記憶體模式
維護狀態停止更新 (最後版 2009)活躍維護中

遷移建議

新專案強烈建議直接使用 Apache POI (含 SXSSFWorkbook 處理大資料),避免 JXL 停維、不支援 .xlsx、記憶體限制等坑。若必須維護舊 JXL 專案,請牢記:

  1. Cell 座標 (col, row) 自行管理,不需建立 Row。
  2. workbook.write() 只呼叫一次,置於所有 addCell 之後、close() 之前。
  3. 寫入前先加標題列 (row=0),資料從 row=1 開始。

總結

JXL 導出只有一行,主因是 workbook.write() 放在迴圈內導致重複覆寫/截斷。JXL 採用座標式 API 無需顯式建立 Row,只要確保「正確計算 row 索引、統一在最後寫入一次」即可正常導出多行資料。長期專案請規劃遷移至 Apache POI。

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