2016-07-11 10 views
1

я наткнулся на этом аналогичный вопрос и прочитать ответы: Modeless form that still pauses code executionVBA лучших практики для модулей относительно немодального UserForms

, которые я пытался применить в моей ситуации предложения, предоставленное David Zemens. В моей ситуации я не могу найти подход, который включает предложение г-на Земена, не используя также GoTo.

Мне интересно, есть ли лучшее или более элегантное решение.

Вот набросок того, что я делаю:

У меня есть UserForm с командной кнопкой, с которой начинается выполнение кода, который будет выполнять несколько действий на нескольких рабочих книг Excel. Таким образом, существует несколько блоков кода, и успешное завершение одного блока кода позволяет выполнить последующий блок кода.

В определенный момент, в зависимости от ситуации, код может требует ввода пользователем; в других ситуациях необходимые данные можно получить из Excel. Если требуется ввод данных от пользователя, отображается другой UserForm.

Пользователю может потребоваться просмотреть несколько разных листов Excel перед входом на вход, поэтому UserForm не нужен. Таким образом, код останавливается до тех пор, пока Пользователь не войдет в нужный вход и не щелкнет другой кнопкой Command.

В этот момент у меня возникают проблемы: как возобновить поток программы. Есть ли единственный способ «взять туда, где он остановился», используя инструкцию GoTo? Или есть какой-то способ организовать модули, поэтому есть один согласованный поток программ, определенный в одном месте и не дублированный с того момента, когда может потребоваться ввод пользователя?

+0

Трудно предложить лучший способ организовать свои модули/код без предварительного просмотра ваших модулей/кода :). Другая возможность, конечно же, предусматривает способ (во второй пользовательской форме) для самой программы «выбрать» и привести необходимые рабочие листы для просмотра (например, элемент управления ComboBox, содержащий список всех книг/рабочих листов и т. д.). –

+0

Я бы также предположил, что * идеально * вы должны сделать необходимую проверку * до * для выполнения какого-либо кода - какие условия требуют ручного вмешательства? Проверьте эти условия до того, как код * сделает что-либо и что угодно, и предложите пользователю ввести данные в эту точку, при этом завершая время выполнения. Затем, когда пользователь повторно запускает программу, он не должен требовать добавления пользователя (пользователь, предварительно исправляя недостающую информацию) –

+0

Ну, есть много кода, уже написанных и что каждый блок кода сделал По-видимому, это не связано с общим потоком программы. В принципе, имеется командная кнопка, доступная из листа. Это Click-событие вызывает основную функцию в модуле. Эта основная функция содержит вызовы для других функций. Если вызываемая функция успешно выполняется, то фокус возвращается к основной функции, и выполняется следующая строка кода, которая является вызовом следующей функции. –

ответ

2

Вот моя проблема. Надеюсь, я правильно понял проблему.

Предположения:

  1. Там находятся две формы пользователя.
  2. UserForm1 с кнопкой, чтобы начать обработку.
  3. UserForm2 с кнопкой для подачи промежуточного входа.
  4. Sub внутри модуля для запуска/запуска UserForm1.

VBA Code (для вспомогательной подпрограммы)

Sub LaunchUserForm1() 
    Dim frm As New UserForm1 

    '/ Launch the main userform. 
    frm.Show vbModeless 
End Sub 

VBA код (UserForm1)

Private Sub cmdStart_Click() 
    Dim i  As Long 
    Dim linc As Long 
    Dim bCancel As Boolean 
    Dim frm  As UserForm2 

    '/ Prints 1 to 5 plus the value returned from UserForm2. 

    For i = 1 To 5 

     If i = 2 Then 
      Set frm = New UserForm2 
      '/ Launch supplementary form. 
      frm.Show vbModeless 

