在 Windows 應用程式開發中,透過 OLE 自動化控制 Excel 是常見需求。本文分享一個在 C++ Builder 環境下完整操作 Excel 的實作範例,特別針對 Windows 2000/XP 環境下 Excel 進程無法正常退出的問題提出解決方案。
在 Windows 2000 作業系統上,僅呼叫 ExcelApp.OleProcedure("Quit") 往往無法徹底終止 Excel 執行緒。若主程式不結束,被呼叫的 Excel 檔案將無法在 Shell 中以 Excel 開啟。解決之道是在釋放 COM 物件前,將所有 Variant 變數明確設為 Unassigned,強制釋放介面指標,使參考計數歸零,讓 Excel 進程正常退出。
為簡化程式碼,建議在標頭檔定義以下巨集:
#define OPG OlePropertyGet
#define OPS OlePropertySet
#define OFN OleFunction
#define OPR OleProcedure
#define PR Procedure
以下程式碼示範:建立新活頁簿、顯示工作表數量、新增並重命名工作表、寫入儲存格資料、刪除工作表、儲存檔案並正確釋放資源。
// 變數宣告
Variant Axl, Workbook, AxSheet, nms, bef, aft;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// 1. 參數準備
AnsiString s = "hello!";
AnsiString filename = GetCurrentDir() + "\\test.xls";
// 2. 檔案存在檢查
if (FileExists(filename)) {
if (MessageDlg("檔案已存在,是否刪除?", mtWarning,
TMsgDlgButtons() << mbOK << mbCancel, 0) == mrOk)
DeleteFile(filename);
else { ShowMessage("放棄操作"); return; }
}
// 3. 建立 Excel 連線
Axl = Variant::CreateObject("Excel.Application");
Axl.OPS("Visible", false); // 背景執行
Workbook = Axl.OPG("Workbooks");
Workbook.Exec(PR("Add")); // 新增活頁簿
Workbook = Axl.OPG("ActiveWorkbook"); // 取得作用中活頁簿
// 4. 顯示現有工作表數量
int count = Workbook.OPG("sheets").OPG("count");
ShowMessage(IntToStr(count) + " 個表");
// 5. 新增工作表並命名為 "test"
aft = Workbook.OPG("sheets", count);
Workbook.OPG("sheets").OPR("Add", bef.NoParam(), aft);
AxSheet = Workbook.OPG("ActiveSheet");
AxSheet.OPS("Name", "test");
// 6. 寫入儲存格 (1,2)
AxSheet.OPG("Cells").OPG("Item", (Variant)1, (Variant)2).OPS("Value", s.c_str());
// 7. 選取第一張工作表
int sheetnum = 1;
AxSheet = Workbook.OPG("sheets", sheetnum);
// 8. 依名稱選取工作表
AnsiString shname = "sheet2";
AxSheet = Workbook.OPG("sheets", shname.c_str());
// 9. 關閉警告並刪除工作表
Workbook.OPG("Application").OPS("DisplayAlerts", false);
AxSheet.OFN("Delete");
Workbook.OPG("Application").OPS("DisplayAlerts", true); // 重新開啟警告
// 10. 儲存並關閉
Workbook.OPR("SaveAs", filename.c_str());
Workbook.OPR("Close");
Axl.OFN("Quit");
// 11. 關鍵:釋放所有 Variant 參考
Axl = Unassigned;
Workbook = Unassigned;
AxSheet = Unassigned;
bef = Unassigned;
aft = Unassigned;
nms = Unassigned;
ShowMessage("Well Done boy!");
}
C++ Builder 的 Variant 封裝了 IDispatch 指標。每次取得屬性或呼叫方法都會增加參考計數。若不顯式設為 Unassigned,參考計數不歸零,Excel 進程便會常駐記憶體。
實際專案中建議包裝在 try...catch 區塊,並在 catch 區塊中同樣執行 Unassigned 清理,確保異常情況下也能正確釋放資源。
開發測試階段可設 Visible = true 觀察 Excel 行為;正式部署建議設 false 提升效能並避免干擾使用者。
掌握 Variant::CreateObject、屬性/方法呼叫巨集、以及 Unassigned 釋放機制,即可在 C++ Builder 中穩健操作 Excel。此模式同樣適用於 Word、PowerPoint 等 Office 元件。