oleaut32.dll),實現 Java 物件與 COM 物件雙向映射jacob_1.9.zip (或更新版 1.14.3+)jacob.jar → 加入 Classpath (專案 Libraries / WEB-INF/lib / Maven 依賴)jacob.dll (32/64-bit 對應 JVM) → 放入 java.library.path 目錄:
%JAVA_HOME%/bin%SYSTEMROOT%/System32 (需管理員權限)WEB-INF/lib/native/ (配合 -Djava.library.path)regsvr32),COM 元件本身需已在系統註冊| 類別 | 用途 | 關鍵方法 |
|---|---|---|
ActiveXComponent | 代表 COM 物件 (ProgID/CLSID) | getObject(), invoke(), setProperty(), getProperty() |
Dispatch | 底層 IDispatch 封裝 | call(), put(), get(), getEnum() |
Variant | COM VARIANT 類型映射 | toString(), toInt(), toBoolean(), getDispatch() |
ComThread | STA 執行緒管理 (Office 自動化必須) | initSTA(), release(), run() |
EnumVariant | 集合迭代 | next(), hasMoreElements() |
import com.jacob.com.*;
import com.jacob.activeX.*;
public class AppTest {
public static void main(String[] args) {
// 1. 建立 COM 物件 (ProgID: "ScriptControl")
ActiveXComponent scriptControl = new ActiveXComponent("ScriptControl");
Dispatch dispatch = scriptControl.getObject();
// 2. 設定腳本語言
Dispatch.put(dispatch, "Language", "VBScript");
// 3. 呼叫 Eval 方法執行運算式
Variant result = Dispatch.call(dispatch, "Eval", args[0]); // args[0] = "1+2*3"
// 4. 輸出結果
System.out.println(result.toString()); // 輸出 7
}
}
編譯執行:
javac -cp jacob.jar AppTest.java
java -cp .;jacob.jar AppTest "1+2*3"
public class ExcelReport {
public static void main(String[] args) {
ComThread.InitSTA(); // 必須:Office 需單執行緒單元
ActiveXComponent excel = null;
try {
excel = new ActiveXComponent("Excel.Application");
excel.setProperty("Visible", new Variant(false)); // 背景執行
Dispatch workbooks = excel.getProperty("Workbooks").toDispatch();
Dispatch workbook = Dispatch.call(workbooks, "Add").toDispatch();
Dispatch sheets = Dispatch.get(workbook, "Sheets").toDispatch();
Dispatch sheet = Dispatch.call(sheets, "Item", 1).toDispatch();
// 寫入標題
Dispatch.put(Dispatch.call(sheet, "Cells", 1, 1).toDispatch(), "Value", "產品");
Dispatch.put(Dispatch.call(sheet, "Cells", 1, 2).toDispatch(), "Value", "價格");
// 寫入資料 (範例)
String[][] data = {{"蘋果", "50"}, {"香蕉", "30"}, {"橘子", "40"}};
for (int i = 0; i < data.length; i++) {
Dispatch.put(Dispatch.call(sheet, "Cells", i+2, 1).toDispatch(), "Value", data[i][0]);
Dispatch.put(Dispatch.call(sheet, "Cells", i+2, 2).toDispatch(), "Value", data[i][1]);
}
// 儲存
String filePath = "C:\\temp\\report.xls";
Dispatch.call(workbook, "SaveAs", filePath);
System.out.println("報表已產生: " + filePath);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (excel != null) {
Dispatch.call(excel.getObject(), "Quit"); // 關閉 Excel 進程
}
ComThread.Release(); // 釋放 STA
}
}
}
ComThread.InitSTA() 啟動,結束時 ComThread.Release()Dispatch、Variant 用完呼叫 safeRelease() 或 Dispatch.safeRelease(),避免 COM 參考計數洩漏導致 Excel/Word 殭屍進程ComFailException,檢查 ex.getErrorCode() 對應 HRESULTUnsatisfiedLinkError 或 ClassNotRegisteredExceptionVisible=false、DisplayAlerts=false,避免彈窗卡住| 錯誤 | 原因 | 解決 |
|---|---|---|
Can't load library: jacob.dll | DLL 不在 library path | 設定 -Djava.library.path=... 或放入 System32 |
ClassNotRegisteredException | COM 元件未註冊或位元不符 | 確認 Office 安裝位元,regsvr32 相關 DLL |
| Excel 進程不退出 | 未呼叫 Quit / 參考未釋放 | 加 Dispatch.call(app, "Quit")、徹底 safeRelease |
| 中文亂碼 | Variant 字串編碼 | 使用 new Variant(str),Jacob 內部處理 Unicode |
Jacob 是 Java 呼叫 Windows COM 的經典橋樑,適合維護舊系統整合 Office/系統管理自動化。核心要點:STA 執行緒、參考計數釋放、位元相容。新專案優先考慮 Apache POI 或雲端 API,避免平台鎖定與維護負擔。