'<< This is just a PoC. If you have large number of inputs, better way will be 
' to create another prop such as Waiting(Boolean Type) and then manipulate it as and when User 
' supplies valid input. Then validate the same in While loop>> 

      '/ Wait till we get the value from UserForm2. 
      '/ Or the User Cancels the Form with out any input.    
      Do While linc < 1 And (linc < 1 And bCancel = False) 
       linc = frm.Prop1 
       bCancel = frm.Cancel 
       DoEvents 
      Loop 

      Set frm = Nothing 
     End If 

     Debug.Print i + linc 
    Next 

    MsgBox "User Form1's ops finished." 

End Sub 

VBA код (UserForm2)

Dim m_Cancel  As Boolean 
Dim m_prop1   As Long 

Public Property Let Prop1(lVal As Long) 
    m_prop1 = lVal 
End Property 

Public Property Get Prop1() As Long 
    Prop1 = m_prop1 
End Property 

Public Property Let Cancel(bVal As Boolean) 
    m_Cancel = bVal 
End Property 

Public Property Get Cancel() As Boolean 
    Cancel = m_Cancel 
End Property 

Private Sub cmdlinc_Click() 
    '/Set the Property Value to 10 
    Me.Prop1 = 10 
    Me.Hide 
End Sub 

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) 
    '/ Diasble X button 

    Me.Cancel = True 
    Me.Hide 
    Cancel = True 

End Sub 
0

ИТАК здесь мои мысли.

У вас есть пользовательская форма frmSelectUpdateSheet, которую вы хотите использовать, чтобы пользователь мог выбрать лист, когда лист не может быть определен программным путем.Проблема в том, что если вы делаете .Show vbModeless (что позволяет пользователю перемещаться по рабочему листу/с), то код продолжает выполняться, что приводит к ошибкам или иным нежелательным выводам.

Я думаю, что можно адаптировать метод I described in the previous answer. Тем не менее, это не может быть и речи, если вы не платите мне, чтобы перепроектировать весь ваш код: P

Предполагая, что у вас есть объектная переменная Worksheet (или строка, представляющая имя листа и т. Д.), Которая должна быть (и эта переменная равна Public в области), просто используйте CommandButton в форме, чтобы назначить это на основе выбранного элемента в списке frmSelectUpdateSheet.

Это, вероятно, является более предпочтительным решением для целого ряда причин (не в последнюю очередь пытается избежать применения редизайн для такого рода бахромой случае), таких как:

  • Это сохраняет свою форму vbModal и не мешает пользователю неосторожно манипуляции с листа во время процесса и т.д.

  • Используя этот подход, нить остается с vbModal отображается frmSelectUpdateSheet, и вы будете полагаться на процедуры событий формы для управления потоком процесса/выполнение кода.

  • Должно быть проще (и, следовательно, дешевле) реализовать; независимо от того, делаете ли вы это самостоятельно или выполняете аутсорсинг.

  • Должно быть проще (и, следовательно, дешевле) поддерживать.

сейчас, при ближайшем рассмотрении, это выглядит, как вы уже делаете такого рода подход с обработчиком cmdbtnSelect_Click событий, , который заставляет меня верить, есть родственный/последующий проблема:

Недостаточно имени листа (в списке) для идентификации правильного рабочего листа. Итак, , если пользователю нужна возможность «прокручивать» лист (например, просматривать данные, которые не подходят в окне и т. Д.), А затем добавить несколько кнопок счетчика или другие элементы управления формой, чтобы они могли перемещаться по листу.

+0

Позвольте мне проверить мое понимание: сохранить UserForm в режиме Modal и добавить элементы управления в UserForm, которые позволяют перемещаться по Workbook , У меня есть это право? –

+0

Да использовать события форм и элементы управления, чтобы манипулировать листами –

+0

Хорошо, скажем, ради обсуждения, что я еще не написал весь этот код, - что я на этапе планирования кода, - и я знаю, что при определенном то для получения пользовательского ввода будет отображаться немощный UserForm. Как организовать код? Каким будет подход? Я немного поиграл и, похоже, не могу понять, как это достичь, даже с очень простым кодом. –

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

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