【发布时间】:2016-11-21 12:30:45
【问题描述】:
任务:我的目标是在双击后从UserForm 中的多行TextBox 中提取突出显示的单词。
Used Properties:虽然通过TextBox 属性.SelStart 和.SelLength 突出显示给定的字符串位置绝对没有问题,但反过来就不那么容易了:a用户DblClick 突出显示整个字符串,但Excel 不会像人们假设的那样在突出显示文本的起始位置重置.SelStart 值,.SelStart 值仍然存在于用户双击的位置。
我的问题:是否有可能直接捕捉应用程序设置的突出显示的文本起始位置?
我的解决方法:我将演示一个非常简单的解决方法来重建突出显示的单词,只需检查以下和前面的例如实际点击位置左右各20个字母(当然,也可以使用正则表达式并细化示例代码):
Private Sub TextBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim sTxt As String, sSel As String ' edited due to comment below
Dim selPos As Long, i As Long, i2 As Long ' "
TextBox1.SetFocus
' this is the User's DblClick Position,
' but not the starting Position of the highlighted Word
' after DblClick
selPos = TextBox1.SelStart
sTxt = Replace(Replace(TextBox1.Text, vbCrLf, vbLf), "\", ".")
If TextBox1.SelLength > 0 Then
sSel = TextBox1.SelText
Else
sSel = Mid(sTxt, selPos + 1, 5)
' check the preceding 20 letters
i = selPos
For i = selPos To (selPos - 20) Step -1
If i < 0 Then Exit For
Select Case Left(Mid(sTxt, i + 1), 1)
Case " ", vbLf, ":", ".", "?", """", "'", "(", ")"
sSel = Mid(sTxt, i + 2, selPos - i)
Exit For
End Select
Next i
' check the following 20 letters
i2 = selPos
For i2 = selPos To (selPos + 20)
If i2 > Len(sTxt) Then Exit For
Select Case Left(Mid(sTxt, i2 + 1), 1)
Case " ", vbLf, ":", ".", "?", """", "'", ")", "("
sSel = Replace(Mid(sTxt, i + 2, i2 - i - IIf(i = i2, 0, 1)), vbLf, "")
Exit For
End Select
Next i2
End If
' Show the highlighted word
Me.Label1.Text = sSel
End Sub
在 UserForm 代码模块中找到解决方案的附加说明(感谢 @Rory)
为了真正从多行文本框中获得双击突出显示的字符串,您需要三个步骤来解决时间问题:
- 由于文本框位置属性
SelStart和SelLength尚未在DblClick事件中设置, 必须将True分配给布尔变量/标记 (bCheck)。 - 检查
bCheck后,使用MouseUp事件获取最终位置属性。 -
为了正确计数,有必要删除例如
vbLf在 MS 系统上的 回车Chr(13)(=vbCr) 和 换行符Chr(10)(=vbLf) 对中。警告: 请注意,AFAIK Mac 系统仅使用换行符
Chr(10)作为结束符号,因此 IMO 在这种情况下可以省略替换。
最终代码
Option Explicit
Private bCheck As Boolean
' [1] assign True to boolean variable
Private Sub TextBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
bCheck = True ' set marker to True
End Sub
Private Sub TextBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If bCheck Then
bCheck = False ' reset marker to False
' [2][3] extract the highlighted doubleclicked word from multi-line textbox
MsgBox Trim(Mid(Replace(Me.TextBox1.Text, vbLf, ""), Me.TextBox1.SelStart + 1, Me.TextBox1.SelLength))
End If
End Sub
【问题讨论】:
-
您需要修正您的声明...必须为每个变量分配一个类型,否则默认情况下它将是一个 Variant。 (即-sTxt 不是字符串,i 不是整数)无需在 For 循环之前将变量设置为 For 循环的开头。
-
感谢您的评论,但我认为第 2 行和第 3 行中的 Dim sTxt As String, Dim i as Long 就足够了。在这些代码行之后我应该做什么?
-
Dim sTxt as String是正确的,但这不是你所拥有的。Dim sText, sSel as String将 sSel 声明为 String 并将 sText 声明为 Variant。 -
谢谢,我确实学到了一些东西。
标签: vba excel textbox userform