研究了一下
我一開始的構想是用 cmd 執行播放程式,例如:windows media player
後來爬文知道 cmd 就是預設用 windows media player 來開啟音檔
而在VBA 可以用 Shell函數 或者引用 WScript.Shell物件來執行cmd
但是其實也可以直接用 Shell函數 或者 WScript.Shell物件執行 windows media player
不需要再調用 cmd來執行 windows media player
後來爬文發現另一個方式是調用winmm.dll 的sndPlaySoundA 或 PlaySoundA
以下分別說明這幾種方式的應用
Shell函數
{{CODE-4616}}
| Windowstyle 常數 |
值 |
描述 |
| vbHide |
0 |
隱藏視窗,且將焦點傳遞給隱藏視窗。 VbHide 常數不適用於 Macintosh 平台。 |
| vbNormalFocus |
1 |
視窗有焦點並還原成原始的大小和位置。 |
| vbMinimizedFocus |
2 |
視窗顯示為具有焦點的圖示。 |
| vbMaximizedFocus |
3 |
視窗最大化且具有焦點。 |
| vbNormalNoFocus |
4 |
視窗還原為最近的大小和位置。 目前的作用中視窗仍維持作用中。 |
| vbMinimizedNoFocus |
6 |
視窗顯示為圖示。 目前的作用中視窗仍維持作用中。 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
Public Sub Shell_1()
Dim RetVal '接收回傳執行情況
RetVal = Shell("C:\Program Files (x86)\Windows Media Player\wmplayer.exe C:\windows\media\chord.wav", 0)
If RetVal = 0 Then
MsgBox "執行失敗"
End If
End Sub
'
'
Public Sub Shell_2()
Dim RetVal '接收回傳執行情況
'cmd 語法
'https://learn.microsoft.com/zh-tw/windows-server/administration/windows-commands/cmd
RetVal = Shell("cmd.exe /S /C" & "C:\windows\media\chord.wav", 0)
If RetVal = 0 Then
MsgBox "執行失敗"
End If
End Sub
|
WScript.Shell
語法 .Run(ByVal Command As String, [ByVal WindowStyle], [ByVal WaitOnReturn]) As Integer
WindowStyle:跟Shell函數一樣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
Public Sub ws1()
Dim wsh As Object
Set wsh = CreateObject("WScript.Shell")
'cmd 語法
'https://learn.microsoft.com/zh-tw/windows-server/administration/windows-commands/cmd
wsh.Run "cmd.exe /S /C" & "C:\windows\media\chord.wav", 0, 0
End Sub
'
'
Public Sub ws2()
Dim wsh As Object
Set wsh = CreateObject("WScript.Shell")
wsh.Run "wmplayer.exe C:\windows\media\chord.wav", 0, 0
End Sub
|
無論是Shell函數 還是 WScript.Shell 只要是透過執行cmd來啟動 wmplayer.exe
windows media player都會顯示視窗,無法隱藏,原因在於wmplayer.exe是被cmd啟動的
sndPlaySoundA
引用 winmm.dll 的sndPlaySoundA
參數1 pszSoundName
檔案路徑
參數2 uFlags
SND_ASYNC 異步/非同步 ,也可以用1,播放開始後即往下執行
SND_SYNC 同步,也可以用0,播放完了才往下執行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#If VBA7 Then
'Office 2013 & above
#If Win64 Then
'x64 host
Private Declare PtrSafe Function sndPlaySound32 Lib "winmm.dll" _
Alias "sndPlaySoundA" (ByVal lpszSoundName _
As String, ByVal uFlags As LongPtr) As LongPtr
#Else
'x86 host
Private Declare PtrSafe Function sndPlaySound32 Lib "winmm.dll" _
Alias "sndPlaySoundA" (ByVal lpszSoundName _
As String, ByVal uFlags As Long) As Long
#End If
#Else
'Office 2010 & under:
Private Declare Function sndPlaySound32 Lib "winmm.dll" _
Alias "sndPlaySoundA" (ByVal lpszSoundName _
As String, ByVal uFlags As Long) As Long
#End If
|
1
2
3
4
5
|
Sub SndPly()
Call sndPlaySound32("C:\windows\media\chord.wav", 1)
End Sub
|
PlaySoundA
引用 winmm.dll 的PlaySoundA
參數1 lpszName
檔案路徑
參數2 hModule
必須是0
參數3 dwFlags
SND_ASYNC 異步/非同步 ,也可以用1,播放開始後即往下執行
SND_SYNC 同步,也可以用0,播放完了才往下執行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#If VBA7 Then
'Office 2013 & above
#If Win64 Then
'x64 host
Private Declare PtrSafe Function PlaySound Lib "winmm.dll" _
Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As LongPtr, ByVal dwFlags As LongPtr) As LongPtr
#Else
'x86 host
Private Declare PtrSafe Function PlaySound Lib "winmm.dll" _
Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
#End If
#Else
'Office 2010 & under:
Private Declare Function PlaySound Lib "winmm.dll" _
Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
#End If
|
1
2
3
4
5
|
Sub Ply()
Call PlaySound("C:\windows\media\chord.wav", 0, 1)
End Sub
|
在工作簿的應用
自訂function beepFn()呼叫程序
1
2
3
4
5
|
Function beeFn()
Call sndPlaySound32("C:\windows\media\chord.wav", 1)
End Function
|
在公式引用 自訂function beepFn()
E2=IF(AND(C2<>"",C3 <>""),IF(C2=C3,"PASS","FAIL" & beepFn()),"")
缺點:因為是在公式裡引用,所以開啟檔案的時候會自動執行一次
備註1:關於程式路徑
cmd.exe 無論在Shell函數還是WScript.Shell
都可以省略路徑
而wmplayer.exe在WScript.Shell可以省略路徑,但是在Shell函數必須有完整路徑
這應該是跟環境參數的設定有關
備註2:關於同步/非同步
Shell函數只能非同步執行,也就是執行之後,不會等執行結束,程序就會立即接著執行後面的程式碼
WScript.Shell 、sndPlaySoundA、PlaySoundA,都可以設定同步/非同步
參考資料
VBS中WScript.Shell对象的run和exec的使用及区别
VBA关于声音的多种实现方法
0 comments:
張貼留言