Creating a Spell Checker in Visual Basic

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Introduction

Spelling and grammar are a headache, especially for a bi-lingual person such as me. I am quite good with spelling, but grammar not that much. Today, you will learn how to create your own spelling checker.

Our Project

The project is nothing spectacular. There are simply two buttons on the form, as shown in Figure 1:

Our Design
Figure 1: Our Design

Add a new Class and name it ‘Spell.’ Add the following Namespaces to the Spell class:

Imports System.IO
Imports System.Text.RegularExpressions

The System.IO namespace is responsible for reading and writing the files. You will read a file containing some text a bit later in this example. The System.Text.RegularExpressions namespace allows you to manipulate words and phrases.

Add the following fields to the class:

   Private strLetters As String = "abcdefghijklmnopqrstuvwxyz"
   Private regWord As New Regex("[a-z]+", RegexOptions.Compiled)

   Private dicDictionary As New Dictionary(Of [String], Integer)()

strLetters contains all the alphabetic letters that we will work with. The regWord object will be used to identify the words that need to be checked for spelling and manipulate them. dicDictionary contains the correct words to be checked against. Add the Constructor:

   Public Sub New()

      Dim strFile As String = File.ReadAllText("Dictionary.txt")

      Dim lstWords As List(Of String) = _
         strFile.Split(New String() {vbLf}, _
         StringSplitOptions.RemoveEmptyEntries).ToList()

      For Each strWord As String In lstWords

         Dim strTrim As String = strWord.Trim().ToLower()

         If regWord.IsMatch(strTrim) Then

            If dicDictionary.ContainsKey(strTrim) Then

               dicDictionary(strTrim) += 1

            Else

               dicDictionary.Add(strTrim, 1)

            End If

         End If

      Next

   End Sub

When the Spell class is instantiated, the Dictionary.txt file gets read and formatted and the contents get stored inside the dicDictionary object. Add the Prepare Function:

   Private Function Prepare(strWord As String) As List(Of String)

      Dim lstParts = New List(Of Tuple(Of String, String))()

      Dim lstInverts = New List(Of String)()
      Dim lstDeletions = New List(Of String)()
      Dim lstReplaces = New List(Of String)()
      Dim lstInsertions = New List(Of String)()

      ' Splits '
      For p As Integer = 0 To strWord.Length - 1

         Dim tParts = New Tuple(Of String, String)
            (strWord.Substring(0, p), strWord.Substring(p))

         lstParts.Add(tParts)

      Next

      ' Transposes '
      For i As Integer = 0 To lstParts.Count - 1

         Dim strOne As String = lstParts(i).Item1
         Dim strTwo As String = lstParts(i).Item2

         If strTwo.Length > 1 Then

            lstInverts.Add(strOne + strTwo(1) + strTwo(0) & _
               strTwo.Substring(2))

         End If

      Next

      ' Deletes '
      For d As Integer = 0 To lstParts.Count - 1

         Dim strOne As String = lstParts(d).Item1
         Dim strTwo As String = lstParts(d).Item2

         If Not String.IsNullOrEmpty(strTwo) Then

            lstDeletions.Add(strOne & strTwo.Substring(1))

         End If

      Next

      ' Replaces '
      For r As Integer = 0 To lstParts.Count - 1

         Dim strOne As String = lstParts(r).Item1
         Dim strTwo As String = lstParts(r).Item2

         If Not String.IsNullOrEmpty(strTwo) Then

            For Each letter As Char In strLetters

               lstReplaces.Add((strOne & letter) + _
                  strTwo.Substring(1))

            Next

         End If

      Next

      ' Inserts '
      For i As Integer = 0 To lstParts.Count - 1

         Dim strOne As String = lstParts(i).Item1
         Dim strTwo As String = lstParts(i).Item2

         For Each letter As Char In strLetters

            lstInsertions.Add(Convert.ToString
               (strOne & letter) & strTwo)

         Next

      Next

      Return lstDeletions.Union(lstInverts)
         .Union(lstReplaces).Union(lstInsertions).ToList()

   End Function

The Prepare Function identifies the given word’s broken pieces. These pieces could be a misplaced letter, a missing letter, or an accidentally swapped letter. Once all the options have been considered and processed, it returns a list containing possible words that could match the wrongly spelled word. Add the final Function:

   Public Function Fix(strWord As String) As String

      If String.IsNullOrEmpty(strWord) Then

         Return strWord

      End If

      strWord = strWord.ToLower()

      If dicDictionary.ContainsKey(strWord) Then

         Return strWord

      End If

      Dim lstWords As List(Of [String]) = Prepare(strWord)
      Dim dicPotential As New Dictionary(Of String, Integer)()
      For Each strVariation As String In lstWords

         If dicDictionary.ContainsKey(strVariation) AndAlso _
               Not dicPotential.ContainsKey(strVariation) Then

            dicPotential.Add(strVariation, dicDictionary(strVariation))

         End If

      Next

      If dicPotential.Count > 0 Then

         Return dicPotential.OrderByDescending _
            (Function(x) x.Value).First().Key

      End If

      For Each sWord As String In lstWords

         For Each strVariation As String In Prepare(sWord)

            If dicDictionary.ContainsKey(strVariation) AndAlso _
                  Not dicPotential.ContainsKey(strVariation) Then

               dicPotential.Add(strVariation, dicDictionary(strVariation))

            End If

         Next

      Next

      Return If((dicPotential.Count > 0), _
         dicPotential.OrderByDescending(Function(x) x.Value) _
         .First().Key, strWord)

   End Function

The Fix Function takes the received word and compares it with a correct similar word.

Add the following code behind the Button on Form1 labeled ‘Words:’

   Private Sub Button1_Click(sender As Object, e As EventArgs)_
         Handles Button1.Click

      Dim sEngine As New Spell()
      Dim strWord As String = ""

      strWord = "spellling"

      Console.WriteLine("{0} => {1}", strWord, _
         sEngine.Fix(strWord))

      strWord = "Hannes"

      Console.WriteLine("{0} => {1}", strWord, _
         sEngine.Fix(strWord))

      strWord = "supposidly"

      Console.WriteLine("{0} => {1}", strWord, _
         sEngine.Fix(strWord))

      Console.Read()

   End Sub

The preceding code is quite self-explanatory.

Add the following code behind the remaining button labeled ‘Sentences:’

   Private Sub Button2_Click(sender As Object, e As EventArgs) _
         Handles Button2.Click

      Dim sEngine As New Spell()

      Dim strSentence As String = "I cann niot spel niceely"

      Dim strCorrection As String = ""

      For Each wWord As String In strSentence.Split(" "c)

         strCorrection += " " + sEngine.Fix(wWord)

      Next

      Console.WriteLine(Convert.ToString("Did you mean:") _
         & strCorrection)

      Console.Read()

   End Sub

This code looks similar to the previous code except for the part that includes a loop. The For Each loop loops through each word in the given sentence.

Download the Code

You can download the code to accompany this article from the link below.

Conclusion

As you can see, creating a spell checker is quite simple. All you need is a bit of logic.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read