[Last Call] Learn how to a build a cloud-first strategyRegister Now

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 399
  • Last Modified:

vba or api hilite partial text in a textbox and place the text cursor (not the mouse) after the hilited text

Dear Experts,

I am taking a multi-line textbox in access (I cannot add a rich text box control to the form, access says it cannot add it, so this is a regular textbox) and when the user types in something on the first line and then types in something on the second line that matches the first I want it to automatically fill in the first word (the one from line1) on the second line, hilite it in case the user is trying to type something else, and then put the cursor position for the textbox right after the hilited text.

So, if user types this on the first line:
And then on the second line types
I want it to automatically fill in SMITH on the second line, hilite SMITH and then put the caret right next to it on the right (right now it is putting it on the left)

The simple answer would be to simply set the selstart to the length of the line, but doing so unhilites the text, I will post my partially working code below in the code section..

Note: I am willing to use windows API calls if that's what it takes to do this.

Thanks! ~Michael
Private Sub Seller_KeyUp(KeyCode As Integer, Shift As Integer)
    Dim myText$, buyerText$, currKey$
    currKey = Chr(KeyCode): myText = UCase(Nz(Me.Seller.text)): buyerText = UCase(Nz(Me.Buyer))
    If InStr("ABCDEFGHIJKLMNOPQRSTUVWXYZ ", UCase(currKey)) > 0 Then
        If InStr(myText, vbCr) > 0 Then
            Dim line2$, line1$, line1_word1$, line2_word1$, newText$, newPos As Integer
            line1 = firstLine(myText)
            line1_word1 = firstWord(myText)
            line2 = secondLine(myText)
            line2_word1 = firstWord(line2)
            If InStr(line2, " ") > 0 Then Exit Sub 'must be still typing the first word of the second line
            If Len(line2_word1) < 2 Then Exit Sub
            If line2_word1 = Left(line1_word1, Len(line2_word1)) Then
                'words are matching, insert word and hilite just that word
                newText = line1 & vbCrLf
                newPos = Len(newText) + 1
                newText = newText & line1_word1 & " "
                Me.Seller = newText
                Me.Seller.SelStart = newPos
                Me.Seller.SelLength = Len(line1_word1) + 1	'now the cursor is on the left of the hilited text (selstart) which is wrong
            End If
       end if
end sub

'Other supporting functions

Public Function firstLine(ByVal someStr$) As String
    firstLine = myTrim(someStr, vbCrLf)
    If InStr(firstLine, vbCrLf) = 0 Then Exit Function
    firstLine = Left(firstLine, InStr(firstLine, vbCrLf) - 1)
End Function

Public Function secondLine(ByVal someStr$)
    'returns "" if there is no 2nd line
    Dim linePos As Integer
    linePos = InStr(someStr, vbCrLf)
    If linePos = 0 Then Exit Function
    secondLine = Mid(someStr, linePos + 2)
    linePos = InStr(secondLine, vbCrLf)
    If linePos > 0 Then secondLine = Mid(secondLine, 1, linePos - 1)
End Function

Public Function firstWord(ByVal someStr$) As String
    firstWord = Trim(someStr)
    If InStr(firstWord, " ") = 0 Then Exit Function
    firstWord = Left(firstWord, InStr(firstWord, " ") - 1)
End Function

Open in new window

1 Solution
OK, my question is why do you care where the caret is?  It seems you would want to be storing each line of text in an array or something after the user presses enter (which you could check for in the keypress or keyup event)...at that point add to the array or string collection.
Then as they type, trap each char and remember what they have typed so far on that line by storing it in a variable....trap it on keydown, keypress or keyup, depending on how you want it to behave.  compare to the array. If it meets a condition there, replace that text with whatever it matches, keep doing this until a key comes in that makes it a unique word. At that point, deselect it all, add the string you've been tracking + the char they just pressed and set selstart to the end of that line.

Isn't this what you are after?
If not, here is an article on getting and setting the textbox caret from vb.net:


It uses SendMessage,GetCaretPos, and SetCaretPos API calls - note you will need the pre vb.net version of DECLARES for use in VBA
this link uses an html tag in a rich texbox....see if it helps for what you want it to do:
Fill in the form and get your FREE NFR key NOW!

Veeam is happy to provide a FREE NFR server license to certified engineers, trainers, and bloggers.  It allows for the non‑production use of Veeam Agent for Microsoft Windows. This license is valid for five workstations and two servers.

Helen FeddemaCommented:
I would suggest a completely different approach.  Make a table to store the values that are now typed into lines of the multi-line textbox, and display it in a datasheet subform.  This is better from the point of view of normalization, and much easier to work with besides.
JeffreyDurhamAuthor Commented:
No worries Jim Dettman, my first name is Jeffrey, and my second name is Michael. So for work, money, taxes, etc, I go by Jeffrey, but I otherwise go by Michael, which is why I will end comments or letters or whatever with Michael. But yeah, it's just me.

Actually I like your idea for how to track it using an array or whatnot. The only reason I wanted the caret at the end is if the user liked the word and kept typing, I wanted them to be able to hit the arrow key once to get over and then keep typing, or I was debating trapping the space, and if the word is good just keep going. But basically, the reason was the cursor was way to the left of the word and that was awkward for entering data and stuff. Umm, lemme toy with your idea and if that doesn't go I'll do the API. Thanks!
JeffreyDurhamAuthor Commented:
For this field I really only need to deal with two lines of text, so I don't think it's really necessary to make a table to hold the data. I think just holding the text in memory wouldn't be a big deal since it's so little, and would probably be faster.
Well yeah... You could still trap the tab key, deselect, move caret to the end.  
JeffreyDurhamAuthor Commented:
Thank you SStory!

Yep, keeping it in memory and altering it to fit is an excellent approach. Thanks for the good idea! Also, thanks for the api info too, now I know everything I wanted to know!

Hey you are welcome.

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now