在 Windows 環境下,Excel 試算表幾乎是辦公自動化的代名詞。然而,若要用 Java 程式直接操控 Excel 檔案(.xls),卻非易事。早期 Web 應用常透過 JSP/Servlet 產生 CSV 並以 text/csv MIME 型別回傳,瀏覽器再呼叫 Excel 開啟。這雖能「檢視」資料,卻無法真正「操作」試算表(如格式化、公式、樣式等)。
本文介紹開源專案 Java Excel API (JExcelApi),讓 Java 開發者能以純 Java 程式碼,跨平台地讀取、建立、修改 Excel 97/2000 格式檔案,並支援字型、數字、日期格式、儲存格陰影與顏色等豐富功能。
jxl.Workbook、可寫 jxl.write.WritableWorkbook)。jxl.Sheet、jxl.write.WritableSheet)。jxl.Cell、jxl.write.WritableCell 及其子類別 Label、Number、DateTime、Boolean 等)。import java.io.*;
import jxl.*;
InputStream is = new FileInputStream("source.xls");
Workbook rwb = Workbook.getWorkbook(is); // 唯讀 Workbook
亦可直接用 Workbook.getWorkbook(new File("source.xls"))。
Sheet rs = rwb.getSheet(0); // 索引從 0 開始
// 或依名稱:Sheet rs = rwb.getSheet("Sheet1");
Cell c00 = rs.getCell(0, 0); // (column, row)
String str = c00.getContents(); // 統一以字串取值
// 若需確切型別:
if (c00.getType() == CellType.LABEL) {
LabelCell lc = (LabelCell) c00;
String text = lc.getString();
} else if (c00.getType() == CellType.NUMBER) {
NumberCell nc = (NumberCell) c00;
double val = nc.getValue();
} else if (c00.getType() == CellType.DATE) {
DateCell dc = (DateCell) c00;
Date date = dc.getDate();
}
| 類別 | 方法 | 說明 |
|---|---|---|
| Workbook | getNumberOfSheets() | 取得工作表數量 |
| Workbook | getSheets() | 取得所有 Sheet 陣列 |
| Workbook | getVersion() | 取得 API 版本 |
| Sheet | getName() | 取得工作表名稱 |
| Sheet | getColumns() | 取得總欄數 |
| Sheet | getRows() | 取得總列數 |
| Sheet | getColumn(int col) | 取得指定欄的所有 Cell 陣列 |
| Sheet | getRow(int row) | 取得指定列的所有 Cell 陣列 |
| Sheet | getCell(int col, int row) | 取得指定儲存格(注意參數順序:column, row) |
rwb.close(); // 釋放記憶體,讀取大量資料時尤為重要
import jxl.write.*;
WritableWorkbook wwb = Workbook.createWorkbook(new File("target.xls"));
// 或寫入輸出串流(如 Servlet 輸出):
// OutputStream os = response.getOutputStream();
// WritableWorkbook wwb = Workbook.createWorkbook(os);
WritableSheet ws = wwb.createSheet("Report", 0); // 名稱、索引
// 純文字
ws.addCell(new Label(0, 0, "Hello"));
// 帶字型格式
WritableFont wf = new WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD, true);
WritableCellFormat wcf = new WritableCellFormat(wf);
ws.addCell(new Label(1, 0, "Styled", wcf));
// 紅色字體
WritableFont wfRed = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false,
UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED);
ws.addCell(new Label(2, 0, "Red", new WritableCellFormat(wfRed)));
// 數值與格式
NumberFormat nf = new NumberFormat("#.##");
ws.addCell(new Number(0, 1, 3.1415926, new WritableCellFormat(nf)));
// 日期與格式
DateFormat df = new DateFormat("dd MMM yyyy HH:mm:ss");
ws.addCell(new DateTime(0, 2, new java.util.Date(), new WritableCellFormat(df)));
// 布林值
ws.addCell(new Boolean(0, 3, true));
注意:儲存格位置在建構時即固定(column, row,索引從 0 起),不可變更位置,只能修改內容。
wwb.write(); // 將緩衝資料寫入檔案/串流
wwb.close(); // 釋放資源
務必先呼叫 write() 再 close(),否則會產生空白檔案。
// 1. 讀取唯讀 Workbook
Workbook rb = Workbook.getWorkbook(new File("source.xls"));
// 2. 以其為基礎建立可寫入副本
WritableWorkbook wb = Workbook.createWorkbook(new File("target.xls"), rb);
// 3. 取得可寫入 Sheet 並修改
WritableSheet ws = wb.getSheet(0);
WritableCell wc = ws.getWritableCell(0, 0);
if (wc.getType() == CellType.LABEL) {
((Label) wc).setString("Updated Value");
}
// 4. 寫入並關閉(須關閉兩個 Workbook)
wb.write();
wb.close();
rb.close();
此機制為效率考量:讀取時忽略格式資訊,僅保留數值;修改時在記憶體中同時保留兩份副本,大檔案會佔用較多記憶體。
文末亦附上 POI (HSSF) 建立 50x50 矩陣的範例,展示另一主流選擇。
JExcelApi 以輕量、易用、跨平台特性,成為 Java 操作 Excel 97/2000 格式的經典方案。雖近年 Apache POI 支援更廣(含 .xlsx),JExcelApi 於維護舊系統、簡易報表產出仍具參考價值。