VB中的查找替换[1]
http://www.csai.cn 作者:不详 来源:yesky 2007年2月2日 发表评论 进入社区
一、前言
尽管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.", _
bExclamation + 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被扫描时,这个循环都将被激活。
第二步,我使用