扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
尽管Visual Basic并不是我最喜欢的开发工具,但我喜欢它简单而又丰富的库集。每当开发一个需要处理大量文本数据的应用程序时,需要具有拼写错误纠正功能,例如,微软的Word程序,当运行"拼写检查"时,将提供给你一个改正错误的机会(尽管是建议),它同时也提供了"查找替换"工具,用以进行用户定义的单词替换。这篇文章我将解释如何在VB应用程序中实现"查找替换"功能。
二、前提条件
在解释代码的时候,我假定读者朋友们已经有使用Visual Basic的经验,熟悉Visual Studio开发环境中各种内置的控件及库函数(尽管我使用的不多)。我已经尝试着尽可能地简化程序代码,用不了多久你就可以明白程序的逻辑。如果想对一些库函数(如参数,语法)进一步详细地理解,可以参阅MSDN。图一是程序运行后的效果图:
图一、程序实现"查找替换"功能时的效果图
三、基础工作
首先创建一个标准的EXE类型的VB工程,将默认窗体更名为frmMainForm ,在默认窗体上增添一个菜单,具体设置如下(符号"&"用于加速键,单词mnu后的名字用来说明菜单项的名字(在代码中使用)):
&Edit
...&Find and Replace mnuFindandreplace
E&xit mnuExit
向默认窗体添加一个TextBox控件,命名为txtClientArea。使用鼠标调整控件位置和尺寸,使它覆盖窗体的整个客户区,在属性窗口将这个TextBox控件的 MultiLine属性设置为"True"。
使用Project > Add Form菜单向工程中添加另外一个窗体,将这个窗体命名为"frmFindReplace",并在属性窗口中将它的BorderStyle属性设置为"4 - FixedToolWindow"。现在,添加两个TextBox控件,并分别命名为"txtSearchTerm"和"txtReplaceWithString"。添加一个复选框,命名为chkCaseSense。最后,添加一个命令按钮控件,命名为"cmdReplace"。
在frmMainForm窗体中添加如下代码:
Private Sub mnuExit_Click()
End
End Sub
Private Sub mnuFindandreplace_Click()
frmFindReplace.FindnReplace txtClientArea
End Sub
从上面代码中可以非常明显地看出, 当点击Exit菜单时,我们想终结应用程序,当点击"Find and Replace"菜单时,想通过共用接口frmFindReplace及FindnReplace()方法来激活frmFindReplace窗体。这个公用的接口使查找算法具有普遍性,使用这个接口时,需要提供一个TextBox作为参数(在这里面,搜寻将被执行)。通过使用你自己的TextBox的名字来代替txtClientArea的名字,可以在多个文本框内执行"查找替换"功能,而不用更改代码。"查找和替换"的实现代码主要是在frmFindReplace窗体内,这个模块的代码如下:
'' 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
四、代码说明
公用接口SearchnReplace的"查找替换"算法带有普遍性,使用这种方法,"查找替换"功能可以在任何应用程序中实现,而不用更改frmFindReplace的代码。只是在调用公用接口的地方需要做一些小的改动。
"查找和替换"代码在cmdReplace_Click()过程与ReplaceFun() 函数下,让我们从cmdReplace_Click()过程开始。
首先,变量CaseSense用于跟踪用户的选择,是否是大小写敏感,如果用户选择大小写敏感的话,它的值设置为0,否则,设置为1。变量SourceText和SourceTextCopy用于保存frmMainForm窗体中 txtClientArea的内容(或者是用户在主窗体中为TextBox提供的内容,对于本程序来说,它就是txtClientArea),两个变量保存同样的内容将在下面进行解释(一个是临时变量)。变量Cnt用来跟踪文档的结束,当重新从文档开始处进行"查找替换"时它将非常有用。这个变量含蓄地说明了当前光标的位置,下次的"查找替换"将从这个位置开始。
主要的算法在while循环内,只要替换或是源TextBox被扫描时,这个循环都将被激活。
第二步,我使用了InStr()库函数,它将从第一个参数规定的位置处开始搜索,如果在第二个参数字符串中发现与第三个字符串相匹配的子串,将返回该子串的位置。最后一个参数是大小写敏感选项。
InStr()函数的返回值传递给FndPos,如果在源文档中发现了所要查找的字符串,这个值将大于0,否则将返回一个0值。在紧接着的IF语句中,首先替换SourceText变量,然后是通过FndPos + SearchTermLen语句修改Cnt变量,这是必须的, 因为下一次的"查找和替换"要从新的位置开始。另一方面,在Else部分,Cnt变量加一,说名查找和替换要从下一个字符开始。紧接着的几个语句用来通知用户查找结果,它们非常容易理解,也非常容易实现。可以直接跳过它们。
最后,ReplaceFun()函数进行实际的替换工作,它从源字符串的左边开始,挑选出所有的字符,直到发现所搜索的字符串位置处为止。紧接着,StringTBReplace被添加到结果的后面,它将代替所匹配的源字符串。最后,所有的保留的源字符(排除所要更换的子字符串)被添加到这个结果中去,并作为结果返回。
五、结论
有很多方法来实现这一功能,但我认为我所使用的方法是最简单也是最直接的,通过例子程序,你可以在应用程序中实现自己的"查找替换"功能。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者