我有一个包含多个用户表单的Excel 2007 VBA项目,其中一个是包含Calendar Control 12.0对象的日期选择器。只要用户单击其中一个表单上的两个文本框控件之一,就会激活日期选择器。我想控制日期选择器的启动位置,以便在显示时,它与任何单击的文本框控件一致。
为此,日期选择器用户表单(frmDatePicker
)会公开三个公共变量:xOffset
,yOffset
和frmParent
。目的是,在显示frmDatePicker
之前,将通过引用这三个变量来设置其.Top
和.Left
属性,这三个变量本身由调用子初始化。 (userform的.StartUpPosition
属性也设置为零(即“手动”),以允许以这种方式控制其初始位置。)
这完全有效......除了第一次显示日期选择器。第一次调用.Show
方法时,frmDatePicker
与所点击的文本框不对齐。从第二次开始,这个问题就消失了。
frmDatePicker
的代码如下:
Option Explicit
Public InitialDate As Variant
Public xOffset As Double
Public yOffset As Double
Public frmParent As Object
Private DateSelected As Boolean
Function Execute() As Boolean
If Not frmParent Is Nothing Then
Me.StartUpPosition = 0
Me.Left = frmParent.Left + xOffset
Me.Top = frmParent.Top + yOffset
End If
If Not IsDate(InitialDate) Then InitialDate = DateSerial(Year(Now), Month(Now), 1)
calPickDate.Value = InitialDate
calPickDate.ValueIsNull = True
btnCancel.SetFocus
DateSelected = False
Me.Show
Execute = DateSelected
End Function
Private Sub btnCancel_Click()
DateSelected = False
Me.Hide
End Sub
Private Sub calPickDate_Click()
DateSelected = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
DateSelected = False
Me.Hide
End If
End Sub
调用子如下:
Private Sub GetDate(Target As MSForms.TextBox)
With frmDatePicker
.Caption = IIf(Target Is txtDstart, "Start date", "End date")
Set .frmParent = frmAnalysis
.xOffset = Target.Left
.yOffset = Target.Top
.InitialDate = Target.Value
If .Execute() Then Target.Value = Format(.calPickDate, "dd/mm/yyyy")
End With
End Sub
到目前为止我尝试过:
在空白工作簿中使用新的用户窗体进行测试,以确保此行为不是因为我的项目中存在某些瑕疵或损坏(不是)
在.Top
的{{1}}和.Left
事件中设置UserForm_Initialise
和UserForm_Activate
属性 - 单独和同时设置(无差异) )
在调用我的frmDatePicker
函数并设置上述位置属性(无效)之前预加载frmDatePicker
我真的不想回到“快速显示然后隐藏表格”,因为......好吧,这只是一个可怕的解决方案!
感谢阅读!有什么想法吗?
答案 0 :(得分:1)
奇怪,正如你所说,第一次设置.Left/Top
似乎重置/被忽略:
不确定原因。作为修复,这似乎有效:
If Not frmParent Is Nothing Then
Me.StartUpPosition = 0
Me.Move frmParent.Left + xOffset, frmParent.Top + yOffset
End If
答案 1 :(得分:1)
我发布此答案只是为了完整性,以提供有关此实例中实际发生情况的更多信息。 Alex K的解决方案更好。
我做了一些测试,发现只有.Left
或.Top
的FIRST写入被重置/忽略。
在上面的示例中,事实证明.Left
正在被观察重置/忽略,但写入.Top
的值实际上是“坚持”。在我的项目中,默认居中位置所需的垂直位移非常小,所以我没有发现它。
我的解决方案只是将第一个属性设置两次,即
If Not frmParent Is Nothing Then
Me.StartUpPosition = 0
Me.Left = frmParent.Left + xOffset
Me.Left = frmParent.Left + xOffset
Me.Top = frmParent.Top + yOffset
End If
第一行是.Left
还是.Top
并不重要,可能第一行只能设置一个虚拟值,因为无论如何它都会被忽略。只要您再次设置它,用户窗体就会在第一轮显示在所需位置。