尝试使用Windows API从电子表格中打开音频文件

时间:2015-12-25 04:13:00

标签: excel vba audio


我正在努力以一种不会泄露他们名字的方式从Excel打开声音文件(这是一个测验)。我怀疑这应该很容易,但到目前为止我所看到的一切都让我感到困惑。 我之前已经建立了基于电子表格的测验而不是声音文件,我随机排序问题的顺序,并从隐藏字段中的值检查我的答案。总结了正确的答案 - 简单的电子表格功能以及一些具有动态范围的VBA
我只想点击特定的单元格,以便打开声音文件(从隐藏字段中的文件名到我点击的位置给定的偏移量),播放一首歌然后关闭而不显示文件名,让我输入导致声音文件打开的单元格的答案。

我使用的是Windows 10和Excel 2013与64位计算机。  
我想从一个链接指定的普通目录中访问MP3声音。我会使用超链接但是: a)他们引入令人讨厌的“你真的认为这个链接是安全的”消息,人们在网上有成功的混合 - 它涉及摆弄注册表,我宁愿不去那里。这些显示声音文件的名称,让游戏远离! b)在其他应用程序中打开文件并提供文件名。这是一个让他们再次关闭的问题 - 测验可能是数百个电话。 我考虑过嵌入文件,但这似乎是内存密集型的 - 如果每个文件可以从其他地方打开和关闭,那么为什么要将它们放入一个庞大的电子表格中? 相反,我试图使用sndPlaySound打开声音文件,我认为这是应该完成目标的64位功能。 到处都有关于如何做到这一点的帖子,但没有一个对我来说是最有意义的。我尝试调整下面的URL中的代码(对于32位 - 使用不同的sndPlaySound32),但无济于事。 http://www.cpearson.com/excel/PlaySound.aspx 与我的电子表格相关联的代码(到目前为止)非常简单,并响应用户单击测验的“答案”列,从隐藏位置获取声音文件的名称(使用偏移量)并使用以下方法调用sndPlaySound函数隐藏文件名。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

'Declare my sound directory
Dim SoundDirectory As String
SoundDirectory = "C:\Users\Andrew\Desktop\Bird Sounds\"

'The file name comes from a hidden cell using an offset function
Dim File As String
File = ActiveCell.Offset(columnOffset:=1).Value

'Declare variable link to be derived from SoundDirectory and File     variables
Dim Link As String

'Used to see if the user has moved to a cell used to open a sound file (2nd column)
Dim MyColumn As Long
If ActiveCell.Column = 2 Then
Link = SoundDirectory & File

‘The next line my machine hates this - it tells me there is a missing  "=" sign.

'sndPlaySound (Link,0)
End If
End Sub 

在一个模块中,我从windows API声明了sndPlaySound方法,将其从原始方法中改变,因为我相信它需要64位的sndPlaySound而不是sndPlaySound32

Public Declare Function sndPlaySound _
    Lib "winmm.dll" _
    Alias "sndPlaySoundA" ( _
    ByVal lpszSoundName As String, _
    ByVal uFlags As Long) As Long

我会非常感谢任何建议:)

2 个答案:

答案 0 :(得分:0)

我猜你的具体问题可以通过你的评论来证明:

  

'下一行,我的机器讨厌这个 - 它告诉我有一个缺失   " ="登录。

这是由于VBA中的语法,并且与API调用没有任何关系。如果将参数包装在括号中,则告诉编译器您关心返回值。由于您显然不关心返回(您的代码会丢弃它),因此您需要在其前面使用Call关键字来表示它可以被丢弃(并且您还应明确传递将0作为Long - 更好的是使用来自mmsystem.hSND_SYNC的API常量声明:

Call sndPlaySound(Link, 0&)

如果省略括号,则隐含可以忽略返回值,并且编译器不会抱怨缺少赋值:

sndPlaySound Link, 0&

我也不知道为什么Pearson声明函数返回Long - 它实际上返回BOOL,因此可以安全地在VBA中将其声明为Boolean ...

Public Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" ( _
    ByVal lpszSoundName As String, ByVal uFlags As Long) As Boolean

