获取两个 VBA 文本框一起滚动
Get two VBA textboxes to scroll together
我有一个宏可以生成两个相关数据的多行文本框(有时长达数百行)。这些框中的文本行数始终相同,每行对应于另一个文本框中的相邻行。我考虑使用两列列表框,但决定使用文本框,以便可以根据用户的需要复制数据 out/highlighted/selected。
我想让它在用户向下滚动时,两个文本框一起滚动(即,行保持向上同步)。
经过大量挖掘和试验,我明白了!通过添加滚动条,我能够使用 ScrollBar_Change()
事件来调整文本框。在我的表单上,我现在有两个 TextBox 和一个 ScrollBar 对象。然后我的用户窗体代码中有一些必要的潜艇:
'This constant affects whether the ScrollBar appears or _
not, as well as some of the movement graphics of the _
ScrollBar.
'This MUST be reset if the TextBoxes are resized
'I made it a UserForm-level Const because I use it _
elsewhere, but it could also live in SetUpScrollBar
Private Const TEXTBOX_MAX_LINES_IN_VIEW as Long = 21
Private Sub SetUpScrollBar()
'I call this whenever I show my Userform (happens after a _
separate macro determines what to put in the TextBoxes). _
It determines whether the ScrollBar should be shown, and _
if so, sets the .Max property so it scrolls in accordance _
to the number of lines in the TextBoxes.
Dim linesInTextBox as Long
With Me.TextBox1
.SetFocus
linesInTextBox = .LineCount - 1
'Need to subtract 1 or you'll get an error _
when dragging the scroll bar all the way down.
End With
'If there are fewer lines than the max viewing area, hide the scroll bar.
Select Case linesInTextBox > TEXTBOX_MAX_LINES_IN_VIEW
Case is = True
ShowScrollBar True
With Me.ScrollBox
.Min = 0 'I believe this is the default, but I set it just in case
.Max = maxLinesInTextBox
.Value = 0
End With
Case is = False
ShowScrollBar False
End Select
End Sub
Private Sub ShowScrollBar(show As Boolean)
'A simple way of showing or hiding the scrollbar
With Me.ScrollBar1
.Enabled = show
.Visible = show
End With
End Sub
Private Sub ScrollBar1_Change()
'When the scrollbar position changes (either by dragging _
the slider or by clicking it), set the CurLine property _
of each TextBox to the current ScrollBar value.
With Me.TextBox1
'Need to set focus to the box to get or adjust the CurLine property
.SetFocus
.CurLine = Me.ScrollBar1.value
End With
With Me.TextBox2
'Need to set focus to the box to get or adjust the CurLine property
.SetFocus
.CurLine = Me.ScrollBar1.value
End With
End Sub
这似乎很适合我的目的。它使我能够保持使用文本框的 text-selecting/copying 优势,同时保持数据同步。
我尚未解决的一些问题:
- 滚动效果很好,但是如果您尝试单击箭头(特别是向与您刚刚滚动的方向相反的方向),则必须单击直到光标到达文本框的顶部。对我来说,这是 21 次点击。有点烦人,但我确信有解决方法。
- 滚动不像普通滚动条那样实时。这意味着您可以拖动滚动条,但在您放手之前它不会更新文本框。
- 如果用户单击进入文本框并开始使用箭头键导航,则这两个框将变得不同步。下次用户单击 ScrollBar 时,它们将重新同步。如果用户尝试 select 比 window 中可见的行多,这将是非常有问题的:一个 TextBox 将在他们拖动 selection 时滚动,但另一个 TextBox 保持原位
我有一个宏可以生成两个相关数据的多行文本框(有时长达数百行)。这些框中的文本行数始终相同,每行对应于另一个文本框中的相邻行。我考虑使用两列列表框,但决定使用文本框,以便可以根据用户的需要复制数据 out/highlighted/selected。
我想让它在用户向下滚动时,两个文本框一起滚动(即,行保持向上同步)。
经过大量挖掘和试验,我明白了!通过添加滚动条,我能够使用 ScrollBar_Change()
事件来调整文本框。在我的表单上,我现在有两个 TextBox 和一个 ScrollBar 对象。然后我的用户窗体代码中有一些必要的潜艇:
'This constant affects whether the ScrollBar appears or _
not, as well as some of the movement graphics of the _
ScrollBar.
'This MUST be reset if the TextBoxes are resized
'I made it a UserForm-level Const because I use it _
elsewhere, but it could also live in SetUpScrollBar
Private Const TEXTBOX_MAX_LINES_IN_VIEW as Long = 21
Private Sub SetUpScrollBar()
'I call this whenever I show my Userform (happens after a _
separate macro determines what to put in the TextBoxes). _
It determines whether the ScrollBar should be shown, and _
if so, sets the .Max property so it scrolls in accordance _
to the number of lines in the TextBoxes.
Dim linesInTextBox as Long
With Me.TextBox1
.SetFocus
linesInTextBox = .LineCount - 1
'Need to subtract 1 or you'll get an error _
when dragging the scroll bar all the way down.
End With
'If there are fewer lines than the max viewing area, hide the scroll bar.
Select Case linesInTextBox > TEXTBOX_MAX_LINES_IN_VIEW
Case is = True
ShowScrollBar True
With Me.ScrollBox
.Min = 0 'I believe this is the default, but I set it just in case
.Max = maxLinesInTextBox
.Value = 0
End With
Case is = False
ShowScrollBar False
End Select
End Sub
Private Sub ShowScrollBar(show As Boolean)
'A simple way of showing or hiding the scrollbar
With Me.ScrollBar1
.Enabled = show
.Visible = show
End With
End Sub
Private Sub ScrollBar1_Change()
'When the scrollbar position changes (either by dragging _
the slider or by clicking it), set the CurLine property _
of each TextBox to the current ScrollBar value.
With Me.TextBox1
'Need to set focus to the box to get or adjust the CurLine property
.SetFocus
.CurLine = Me.ScrollBar1.value
End With
With Me.TextBox2
'Need to set focus to the box to get or adjust the CurLine property
.SetFocus
.CurLine = Me.ScrollBar1.value
End With
End Sub
这似乎很适合我的目的。它使我能够保持使用文本框的 text-selecting/copying 优势,同时保持数据同步。
我尚未解决的一些问题:
- 滚动效果很好,但是如果您尝试单击箭头(特别是向与您刚刚滚动的方向相反的方向),则必须单击直到光标到达文本框的顶部。对我来说,这是 21 次点击。有点烦人,但我确信有解决方法。
- 滚动不像普通滚动条那样实时。这意味着您可以拖动滚动条,但在您放手之前它不会更新文本框。
- 如果用户单击进入文本框并开始使用箭头键导航,则这两个框将变得不同步。下次用户单击 ScrollBar 时,它们将重新同步。如果用户尝试 select 比 window 中可见的行多,这将是非常有问题的:一个 TextBox 将在他们拖动 selection 时滚动,但另一个 TextBox 保持原位