Believe it or not, you can make Excel talk to you with the Application.Speech.Speak method of VBA. By default, there’s not a way to change the voice or speed, but you can add a reference to the sapi.dll Microsoft Speech Object Library to control all that.
I’ll show you how!
Example - Application.Speech.Speak
Sub TalkToMe() Application.Speech.Speak "Excel is talking to me" End Sub
Make powerful macros with our free VBA Developer Kit Tutorials like this can be complicated. That’s why we created our free VBA Developer Kit to supplement this tutorial. Grab it below and you’ll be writing macros so much faster than you are right now.
Tutorials like this can be complicated. That’s why we created our free VBA Developer Kit to supplement this tutorial. Grab it below and you’ll be writing macros so much faster than you are right now.
The Application.Speech.Speak function gets Microsoft Excel to play whatever string you pass it. By default, it waits until the voice finishes talking before it continues with your macro, but you can change that!
Application.Speech.Speak accepts many arguments. Four arguments as a matter of fact. The first one, we know, is the string you want your computer to say. This is a required argument.
The other 3 arguments are optional and are described below:
- SpeakAsync - By setting this to True, the VBA compiler will continue to march through your code while the voice is speaking. This is usually a good idea because it speeds up your code execution. The default is False. In other words, by default your macro will pause until the voice finishes speaking.
- SpeakXML - Setting this to True will cause your string to be interpreted as XML and any XML tags you have will not be spoken. The default is False, since most of the time you’re not feeding the script any XML. Keeping it False is usually good.
- Purge - If you set this to True, your macro will stop saying anything it was in the process of saying and start saying your new string, instead. In other words, it “purges” the queued up text in favor of your new text. The default is False.
Let’s go through a few examples to see how the arguments change the behavior of the speech method:
First, we’ll add a MsgBox at the end of our original example macro:
Sub TalkToMe2() Application.Speech.Speak "Excel is talking to me" MsgBox "test" End Sub
When you run this macro, you’ll notice the MsgBox doesn’t appear until AFTER the voice finishes saying “Excel is talking to me.” What happens when we set SpeakAsync to True?
Sub TalkToMe3() Application.Speech.Speak "Excel is talking to me", SpeakAsync:=True MsgBox "test" End Sub
Notice the MsgBox immediately pops up! Your macro continues to run while your computer is talking. This is a great feature, and I’m glad it was included in speak property.
To test the purge property, we’ll add a 1 second delay after our first command starts talking. We’ll set the SpeakAsync property to True so our macro will continue running.
Sub TalkToMe4() Application.Speech.Speak "Excel is talking to me", SpeakAsync:=True Application.Wait (Now + TimeValue("00:00:01")) Application.Speech.Speak "Interrupting Cow!", SpeakAsync:=True, Purge:=True End Sub
When you play the code, the voice will stop saying the first string mid-sentence and will start saying “Interrupting Cow!” instead. It clears everything it had planned to say and says your new expression.
Play around and set the Purge property to false - you’ll see that it completely waits to finish saying your first string before starting your second one.
Function to Say Results
Arguably one of the most helpful ways you can get Excel to talk to you is by forcing it to say the value of a cell or multiple cells buried deep on another worksheet.
Another useful application is when you’re performing data entry. Let’s say you’re looking at data on a PDF, sticky note or website. You need to enter some of these values into Excel. Normally, you would look at your source of data, type the data, then look at your spreadsheet to make sure you typed the data correctly. By making Excel repeat the contents of your cells as you enter them, you can confirm whether or not you’ve entered your data correctly.
One way I like to do this is with a custom function (a UDF) designed to let Excel speak the contents of whatever cell I give it.
Function SayIt(cell1 As Variant, Optional bAsync As Boolean, Optional bPurge As Boolean) Application.Speech.Speak (cell1), bAsync, , bPurge SayIt = "Speaking" End Function
Let’s say I’m playing around with my spreadsheet and I want to know the value in cell
=SayIt(A1,TRUE) into any cell and now anytime cell A1 changes, my computer will tell me the new value! It won’t waste my time telling me when other cells change - just when the contents of cell
SayIt accepts 3 arguments, but the last 2 are optional. The two optional arguments control the SpeakAsync and Purge arguments. They’ll default to False, just like the Application.Speech.Speak method.
Change Voice and Speed
Things get a little more complicated when you want to change the voice of your narrator or the speed at which the narrator talks. To change the voice or speed, you have to add a reference to the sapi.dll Microsoft Speech Object Library.
To do this from your VBA editor, go to Tools > References and scroll down until you see “Microsoft Speech Object Library.” I have two references with that title. You want to make sure you check the box next to the one that says sapi.dll in the Location field. If you don’t have this library, you’ll need to download it.
Once you do that, paste the following macro into a module:
Sub ChangeVoiceDemo() SuperTalk "Excel is talking to me.", "BOY", 2, 100 SuperTalk "Excel is talking to me.", "GIRL", 2, 100 SuperTalk "Excel is talking to me.", "BOY", -10, 30 SuperTalk "Excel is talking to me.", "GIRL", 10, 70 End Sub Private Sub SuperTalk(Words As String, Person As String, Rate As Long, Volume As Long) Dim Voc As SpeechLib.SpVoice Set Voc = New SpVoice With Voc If UCase(Person) = "BOY" Then Set .Voice = .GetVoices.Item(0) ElseIf UCase(Person) = "GIRL" Then Set .Voice = .GetVoices.Item(1) End If .Rate = Rate .Volume = Volume .Speak Words End With End Sub
The VBA macro
- Words - the string you want your macro to say
- Person - the voice you want your computer to use. In my example, it can be “BOY” or “GIRL.” See the List Available Voices section for more information about available voices.
- Rate - whole number corresponding to how fast you want your voice to talk. It can range from -10 (very slow) to +10 (very fast).
- Volume - whole number corresponding to how loud you want your voice to talk. It can range from 0 (muted) to 100 (max volume).
List Available Voices
Note: On my computer, I have 2 available voices: one male and one female. I hardwired the “BOY” variable to be the first voice and the “GIRL” variable to be the second voice. Your order and available voices may be different!
You may have more or less so feel free to modify your macro. The following macro prints the number of available voices, provides a sample of each voice, and writes a description of each voice to your Immediate Window:
Sub AvailableVoices() Dim i As Long Dim voc As SpeechLib.SpVoice Set voc = New SpVoice Debug.Print voc.GetVoices.Count & " available voices:" For i = 0 To voc.GetVoices.Count - 1 Set voc.Voice = voc.GetVoices.Item(i) Debug.Print " " & i & " - " & voc.Voice.GetDescription voc.Speak "test audio" Next i End Sub
When I run this, I get the following list of available voices:
2 available voices: 0 - Microsoft David Desktop - English (United States) 1 - Microsoft Zira Desktop - English (United States)
Your list may vary.
A lot of people already know about using Application.Speech.Speak, but few people are aware you can adjust the voice, speed and volume of the narrator by using VBA. This skill is great for self checking data entry and even better for good, ole-fashioned messing with people:-p
It’s also good if you have a macro that takes a really long time to run. You can go about your day doing other things and get your computer to tell you with an audio cue when your macro is complete.
For more macros like this, join our VBA Insiders using the form below.