“Search and Replace” in Visual Basic Applications

Foreword

Although Visual Basic is not one of my favorite languages, I like its simplicity and rich set of libraries. Many times when developing an application that deals with an enormous amount of textual data, you need a functionality that makes the job of correcting misspelt words easier. Microsoft Word, for example, when running a “Spell Check” gives you an opportunity to correct a wrongly typed word (through suggestions). It also facilitates a “Search and Replace” tool that can be used for user-defined word replacments. Here in this article, I am not going to give you details about implementing a dictionary; rather, I focus on how this feature (find and replace) can be implemented in a VB application.

Prerequisites

While I explain the code, I assume that you have worked in Visual Basic and are familiar with various in-built controls and library functions (I have used a few of them) that are available from within the Visual Studio IDE. I have tried to keep the code as simple as possible, and you will be able to understand the logic in a while. If you want to know more about some library functions (such as its syntax, params, and so forth) visit MSDN online.

Groundwork

Create a Standard EXE VB project. Rename the default form as frmMainForm. Add a menu to the default form with the following details (the & sign is used for accelerator key and the name preceded with word mnu depicts menu-item’s internal name (used in code)),

&Edit
...&Find and Replace   mnuFindandreplace
E&xit                  mnuExit

Add a TextBox control to this form and rename it as txtClientArea. Stretch and adjust it with mouse so that it covers entire client-area of the form. Set this TextBox’s MultiLine property to True from the Properties window.

Add another form to this project (from Project > Add Form). Rename this form as frmFindReplace and set its BorderStyle property to 4 - FixedToolWindow from the Properties window. Now, add two TextBox controls and rename them as txtSearchTerm and txtReplaceWithString respectively. Add a checkbox control and rename it as chkCaseSense. Finally, add a CommandButton to the form and rename it as cmdReplace.

In the frmMainForm, you will write the following code:

Private Sub mnuExit_Click()
   End
End Sub

Private Sub mnuFindandreplace_Click()
   frmFindReplace.FindnReplace txtClientArea
End Sub

It is apparent from the above code that when the user clicks on the “Exit” menu item we want to terminate the application and when he selects the “Find and Replace” submenu item from the “Edit” menu, you want to activate the frmFindReplace form by the means of calling public interface of frmFindReplace; in other words, FindnReplace(). This public interface allows the search algorithm to be generic. With this interface, you provide your TextBox as an argument (in which the search is to be performed). By replacing the name txtClientArea with your own TextBox’s name, you can invoke the same search-replace functionality for as many TextBoxes (as well as many times) as desired, without repeating the search code. The main code of “Search and Replace” is, however, placed under the frmFindReplace form only. The code for this module follows.

Source Code

' This variable is used for making the algorithm generic.
Dim txtClient As TextBox

' This method is the public interface to SnR functionality.
Public Sub FindnReplace(ByRef Tb As TextBox)
   Set txtClient = Tb
   Me.Show , txtClient.Parent
End Sub

Private Sub cmdReplace_Click()
   Dim CaseSense      As Integer
   Dim SourceText     As String
   Dim SourceTextCopy As String
   Dim Cnt            As Integer

   ' Check for the case sensitivity options
   If (chkCaseSense.Value = vbChecked) Then
      CaseSense = 0
   Else
      CaseSense = 1
   End If

   ' One contains the original text and another contains replaced
   ' (updated) one.
   ' Used to check whether a replacement was done or not.
   SourceText = txtClient.Text
   SourceTextCopy = SourceText

   If Len(SourceText) = 0 Then
      Exit Sub
    End If

On Error GoTo ErrHandler
   Dim SearchTermLen As Integer
   Dim FndPos As Integer

   SearchTermLen = Len(txtSearchTerm.Text)
   ' Search from the begining of the document.
   Cnt = 1

' This is endless loop (terminated on a condition checked inside
' the loop body).
While (1)

   FndPos = InStr(Cnt, SourceText, txtSearchTerm.Text, CaseSense)

   ' When a match is found, replace it appropriately.
   If (FndPos > 0) Then
      SourceText = ReplaceFun(SourceText, FndPos, _
                   Len(txtSearchTerm.Text), _
                   txtReplaceWithString.Text)
      Cnt = FndPos + SearchTermLen
   Else
      Cnt = Cnt + 1
   End If

   ' Whether a replacement was done at all or not
   If (Cnt >= Len(SourceText)) Then
      txtClient.Text = SourceText
      If (SourceTextCopy <> SourceText) Then
         MsgBox "Finished replacing all occurrences.", _
                vbInformation + vbOKOnly, _
                "Replaced All"
      Else
         MsgBox "No matching strings found. No text replaced.", _
                vbInformation + vbOKOnly, _
                "No Replacement"
      End If
      Unload Me
      Exit Sub
   End If
      ' Else Restart from henceforth
Wend
Exit Sub

ErrHandler:
    Response = MsgBox("An error ocurred while searching. Inform _
               the developer with details.", _
               vbExclamation + vbOKOnly, "Error Searching")
End Sub

Private Sub Form_Load()
   ' Default SearchTerm must be the one selected by the user in
   ' MainForm
   If Len(txtClient.SelText) <> 0 Then
      txtSearchTerm.Text = txtClient.SelText
   End If
End Sub

Function ReplaceFun(Source As String, FromPos As Integer, _
                    Length As Integer, StringTBReplaced _
                    As String) As String
   ' Replaces a source string with new one appropriately
   Dim ResultStr As String

   ResultStr = Left(Source, FromPos - 1)
   ResultStr = ResultStr & StringTBReplaced
   ResultStr = ResultStr & Right(Source, Len(Source) - FromPos - _
                                 Length + 1)

   ReplaceFun = ResultStr
End Function

Private Sub txtReplaceWithString_Change()
   Call EnableDisableReplaceButton
End Sub

Private Sub txtReplaceWithString_GotFocus()
   ' Select the contents of the textbox
   If Len(txtReplaceWithString.Text) <> 0 Then
      txtReplaceWithString.SelStart = 0
      txtReplaceWithString.SelLength = Len(txtReplaceWithString.Text)
   End If
End Sub

Private Sub txtSearchTerm_Change()
   Call EnableDisableReplaceButton
End Sub

Private Sub EnableDisableReplaceButton()
   If Len(txtSearchTerm.Text) <> 0 _
      And Len(txtReplaceWithString.Text) <> 0 Then
      cmdReplace.Enabled = True
   Else
      cmdReplace.Enabled = False
    End If
End Sub

Private Sub txtSearchTerm_GotFocus()
   ' Select the contents of textbox
   If Len(txtSearchTerm.Text) <> 0 Then
      txtSearchTerm.SelStart = 0
      txtSearchTerm.SelLength = Len(txtSearchTerm.Text)
   End If
End Sub

More by Author

Must Read