Using Excel VBA and MIDI to Play Scales

In this post, I can going to demonstrate how you can use VBA to interact with the MIDI capabilities of your PC to play a simple musical scale. In music, scales consist of a series of notes, that are either a semitone or wholetone (in pitch) apart from each other. In this example, we are going to play a C major diatonic scale. This will consist of 8 notes starting with C and finishing with the same note an octave higher.


For a major scale, the interval between the 3rd and 4th notes (E & F) and the 7th and 8th notes (B & C) is a semitone. For the rest of the notes, the interval is going to be a wholetone. This will be an important thing to note, when it comes to coding the scale.

For the solution, I have created two classes called csNote and csMidi:

The class csNote, is going to be used to model each musical note within the scale. Note objects derived from this class, will have all the attributes required for the note to be played by the csMidi class. The Note class will also allow us to specify instructions in musical language, so that they can be translated into MIDI language for the csMidi class to understand. The csMidi class will encapsulate all the lower level code required for playing MIDI sounds on our PC. The code below shows how the two classes are used to play the scale:

A Key of C is defined as well as a starting octave (this is the pitch range for the note) for the scale. The code makes 8 note iterations for the scale. With each iteration it moves the note either a wholetone or semitone up from the previous note until it reaches the last note. That is all that is required to play the scale! The code for both of the classes is presented below:

Note Class (csNote)

Midi Class (csMidi)


Thank you for reading this post. Please take time to read the disclaimer about content found on this site.

Share :Facebooktwitterredditpinterestmail

6 thoughts on “Using Excel VBA and MIDI to Play Scales”

  1. Hi,

    I believe you missed to call StopNote at line 111 of PlayNote in Midi Class (csMidi) in order to release ON keys!


      1. Very useful code, however for the 64bit office version you need to do the following!

        #If Win64 Then
        Private Declare PtrSafe Function midiOutClose Lib “winmm.dll” (ByVal hMidiOut As LongPtr) As Long
        Private Declare PtrSafe Function midiOutOpen Lib “winmm.dll” (lphMidiOut As LongPtr, ByVal uDeviceID As LongPtr, ByVal dwCallback As LongPtr, ByVal dwInstance As LongPtr, ByVal dwflags As LongPtr) As Long
        Private Declare PtrSafe Function midiOutShortMsg Lib “winmm.dll” (ByVal hMidiOut As LongPtr, ByVal dwMsg As LongPtr) As Long
        Private Declare PtrSafe Function timeGetTime Lib “winmm.dll” () As Long
        Private Declare Function midiOutClose Lib “winmm.dll” (ByVal hMidiOut As Long) As Long
        Private Declare Function midiOutOpen Lib “winmm.dll” (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
        Private Declare Function midiOutShortMsg Lib “winmm.dll” (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
        Private Declare Function timeGetTime Lib “winmm.dll” () As Long
        #End If

        #If Win64 Then
        Private mlngCurDevice As LongPtr
        Private mlngHmidi As LongPtr
        Private mlngRc As LongPtr
        Private mlngMidiMsg As LongPtr
        Private mlngCurDevice As Long
        Private mlngHmidi As Long
        Private mlngRc As Long
        Private mlngMidiMsg As Long
        #End If

        Thanks for the code.

    1. Hi Bensley, this is a message produced by the code when it has an issue trying to open the midi port on your computer. It is on line 72 of the the csMidi class. When the function “midiOutOpen” is called if the return value is anything other than a 0, this indicates that the class was unable to open the port. Put a debug statement on line 70 and see what the return value of “mlngRc” is. Then check this value against the error messages listed on the api documentation here:
      Go to the section “RETURN VALUE”. This will hopefully tell you what the issue is.

      1. Hello
        I’ve the same problem but this list is alphanumeric and the error is numeric (lngc=4).
        However, what can I do with this error (4)?

Leave a Reply to Rui Monteiro Cancel Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.