如何正确alignment活动单元格旁边的UserForm?

我有一个MonthView的UserForm,当我单击指定的单元格区域时,它会成功打开, 这个SO线程给了我基本的脚本。 它的function,但它似乎并没有把我所期望的UserForm。

这里是当前脚本(我已经放在一个特定的工作表中)来打开用户窗体,当我点击区域B3:C2000任何单元格时B3:C2000

 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Set oRange = Range("B3:C2000") If Not Intersect(Target, oRange) Is Nothing Then frmCalendar.Show frmCalendar.Top = ActiveCell.Offset(0, 0).Top frmCalendar.Left = ActiveCell.Offset(0, 1).Left End If End Sub 

问题1:我有UserForm StartUpPosition属性设置为0 - Manual – 是否正确?

问题2:当我单击指定范围内的任何单元格时,第一次打开工作簿后,UserForm总是在屏幕的最左上angular打开。 为什么?

问题3:当我单击指定范围内的任何单元格时,对于第一个单元格之后的任何单击,用户窗体相对于前一个活动单元格而不是我刚刚单击的单元格打开。 我怎样才能打开它相对于刚刚点击的单元格,而不是相对于以前的活动单元格?

问题4:为什么看起来alignmentUserForm的底部而不是顶部?

在我执行以下步骤之后:
1 – 点击单元格C15
2 – 用户窗体打开
3 – closures用户窗体
4 – 点击单元格16
5 – UserForm打开

这就是我所看到的:

原始结果

编辑:这是实施J. Garth的解决scheme(并将偏移属性更改为(0,2)后的结果:

正确的结果

问题1:我有UserForm StartUpPosition属性设置为0 – 手动 – 是否正确? 是的,这是正确的。 在下面的代码中,我在代码中设置了这个属性。

问题2:当我单击指定范围内的任何单元格时,第一次打开工作簿后,UserForm总是在屏幕的最左上angular打开。 为什么? 我想这个问题的答案与问题#3有些相关。 这似乎是窗体打开的默认位置。您现在有代码的方式,试图在Worksheet_SelectionChange事件中设置窗体顶部和左侧坐标不起作用,因为坐标实际上从未设置。 坐标的设置需要移动到用户表单初始化事件。

问题3:当我单击指定范围内的任何单元格时,对于第一个单元格之后的任何单击,用户窗体相对于前一个活动单元格而不是我刚刚单击的单元格打开。 我怎样才能打开它相对于刚刚点击的单元格,而不是相对于以前的活动单元格? 这个问题也与代码在错误的地方有关。 如上所述,协调设置需要在用户表单初始化事件中进行。 至于为什么它引用了前一个活动单元格,我猜测活动单元格在工作表select更改事件完成之后才真正被更改。 因此,由于您正在尝试设置此事件中的坐标(即 – 在事件结束之前),您将获得以前激活的单元格。 再次,将代码移动到正确的位置可以修复此问题。

问题4:为什么看起来alignmentUserForm的底部而不是顶部? 当涉及到单元格(范围)与用户表单时,“顶部”的定义似乎有所不同。 单元格的顶部从第一行开始测量,而用户窗体的顶部似乎是从Excel应用程序的顶部开始测量的。 所以换句话说,如果activecell.top和userform.top都等于144,它们将在屏幕上的不同位置。 这是因为活动单元格的顶部从Excel电子表格中的第一行开始向下144个点,而用户窗体的顶部从Excel应用程序的顶部向下144个点(即 – Excel窗口的顶部),这是较高的因为起始点(Excel窗口的顶部)高于activecell.top(电子表格中的第一行)的起始点。 我们可以通过将userform的高度加上活动单元格的高度添加到顶部坐标来进行调整。

工作表模块代码

 Private Sub Worksheet_SelectionChange(ByVal target As Range) Dim oRange As Range Set oRange = Range("B3:C2000") If Not Intersect(target, oRange) Is Nothing Then frmCalendar.Show End If End Sub 

用户表单代码

 Private Sub UserForm_Initialize() With Me .StartUpPosition = 0 .Top = ActiveCell.Top + ActiveCell.Height + .Height .Left = ActiveCell.Offset(0, 1).Left End With End Sub