使用 VBA Excel 播放任何音频文件
Play any audio file using VBA Excel
我有一段代码可以读取大多数音频文件(包括wav、mp3、midi...),但如果路径或文件名中有空格,则无法读取。
所以我必须恢复到接受它但只读取 wav 文件的其他代码...
这是读取所有类型音频的代码:
Option Explicit
Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Private sMusicFile As String
Dim Play
Public Sub Sound2(ByVal File$)
sMusicFile = File 'path has been included. Ex. "C:rdMan.mp3
Play = mciSendString("play " & sMusicFile, 0&, 0, 0)
If Play <> 0 Then 'this triggers if can't play the file
'Play = mciSendString("'play " & sMusicFile & "'", 0&, 0, 0) 'i tried this aproach, but doesn't seem to work
End If
End Sub
Public Sub StopSound(Optional ByVal FullFile$)
Play = mciSendString("close " & sMusicFile, 0&, 0, 0)
End Sub
非常感谢任何帮助,(我不想要外部播放器弹出窗口的解决方法,也不想停止使用 VBA)
我找到了解决方法,纠正路径名中的空格(和(编辑)文件名(使用没有空格的文件副本,丑陋但有效(name as
不是一个好的解决方案) :
第一次尝试播放声音后,如果失败我将当前目录更改为声音目录(暂时):
If Play <> 0 Then
Dim path$, FileName0$
path = CurDir
If InStr(sMusicFile, ":") > 0 Then ChDrive (Left(sMusicFile, 1))
If InStr(sMusicFile, "\") > 0 Then
ChDir (Left(sMusicFile, InStrRev(sMusicFile, "\") - 1))
FileName0 = Mid(sMusicFile, InStrRev(sMusicFile, "\") + 1)
If InStr(FileName0, " ") > 0 Then
FileCopy FileName0, Replace(FileName0, " ", "")
sMusicFile = Left(sMusicFile, InStrRev(sMusicFile, "\")) & Replace(FileName0, " ", "")
Play = mciSendString("play " & Replace(FileName0, " ", ""), 0&, 0, 0)
Else
Play = mciSendString("play " & FileName0, 0&, 0, 0)
End If
Else
FileName0 = Replace(sMusicFile, " ", "")
If sMusicFile <> FileName0 Then
FileCopy sMusicFile, FileName0
sMusicFile = FileName0
End If
Play = mciSendString("play " & sMusicFile, 0&, 0, 0)
End If
ChDrive (Left(path, 1))
ChDir (Left(path, InStrRev(path, "\") - 1))
End If
注意:对于名称中的空格,我还有一个新方法:Filecopy sMusicFile replace(sMusicFile," ","%")
然后播放这个新文件
尝试:
Public Sub Sound2(ByVal File$)
If InStr(1, File, " ") > 0 Then File = """" & File & """"
sMusicFile = File
...
如果存在 space,这会将路径用引号括起来,这是某些 API 函数所必需的。
开始 old-school...想想 DOS。
例如:
"C:\Way Too Long\Long Directory\File.mp3"
变成
"C:\WayToo~1\LongDi~1\File.mp3"
诀窍是去掉空格并将目录和文件名保持在 8 个字符以内。为此,请删除所有空格,然后在前 6 个字符后截断并添加波浪号 (~) 和数字一。
我试过这个方法,对我来说效果很好。
需要注意的一件事是,如果缩短的目录名称(如“\Long File Path\”和“\Long File Paths\”和“\Long File Path 1436\”)有可能出现歧义,那么你'您需要调整波浪号后的数字(“\LongFi~1\”和“\LongFi~2\”和“\LongFi~3\”,按照目录创建的顺序)。
因此,有可能之前的文件夹名为 "FilePa~1" 并被删除,而留下了一个类似名称的 "FilePa~2"。因此您的文件路径可能不会自动以“~1”为后缀。它可能是“~2”或更高的值,具体取决于有多少个名称相似的目录或文件名。
我觉得难以置信,dos 已经发布了 35 年了,VBA 程序员仍然不得不处理这个目录问题的恐龙!
无需复制文件即可使用以下解决方案。
它将您的代码与 Get full path with Unicode file name 中 osknows 的代码结合在一起,并采用了上述 Jared 的想法...
Option Explicit
Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal lBuffer As Long) As Long
Private sMusicFile As String
Dim Play, a
Public Sub Sound2(ByVal File$)
sMusicFile = GetShortPath(File)
Play = mciSendString("play " & sMusicFile, 0&, 0, 0)
If Play <> 0 Then 'this triggers if can't play the file
'Play = mciSendString("'play " & sMusicFile & "'", 0&, 0, 0) 'i tried this aproach, but doesn't seem to work
End If
End Sub
Public Sub StopSound(Optional ByVal FullFile$)
Play = mciSendString("close " & sMusicFile, 0&, 0, 0)
End Sub
Public Function GetShortPath(ByVal strFileName As String) As String
'KPD-Team 1999
'URL: [url]http://www.allapi.net/[/url]
'E-Mail: [email]KPDTeam@Allapi.net[/email]
Dim lngRes As Long, strPath As String
'Create a buffer
strPath = String$(165, 0)
'retrieve the short pathname
lngRes = GetShortPathName(strFileName, strPath, 164)
'remove all unnecessary chr$(0)'s
GetShortPath = Left$(strPath, lngRes)
End Function
该函数将长的完整文件名转换为 8.3 短格式。
Function get8_3FullFileName(ByVal sFullFileName As String) As String
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
get8_3FullFileName = FSO.GetFile(sFullFileName).ShortPath
End Function
试试吧。
我有一段代码可以读取大多数音频文件(包括wav、mp3、midi...),但如果路径或文件名中有空格,则无法读取。
所以我必须恢复到接受它但只读取 wav 文件的其他代码...
这是读取所有类型音频的代码:
Option Explicit
Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Private sMusicFile As String
Dim Play
Public Sub Sound2(ByVal File$)
sMusicFile = File 'path has been included. Ex. "C:rdMan.mp3
Play = mciSendString("play " & sMusicFile, 0&, 0, 0)
If Play <> 0 Then 'this triggers if can't play the file
'Play = mciSendString("'play " & sMusicFile & "'", 0&, 0, 0) 'i tried this aproach, but doesn't seem to work
End If
End Sub
Public Sub StopSound(Optional ByVal FullFile$)
Play = mciSendString("close " & sMusicFile, 0&, 0, 0)
End Sub
非常感谢任何帮助,(我不想要外部播放器弹出窗口的解决方法,也不想停止使用 VBA)
我找到了解决方法,纠正路径名中的空格(和(编辑)文件名(使用没有空格的文件副本,丑陋但有效(name as
不是一个好的解决方案) :
第一次尝试播放声音后,如果失败我将当前目录更改为声音目录(暂时):
If Play <> 0 Then
Dim path$, FileName0$
path = CurDir
If InStr(sMusicFile, ":") > 0 Then ChDrive (Left(sMusicFile, 1))
If InStr(sMusicFile, "\") > 0 Then
ChDir (Left(sMusicFile, InStrRev(sMusicFile, "\") - 1))
FileName0 = Mid(sMusicFile, InStrRev(sMusicFile, "\") + 1)
If InStr(FileName0, " ") > 0 Then
FileCopy FileName0, Replace(FileName0, " ", "")
sMusicFile = Left(sMusicFile, InStrRev(sMusicFile, "\")) & Replace(FileName0, " ", "")
Play = mciSendString("play " & Replace(FileName0, " ", ""), 0&, 0, 0)
Else
Play = mciSendString("play " & FileName0, 0&, 0, 0)
End If
Else
FileName0 = Replace(sMusicFile, " ", "")
If sMusicFile <> FileName0 Then
FileCopy sMusicFile, FileName0
sMusicFile = FileName0
End If
Play = mciSendString("play " & sMusicFile, 0&, 0, 0)
End If
ChDrive (Left(path, 1))
ChDir (Left(path, InStrRev(path, "\") - 1))
End If
注意:对于名称中的空格,我还有一个新方法:Filecopy sMusicFile replace(sMusicFile," ","%")
然后播放这个新文件
尝试:
Public Sub Sound2(ByVal File$)
If InStr(1, File, " ") > 0 Then File = """" & File & """"
sMusicFile = File
...
如果存在 space,这会将路径用引号括起来,这是某些 API 函数所必需的。
开始 old-school...想想 DOS。
例如:
"C:\Way Too Long\Long Directory\File.mp3"
变成
"C:\WayToo~1\LongDi~1\File.mp3"
诀窍是去掉空格并将目录和文件名保持在 8 个字符以内。为此,请删除所有空格,然后在前 6 个字符后截断并添加波浪号 (~) 和数字一。
我试过这个方法,对我来说效果很好。
需要注意的一件事是,如果缩短的目录名称(如“\Long File Path\”和“\Long File Paths\”和“\Long File Path 1436\”)有可能出现歧义,那么你'您需要调整波浪号后的数字(“\LongFi~1\”和“\LongFi~2\”和“\LongFi~3\”,按照目录创建的顺序)。
因此,有可能之前的文件夹名为 "FilePa~1" 并被删除,而留下了一个类似名称的 "FilePa~2"。因此您的文件路径可能不会自动以“~1”为后缀。它可能是“~2”或更高的值,具体取决于有多少个名称相似的目录或文件名。
我觉得难以置信,dos 已经发布了 35 年了,VBA 程序员仍然不得不处理这个目录问题的恐龙!
无需复制文件即可使用以下解决方案。
它将您的代码与 Get full path with Unicode file name 中 osknows 的代码结合在一起,并采用了上述 Jared 的想法...
Option Explicit
Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal lBuffer As Long) As Long
Private sMusicFile As String
Dim Play, a
Public Sub Sound2(ByVal File$)
sMusicFile = GetShortPath(File)
Play = mciSendString("play " & sMusicFile, 0&, 0, 0)
If Play <> 0 Then 'this triggers if can't play the file
'Play = mciSendString("'play " & sMusicFile & "'", 0&, 0, 0) 'i tried this aproach, but doesn't seem to work
End If
End Sub
Public Sub StopSound(Optional ByVal FullFile$)
Play = mciSendString("close " & sMusicFile, 0&, 0, 0)
End Sub
Public Function GetShortPath(ByVal strFileName As String) As String
'KPD-Team 1999
'URL: [url]http://www.allapi.net/[/url]
'E-Mail: [email]KPDTeam@Allapi.net[/email]
Dim lngRes As Long, strPath As String
'Create a buffer
strPath = String$(165, 0)
'retrieve the short pathname
lngRes = GetShortPathName(strFileName, strPath, 164)
'remove all unnecessary chr$(0)'s
GetShortPath = Left$(strPath, lngRes)
End Function
该函数将长的完整文件名转换为 8.3 短格式。
Function get8_3FullFileName(ByVal sFullFileName As String) As String
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
get8_3FullFileName = FSO.GetFile(sFullFileName).ShortPath
End Function
试试吧。