VBA播放音樂:如何引用Window API中的winmm.dll程式庫

VBA可以設計程式讓Excel播放音樂,本文介紹如何於模組層級進行Declare宣告,引用Windows動態連結程式庫中的winmm.dll,執行PlaySound以及sndPlaySound函數,同時補充PtrSafe、Sub、function相關概念。

一、wav音樂檔案

首先在windows電腦的特定資料夾放置了兩個音樂檔案,分別為mp3及wav格式在這裡。本篇文章範例程式實際上播放的是wav音樂檔案,並不能播放mp3,在此特別放上mp3是作為對照。不能播放mp3的理由很簡單,所用的微軟程式庫不支援。wav是微軟開發提倡的音樂檔案格式,因此微軟自己作業系統一開始是以wav為優先適用。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 1

二、VBA播放音樂

設計VBA程式如下截圖所示,實際上執行的程式非常簡單只有一個語句,這裡會比較陌生的地方可能在一開始的宣告(Declare),它是用VB(Visual Basic)語法去引用windows的API服務,亦即作業系統本身播放聲音的程式庫,關於這個宣告接下來會有更多的說明。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 3

三、Declare PtrSafe

首先介紹宣告中的前三個單字「Private Declare PtrSafe」,其中Private表示只有本身這個模組才可以使用該語句,與Private相對應是Public,Public是在這個專案裡面所有的程式都可以使用,Public為預設值,如果沒有特別設定就是Public。另外可以注意到Private跟Public不但可以用在宣告Declare這裡,也可以用在Sub或者Function,都是代表整個程式段落的作用範圍。

「Declare」如同上個步驟所述,宣告引用windows的API程式庫。這裡特別加上「PtrSafe」,因為是在64位元電腦使用32位元程式庫,要特別標註以便於兼容。其實只要把這個單字刪掉,VBA編輯器馬上會跳出錯誤視窗,提示說明相當清楚,它就是windows系統當初從32位元轉換到64位元的時候,當然不會費周章去更改原來32位元的既有程式庫,不過為了要讓64位元順利使用32位元資源,至少要提示一下方便系統作業。也就要加上這裡看到的「PtrSafe」。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 5

四、Windows API dll

為了更加瞭解「Lib “Winmmdll”」這個語法,可以實際到windows電腦系的C槽找到這個程式庫:「C:\Windows\System32」,所謂的Windows API就是去執行預先設計好在這個檔案的系統程式,可以看到它是在「System32」裡面,合理推測它便是windows系統早期延續下來的32位元程式庫,這也是上個步驟為何會用到PtrSafe的緣故。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 7

五、Sub與Alias

接下來介紹「Sub」與「Alias」,它後面接的都是「PlaySound」,這是一種習慣用法,其實Sub後面接的只是開發者所設計程式的代稱,跟VBA常見語法一樣也可以取其他名稱,不過Alias就是正式的Windows程式名稱,不能更改,關於這個「PlaySpund」,可以參考一下微軟說明文件,它是在Winmm.dll裡的一個函數,作用是可以播放wav音樂檔案。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 9

六、sndPlaySpund

在Winmm.all程式庫裡,除了「PlaySpund」函數,其實還有一個「sndPlaySpund」,同樣都可以播放wav音樂檔案,這個類似於Python的套件工具,在一個套件模組裡會有許多對象函數可以引用。另外注意到上個步驟有說明「PlaySpund」是三個參數,因此第二步驟的VBA程式宣告會設定「ByVal pszSound As String, ByVal hmod As Long, ByVal fdwSound As Long)」,而這裡「sndPlaySpund」是兩個參數,因此是「ByVal lpszSoundName As String, ByVal ufalgs As Long)」,有興趣可以跟上個步驟類似去參考微軟說明文件。這些參數如果沒有特別用到可以直接設定為0,因此第二步驟是「PlaySound “E:\VBA\吉他前奏.wav”, 0, 0」,三個參數掛兩個0,這裡的步驟是「sndPlaySound “E:\VBA\吉他前奏.wav”, 0」兩個參數掛一個0,兩個步驟的第一個參數很容易理解,就是音樂檔案所在的資料夾路徑。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 11

七、Sub程序名稱

先前第五步驟有提到Sub後面所接的只是單純一個名稱,因此也可以在宣告中改為是「播放音樂」,因此在設計執行程式的語句也跟著變成是「播放音樂」,同樣是可以執行播放音樂的。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 13

八、Function傳回值

如果仔細去看先前第五步驟所提到的微軟說明,會發現到它是一個函數,有傳回值,而且是傳回一個真假值,因此在這裡程式範例可以改成個宣告一個「Function 播放音樂」,接著再定義一個布林真假值的變數:「Dim 有沒有 As Boolean」,然後再把這個變數設為是播放音樂的傳回值:「有沒有 = 播放音樂(“E:\VBA\吉他前奏.wav”, 0)」,注意到它的語法跟先前有點不太一樣,會以括號方式進行函數語句的撰寫,最後用一個MsgBox把所得到的傳回值以文字訊息的視窗方式呈現。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 15

九、VBA執行測試

執行上個步驟程式,如果順利播放的話,會是在播放結束之後回到Excel畫面並跳出MsgBox視窗,顯示是「True」,如果把是範例程式改成是MP3檔案的話,就會失敗完全沒有播放音樂,直接跳出視窗顯示「False」,這部份讀者可以自行嘗試看看,或者是參考本篇文章最後所附的YouTube的影片會有更加完整的測試。

VBA播放音樂:如何引用Window API中的winmm.dll程式庫 17

從Excel VBA到Visual Basic

這篇文章陸續提到了幾個程式範例,不過其實幾乎都是相同結構,照樣造句的宣告以及實際執行的程式,雖然和其他通常的VBA程式專案比起來,本文的程式語句並不長,但是因為涉及到一般比較少用到的 windows作業系統程式庫,已經超越了VBA原始自動化操作Excel的功能,而是以Visual Basic作為程式語言直接引用Windows系統資源的方式,在這個過程中剛好可以作為從Excel VBA進入VB純粹程式語言的範例,提供給讀者參考。

完整學習:VBA自動化文章合輯