英文:
Autocompletion in a TextBox - VBA
问题
I am trying to do a function to do some autocompletion in a TextBox. I want to autocomplete word per word but currently the autocompletion is only effective on the first typed word. For example if I write "ba," it autocompletes easily with "banana" from the column wanted, no problem on this point. But when I write another word after "banana" (with one space between them two, obviously) the autocomplete is not working. It only works on one word. Can you help me? Here is new code:
Private Sub TextBoxComm_Change()
' Your code here
End Sub
And my first version was this one: (just on another TextBox but I apply the same code on every textbox)
Private Sub TextBoxMach_Change()
' Your code here
End Sub
英文:
I am trying to do a function to do some autocompletion in a TextBox. I want to autocomplete word per word but currently the autocompletion is only effective on the first typed word.
For exemple if i write "ba" it autocompletes easely with "banana" from the column wanted no problem on this point. But when I write another word after "banana" (with one space between them two obviously) the autocomplete is not working. It only work on one word
Can you help me ? Here is new code :
Private Sub TextBoxComm_Change()
Dim lastRow As Long
Dim searchRange As Range
Dim foundCell As Range
Dim chaine, Mot_Proposé As String
Dim word As String 'WORD FAIT OFFICE DE SEArch string
If m_ignore Then Exit Sub
'Définition du champs de recherche
word = TextBoxComm.text
Set searchRange = ThisWorkbook.Worksheets("Base de données").ListObjects("RCA").ListColumns("Numéro de commande").DataBodyRange
'si c'est vide ne rien faire
If word = "" Then Exit Sub
'Trouve la dernière cellule de la colonne
lastRow = searchRange.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
' Si le mot tapé n'apparaît trouver le mot le plus ressemblant
Set foundCell = searchRange.Find(What:=word & "*", LookIn:=xlValues, LookAt:=xlWhole)
If Not foundCell Is Nothing Then
'Compléter le mot tapé
chaine = foundCell.Value
m_currentSuggestion = Find_Mot(word, chaine)
TextBoxComm.text = m_currentSuggestion
If Len(m_currentSuggestion) > 0 Then
m_currentText = m_currentSuggestion
m_selectionStart = Len(word)
m_selectionLength = Len(m_currentSuggestion) - Len(word)
TextBoxComm.text = m_currentText
TextBoxComm.SelStart = m_selectionStart
TextBoxComm.SelLength = m_selectionLength
End If
End If
End Sub
And my first version was this one : (just on another TextBox but i apply the same code on every textbox)
'Machine
Private Sub TextBoxMach_Change()
Dim lastRow As Long
Dim searchRange As Range
Dim searchString As String
Dim foundCell As Range
Dim chaine, Mot_Proposé As String
If m_ignore Then Exit Sub
'Définition du champs de recherche
Set searchRange = ThisWorkbook.Worksheets("Base de données").ListObjects("RCA").ListColumns("Type de machine").DataBodyRange
searchString = TextBoxMach.text
'Ne rien faire si le TextBox est vide
If searchString = "" Then Exit Sub
'Trouve la dernière cellule de la colonne
lastRow = searchRange.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
'Chercher si le mot tapé apparaît déjà dans la colonne
Set foundCell = searchRange.Find(What:=searchString, LookIn:=xlValues, LookAt:=xlWhole)
If Not foundCell Is Nothing Then
'Si oui, autocomplétion
chaine = foundCell.Value
Mot_Proposé = Find_Mot(searchString, chaine)
TextBoxMach.text = Mot_Proposé
TextBoxMach.SelStart = Len(searchString)
TextBoxMach.SelLength = Len(foundCell.Value) - Len(searchString)
Else
' Si le mot tapé n'apparaît trouver le mot le plus ressemblant
Set foundCell = searchRange.Find(What:=searchString & "*", LookIn:=xlValues, LookAt:=xlWhole)
If Not foundCell Is Nothing Then
'Compléter le mot tapé
chaine = foundCell.Value
Mot_Proposé = Find_Mot(searchString, chaine)
TextBoxMach.text = Mot_Proposé
TextBoxMach.SelStart = Len(searchString)
TextBoxMach.SelLength = Len(foundCell.Value) - Len(searchString)
End If
End If
End Sub
答案1
得分: 2
以下是您提供的代码的翻译:
我今天为了WPF自己也在寻找类似的东西,然后在learn.microsoft.com上遇到了一篇文章。我将它从C#翻译成了VBA,并修复了一个与退格键有关的问题,当按下该键时,会导致一个字母无法被删除。
这个示例使用了一个硬编码的单词列表,但你可以在窗体初始化时从Excel获取数据以填充一个数组。
来源:[WPF中TextBox的自动完成(MVVM)][1]
----------
私有字段和源集合:
Option Explicit
Private m_words As VBA.Collection
Private m_currentInput As String
Private m_currentSuggestion As String
Private m_currentText As String
Private m_selectionStart As Integer
Private m_selectionLength As Integer
Private m_ignore As Boolean
'初始化源
Private Sub UserForm_Initialize()
Set m_words = New VBA.Collection
Populate
End Sub
Private Sub Populate()
m_words.Add "英文"
m_words.Add "中文"
m_words.Add "法文"
m_words.Add "法文一"
m_words.Add "法文二"
m_words.Add "俄文"
m_words.Add "日文"
End Sub
----------
`Change()` 事件处理程序:
'Change()
Private Sub AutoTextBox_Change()
If m_ignore Then Exit Sub
Dim word As String
word = AutoTextBox.Text
If Len(word) > Len(m_currentInput) And word <> m_currentSuggestion Then
m_currentSuggestion = FindWord(word)
If Len(m_currentSuggestion) > 0 Then
m_currentText = m_currentSuggestion
m_selectionStart = Len(word)
m_selectionLength = Len(m_currentSuggestion) - Len(word)
AutoTextBox.Text = m_currentText
AutoTextBox.SelStart = m_selectionStart
AutoTextBox.SelLength = m_selectionLength
End If
End If
End Sub
----------
一个用于搜索键入的单词的辅助方法,类似于C#中的 `StartsWith(string)`。
'查找源中以给定参数开头的单词。
Private Function FindWord(ByVal beginsWith As String) As String
Dim i As Integer
For i = 1 To m_words.Count
If LCase(Left(m_words(i), Len(beginsWith))) = LCase(beginsWith) Then
FindWord = m_words(i)
Exit Function
End If
Next
FindWord = vbNullString
End Function
使用数组时,循环略有不同:
For i = LBound(array) To UBound(array)
'...
Next
----------
一个暂停 `TextBox_Change()` 事件的方法,当按下退格键时:
'暂停Change()事件以允许退格键。
Private Sub AutoTextBox_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
m_ignore = Len(AutoTextBox.Text) > 0 And KeyCode = 8 '退格键
End Sub
----------
结果:
[![自动完成][2]][2]
[1]: https://learn.microsoft.com/en-us/answers/questions/840981/auto-complete-for-textbox-in-wpf-(mvvm)
[2]: https://i.stack.imgur.com/PxBr4.gif
请注意,我已根据您的要求仅翻译了代码部分,没有包含其他内容。
英文:
I was looking for something similar myself today for WPF and bumped into a post on learn.microsoft.com. I translated it from C# to VBA and fixed an issue with the Backspace key that was preventing a letter to be deleted when the key was pressed.
The example uses a hard-coded list of words, but you can modify it to get the data from Excel to fill an array when the form is initialized.
Source: Auto Complete for TextBox in WPF (MVVM)
Private fields and source collection:
Option Explicit
Private m_words As VBA.Collection
Private m_currentInput As String
Private m_currentSuggestion As String
Private m_currentText As String
Private m_selectionStart As Integer
Private m_selectionLength As Integer
Private m_ignore As Boolean
'Initialize source
Private Sub UserForm_Initialize()
Set m_words = New VBA.Collection
Populate
End Sub
Private Sub Populate()
m_words.Add "English"
m_words.Add "Chinese"
m_words.Add "French"
m_words.Add "French one"
m_words.Add "French two"
m_words.Add "Russian"
m_words.Add "Japanese"
End Sub
The Change()
event handler:
'Change()
Private Sub AutoTextBox_Change()
If m_ignore Then Exit Sub
Dim word As String
word = AutoTextBox.Text
If Len(word) > Len(m_currentInput) And word <> m_currentSuggestion Then
m_currentSuggestion = FindWord(word)
If Len(m_currentSuggestion) > 0 Then
m_currentText = m_currentSuggestion
m_selectionStart = Len(word)
m_selectionLength = Len(m_currentSuggestion) - Len(word)
AutoTextBox.Text = m_currentText
AutoTextBox.SelStart = m_selectionStart
AutoTextBox.SelLength = m_selectionLength
End If
End If
End Sub
A helper method to search for the keyed word, similar to the C# StartsWith(string)
.
'Find word in source that starts with given param.
Private Function FindWord(ByVal beginsWith As String) As String
Dim i As Integer
For i = 1 To m_words.Count
If LCase(Left(m_words(i), Len(beginsWith))) = LCase(beginsWith) Then
FindWord = m_words(i)
Exit Function
End If
Next
FindWord = vbNullString
End Function
Using an array, the loop is slightly different:
For i = LBound(array) To UBound(array)
'...
Next
A hack to suspend the TextBox_Change()
event when the Backspace key is pressed:
'Suspend the Change() event to allow the backspace key.
Private Sub AutoTextBox_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
m_ignore = Len(AutoTextBox.Text) > 0 And KeyCode = 8 'Backspace key
End Sub
Result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论