...或者因为你从不使用返回值,你可以通过将其声明为Sub来简单地丢弃返回值:

Public Declare Sub sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" ( _
    ByVal lpszSoundName As String, ByVal uFlags As Long)

也就是说,根据MSDN,只保留sndPlaySound以实现向后兼容性 - 您应该使用PlaySound代替:

Option Explicit

#If VBA7 Then
    Public Declare PtrSafe Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
        (ByVal pszSound As String, ByVal hmod As Any, ByVal fdwSound As Long) _
        As Boolean
#Else
    Public Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
        (ByVal pszSound As String, ByVal hmod As Any, ByVal fdwSound As Long) _
        As Boolean
#End If

'fdwSound flag constants:
Public Const SND_SYNC = 0&
Public Const SND_ASYNC = 1&
Public Const SND_NODEFAULT = 2&
Public Const SND_MEMORY = 4&
Public Const SND_LOOP = 8&
Public Const SND_NOSTOP = 16&
Public Const SND_NOWAIT = &H2000&
Public Const SND_ALIAS = &H10000
Public Const SND_FILENAME = &H20000

Public Sub Example()
    Dim wave As String
    wave = Environ("SystemRoot") & "\Media\" & "chord.wav"
    If PlaySound(wave, 0&, SND_FILENAME Or SND_NODEFAULT) = False Then
        Debug.Print "File not found."
    End If
End Sub

注意:我怀疑PtrSafe声明是必需的,因为传递的唯一指针是String,AFAIK会自动处理(如果不是,请发表评论& #39; t准确)。请注意,hmod可以声明为Any,因为您始终会将其传递给0&来自VBA。

答案 1 :(得分:0)

我很难实施你们给我的建议(对不起,我希望你教育我的尝试对你有用!)。然而,我做了一个非常简单的工作,虽然不是我完全理解的。 解决方法使用隐藏单元格的超链接。

http://spreadsheetpage.com/index.php/tip/playing_mp3_files_from_excel/

根据您的默认媒体播放器,标题可能或多或少显而易见。我的下一个阶段是构建一个宏来将目录中的文件名提取到隐藏列中,并可能从元数据中提取物种的名称。前者是我之前完成的(通过窃取有才能的人的代码!)。我会将一些文件附加到Dropbox并在此处将其链接起来,但在此期间我的代码是:

'This function responds to a user clicking in the Answer column of the quiz, getting the name of a sound file from a hidden
'location and calling the sndPlaySound function using it
'Macro which will trigger if you place the cursor in the second row between the 2nd and nth rows as defined by where there is data
Private Sub Worksheet_SelectionChange(ByVal Target As Range)


'Find End Row, used to see if macro should run from cursor insertion event
Dim EndRow As Long

'Declare my directory
Dim SoundDirectory As String
SoundDirectory = "C:\Users\Andrew\Desktop\Bird Sounds\"

'File name will be derived from contents of a cell
Dim File As String

With ActiveSheet
EndRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With

'Exit the sub routine if it is not relevant to procede

If ActiveCell.Column <> 2 Or ActiveCell.Row = 1 Or ActiveCell.Row > EndRow Then
    Exit Sub
    End If

    'The file name comes from a hidden cell using an offset function

    File = ActiveCell.Offset(columnOffset:=1).Value

    'Built from SoundDirectory and File
    Dim Sound As String

    Sound = SoundDirectory & File

    Application.ScreenUpdating = True
    On Error Resume Next
   ActiveSheet.OLEObjects.Add(Filename:=Sound, Link:=False).Select
   If Err.Number <> 0 Then
     Application.ScreenUpdating = True
     MsgBox "Incorrect or missing hyperlink"
     Exit Sub
   End If
   Selection.Verb
   Selection.Delete

End Sub

End Sub