Excel VBA 調用自編 DLL 執行耗時任務,需在 Excel 界面實時顯示進度條。
// C++ DLL
typedef void (__stdcall *ProgressCallback)(int percent, const wchar_t* msg);
__declspec(dllexport) int LongTask(ProgressCallback cb) {
for (int i = 0; i <= 100; ++i) {
// ... 任務邏輯 ...
if (cb) cb(i, L"Processing...");
Sleep(50);
}
return 0;
}
' 標準模塊
Public Declare PtrSafe Function LongTask Lib "MyDll.dll" _
(ByVal cb As LongPtr) As Long
Public Declare PtrSafe Function AddressOf Lib "kernel32" _
Alias "GetProcAddress" (ByVal hModule As LongPtr, ByVal lpProcName As String) As LongPtr
' 實際需用 GetProcAddress 獲取 VBA 函數地址,或使用類模塊實現 ICallback 接口
' 更簡單:VBA 7+ 可用 LongPtr 傳遞函數指針
完整 VBA 回調寫法較繁瑣,建議參考 「VBA Callback DLL」 成熟範例(如 VBA-Callback)。
Public Sub OnProgress(ByVal percent As Long, ByVal msg As String)
UserForm1.ProgressBar1.Value = percent
UserForm1.LabelCaption.Caption = msg
DoEvents ' 讓 UI 重繪
End Sub
WithEvents 接收(需註冊、註冊表,較重)。GetProgress(),VBA 循環調用並 DoEvents(簡單但輪詢開銷大)。DoEvents 刷新。try-catch 轉為錯誤碼返回,避免跨邊界拋出 C++ 異常導致 VBA 崩潰。**回調函數**是 VBA 調用 DLL 實時回報進度的標準模式。關鍵在於正確獲取 VBA 函數地址傳給 DLL,並在回調中安全更新 UI。建議封裝通用回調助手類,複用於所有長任務 DLL。