在一个文本框中的自动完成 – VBA

huangapple go评论74阅读模式
英文:

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

&#39;Initialize source
Private Sub UserForm_Initialize()
    Set m_words = New VBA.Collection
    Populate
End Sub

Private Sub Populate()
    m_words.Add &quot;English&quot;
    m_words.Add &quot;Chinese&quot;
    m_words.Add &quot;French&quot;
    m_words.Add &quot;French one&quot;
    m_words.Add &quot;French two&quot;
    m_words.Add &quot;Russian&quot;
    m_words.Add &quot;Japanese&quot;
End Sub

The Change() event handler:

&#39;Change()
Private Sub AutoTextBox_Change()

    If m_ignore Then Exit Sub
    
    Dim word As String
        word = AutoTextBox.Text
    
    If Len(word) &gt; Len(m_currentInput) And word &lt;&gt; m_currentSuggestion Then
        
        m_currentSuggestion = FindWord(word)
        
        If Len(m_currentSuggestion) &gt; 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).

&#39;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)
    &#39;...
Next

A hack to suspend the TextBox_Change() event when the Backspace key is pressed:

&#39;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) &gt; 0 And KeyCode = 8 &#39;Backspace key
End Sub

Result:

在一个文本框中的自动完成 – VBA

huangapple
  • 本文由 发表于 2023年5月25日 20:45:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332420.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定