2014-02-21 5 views
1

У меня есть проект Excel 2007 VBA с несколькими пользовательскими формами, один из которых - сборщик дат, содержащий объект Calendar Control 12.0. Сборщик событий активируется всякий раз, когда пользователь нажимает одно из двух элементов управления текстовыми полями в одной из других форм. Я хочу управлять стартовой позицией выбора даты таким образом, чтобы при показании она отображалась в соответствии с тем, какой из элементов управления текстовым полем был нажат.XL VBA Как я могу предотвратить игнорирование свойств .Top и .Left UserForm при первом .Show?

Чтобы сделать это, выбор даты UserForm (frmDatePicker) предоставляет три открытых ВАР: xOffset, yOffset и frmParent. Цель состоит в том, чтобы до frmDatePicker свойства .Top и .Left будут заданы по ссылке на эти три vars, которые сами инициализируются вызывающим суб. (Свойство userform .StartUpPosition также установлено на ноль (т. Е. «Руководство»), чтобы можно было контролировать его начальное положение таким образом.)

Это отлично работает, за исключением случаев, когда отображается первый таймер выбора даты. В первый раз вызывается метод .Show, frmDatePicker не выравнивается с текстовым полем с щелчком. Со второго раза эта проблема исчезает. Код

frmDatePicker «S выглядит следующим образом:

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 и .Left свойства в UserForm_Initialise и UserForm_Activate событий frmDatePicker - как индивидуально, так и в (без разницы)

  • Предзагрузка frmDatePicker перед вызовом моего .Execute функция и не устанавливая позиционные свойства, как описано выше (никакого эффекта)

Я действительно не хочу, чтобы упасть обратно на «быстро показывая то скрывает форму» becau se ... ну, это просто ужасное решение!

Спасибо за чтение! Есть идеи?

ответ

1

Странно, Как вы говорите, что первый раз вокруг установки .Left/Top кажется сбросить/игнорироваться:

SS

Не знаю, почему. Как исправить это, кажется, работает:

If Not frmParent Is Nothing Then 
    Me.StartUpPosition = 0 
    Me.Move frmParent.Left + xOffset, frmParent.Top + yOffset 
End If 
+0

Спасибо Alex! Я забыл о «Переместить» ... Как бы то ни было, я только что вернулся сюда, чтобы опубликовать собственное исправление (которое я все равно сделаю в любом случае для полноты), но у вас меньше kludgey, чтобы вы получили голосование! – blackworx

1

Я отправил этот ответ для полноты только, чтобы предоставить больше информации о том, что на самом деле происходит в данном случае. Исправить Alex K лучше.

Я провел еще несколько испытаний и обнаружил, что только FIRST пишет либо .Left, либо .Top, который сбрасывается/игнорируется.

В моем примере выше, оказалось, что .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, и, предположительно, первая линия может просто установить фиктивное значение, так как оно в любом случае будут проигнорированы. Пока вы устанавливаете его во второй раз, пользовательская форма отображается в нужном месте в первый раз.

 Смежные вопросы

  • Нет связанных вопросов^_^