简体   繁体   English

使用 VBA Excel 播放任何音频文件

[英]Play any audio file using VBA Excel

I have a piece of code which can read most audio files (including wav, mp3, midi...), but it won't work if there are spaces in the path or File name.我有一段代码可以读取大多数音频文件(包括 wav、mp3、midi...),但如果路径或文件名中有空格,它将无法工作。

so I have to revert to my other code which accepts it, but reads only wav files...所以我必须恢复到接受它的其他代码,但只读取 wav 文件......

this is the code for reading all type of audio:这是读取所有类型音频的代码:

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:\3rdMan.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

Any help much appreciated, (I don't want workaround with external player popup, nor which I can't stop from playing with VBA)非常感谢任何帮助,(我不想解决外部播放器弹出窗口,也不想停止使用 VBA)

i found The work-around, that correct spaces in path name (and (edit) for file name (using copy of file with no spaces, ugly but works ( name as would not be a good solution) :我找到了解决方法,即文件名的路径名(和(编辑)中的正确空格(使用没有空格的文件副本,丑陋但有效)( name as不是一个好的解决方案):

After the first attempt to play the sound, if fails i change the current directory to the sound directory (temporarely):第一次尝试播放声音后,如果失败,我将当前目录更改为声音目录(暂时):

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

Note : for spaces in the name i got also a new method : Filecopy sMusicFile replace(sMusicFile," ","%") and then play this new file注意:对于名称中的空格,我还有一个新方法: Filecopy sMusicFile replace(sMusicFile," ","%")然后播放这个新文件

Go old-school...think DOS.去老派......想想DOS。
For example:例如:
"C:\\Way Too Long\\Long Directory\\File.mp3" "C:\\Way Too Long\\Long Directory\\File.mp3"
becomes变成
"C:\\WayToo~1\\LongDi~1\\File.mp3" "C:\\WayToo~1\\LongDi~1\\File.mp3"

The trick is to get rid of spaces and keep directories and filenames under 8 characters.诀窍是去掉空格并将目录和文件名保持在 8 个字符以内。 To do this, remove all spaces, then truncate after the first 6 characters and add a tilde (~) plus the number one.为此,请删除所有空格,然后在前 6 个字符后截断并添加波浪号 (~) 和数字 1。
I tried this method and it worked perfectly for me.我试过这种方法,它对我来说非常有效。

One thing to be cautious of is that if there is a chance of ambiguity in a shortened directory name (like "\\Long File Path\\" and "\\Long File Paths\\" and "\\Long File Path 1436\\") then you'll need to adjust the number after the tilde ("\\LongFi~1\\" and "\\LongFi~2\\" and "\\LongFi~3\\", in the order in which the directories were created).需要注意的一件事是,如果缩短的目录名称(如“\\Long File Path\\”和“\\Long File Paths\\”和“\\Long File Path 1436\\”)中存在歧义的可能性,那么您需要调整波浪号后面的数字(“\\LongFi~1\\”和“\\LongFi~2\\”和“\\LongFi~3\\”,按照目录的创建顺序)。

Therefore, it is possible that a previous folder was called "FilePa~1" and was deleted while a similarly named "FilePa~2" was left.因此,前一个文件夹可能被称为“FilePa~1”并被删除,而留下一个类似名称的“FilePa~2”。 So your file path may not automatically be suffixed with a "~1".因此,您的文件路径可能不会自动以“~1”为后缀。 It might be "~2" or something higher, depending on how many similarly named directories or filenames there were.它可能是“~2”或更高,这取决于有多少类似命名的目录或文件名。

I find it incredible that dos was released 35 years ago, and VBA programmers are still having to deal with this dinosaur of a problem with directories!我觉得不可思议的是,dos 是在 35 年前发布的,而 VBA 程序员仍然不得不处理这个目录问题的恐龙!

Try:尝试:

Public Sub Sound2(ByVal File$)

If InStr(1, File, " ") > 0 Then File = """" & File & """"

sMusicFile = File

...

This will wrap the path in quotes if there is a space, which is required for some API functions.如果有空格,这会将路径用引号括起来,这是某些 API 函数所必需的。

The following solution works without having to copy the file.以下解决方案无需复制文件即可工作。

It incorporates your code together with code from osknows in Get full path with Unicode file name with the idea from Jared above...它将您的代码与来自 osknows 的代码合并在一起, 使用 Unicode 文件名的完整路径,其想法来自上述 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

The function converts long full filename to 8.3 short format.该函数将长完整文件名转换为 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

Try it.尝试一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM