Java 原生無法直接操作 Windows COM 組件,JCom (Java-COM Bridge) 彌補了這一缺口,讓 Java 開發者能像 VB/VBA 一樣自動化 Excel、Word、PowerPoint 甚至系統級組件。本文從基礎入門到數據庫報表導出實戰,全面講解 JCom 核心用法。
jcom.dll)jcom.dll 放入 $JAVA_HOME/bin/,確保 JAVA_HOME 環境變量正確IDispatch 代理 → JNI 層 → COM 運行時 → 目標應用程序JCom 封裝了豐富的 Excel 輔助類 (jp.ne.so_net.ga2.no_ji.jcom.excel8.*),極大簡化操作:
import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
public class ExcelHelloWorld {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager(); // COM 釋放管理器
try {
ExcelApplication excel = new ExcelApplication(rm);
excel.setVisible(true); // 顯示 Excel 窗口
ExcelWorkbooks books = excel.getWorkbooks();
ExcelWorkbook book = books.add(); // 新建工作簿
ExcelWorksheets sheets = book.getWorksheets();
ExcelWorksheet sheet = sheets.getItem(1); // 第一個工作表
ExcelRange range = sheet.getCells();
range.getItem(1, 1).setValue("Hello, World from Java!"); // A1 儲存格
} finally {
rm.release(); // 必須釋放所有 COM 引用
}
}
}

| Excel 概念 | JCom 類 | 關鍵方法 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Application | ExcelApplication | getWorkbooks(), setVisible(), quit() | ||||||||
| Workbook | ExcelWorkbook | getWorksheets(), save(), close() | ||||||||
| Worksheet | ExcelWorksheet | getCells(), getRange(), getName() | ||||||||
| Range | ExcelRange | getItem(row,col), setValue(), copy(), setFormula() |
| A | B | C | D | E | F | G(毛額) | H(稅率) | I(稅額) | J(含稅) | K(淨額) |
|---|---|---|---|---|---|---|---|---|---|---|
| ID | 描述 | 數量 | 單價 | 區域 | 稅率 | =C2*D2 | =F2 | =G2*H2/100 | =G2+I2 | =J2*(100-E2)/100 |

// 1. 打開模板
ExcelApplication excel = new ExcelApplication(rm);
excel.setVisible(true);
ExcelWorkbook book = excel.getWorkbooks().open("c:\\sales.xls");
ExcelWorksheet sheet = book.getWorksheets().getItem(1);
ExcelRange range = sheet.getCells();
// 2. 執行查詢獲取 ResultSet rs ...
int row = 1;
while (rs.next()) {
row++;
// 寫入基礎數據 (列映射由輔助函數處理)
for (int i = 1; i <= colCount; i++) {
int excelCol = mapDbColToExcelCol(i); // DB列 → Excel列映射
range.getItem(row, excelCol).setValue(rs.getObject(i).toString());
}
// 3. 方式一:Java 端寫入 R1C1 相對公式 (不推薦,業務邏輯耦合)
range.getItem(row, 7).setValue("=RC[-2]*RC[-1]"); // 毛額
range.getItem(row, 9).setValue("=RC[-2]*RC[-1]/100"); // 稅額
range.getItem(row, 10).setValue("=RC[-3]+RC[-1]"); // 含稅
range.getItem(row, 11).setValue("=RC[-4]*((100-RC[2])/100)"); // 淨額
}
// 4. 方式二:複製模板公式行 (推薦,業務邏輯留在 Excel)
if (row > 1) {
ExcelRange templateRow = sheet.getRange("A2:K2");
templateRow.copy(sheet.getRange("A" + (row + 1) + ":K" + (row + 1)));
}

RC[-2] 表示「左側第 2 列」,複製到任意行自動調整"=C" + row + "*D" + row 的易錯與難維護無輔助類的組件 (Word, PowerPoint, ADO, WMI 等) 通過底層 IDispatch 統一調用:
// Word 自動化示例
IDispatch wdApp = new IDispatch(rm, "Word.Application");
wdApp.put("Visible", new Boolean(true)); // 設置屬性
// 獲取 Documents 集合並添加文檔
IDispatch docs = (IDispatch) wdApp.get("Documents");
IDispatch doc = (IDispatch) docs.method("Add"); // 調用方法
// 向文檔插入文本
IDispatch selection = (IDispatch) wdApp.get("Selection");
selection.method("TypeText", "Hello from Java via JCom!");
// 保存並退出
doc.method("SaveAs", "c:\\test.doc");
wdApp.method("Quit");
finally 中 rm.release() 防止進程殭屍ComException 中,需捕獲轉換excel8 包對應 Office 97-2003,Office 2007+ 需 excel12 等對應包excel.setScreenUpdating(false),操作完成後恢復| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 純數據導出 (無格式/公式) | Apache POI / JXLS | 純 Java,無需 Office 安裝,跨平台 |
| 複雜模板、圖表、巨集、打印 | JCom / Jacob / COM4J | 需真實 Excel 引擎渲染 |
| 系統級自動化 (Outlook發郵、WMI查詢) | JCom / Jacob | 唯一可行路徑 |
JCom 雖非主流選擇,但在「必須借助 Windows/Office 原生能力」的場景下,提供了極具生產力的 Java 入口。