2015-03-27 1 views
0

Я сделал макрос в Excel, который будет в основном передавать все данные из 1 рабочего листа и разделять их туда, где они принадлежат. Иногда, однако, есть неправильное значение, которое необходимо скорректировать вручную (если это будет сделано вручную, оно будет найдено сразу в процессе перенаправления данных на их отдельные листы).Excel макрос для приостановки и возобновления, или вспомнить, где остановлен

Когда такое значение найдено, ячейка рядом с ним помечена (чтобы определить, что это неправильно), предупреждение появляется для пользователя, но я также хотел бы, чтобы код «приостановил», пользователь меняет значения вручную, а затем возобновляет, когда готов, и это часть, я не уверен, как это сделать (pause & резюме).

Полный код операции приведен ниже (есть другой макрос, который подготавливает эти листы, но это не важно сейчас).

Private Sub Zaradi_Click() 
    Dim wb As Workbook 
    Dim ws As Worksheet 
    Dim rngPlan As Range 
    Dim pvtTable As PivotTable 
    Dim pvtField As PivotField 
    Dim pvtItem As PivotItem 
    Dim i As Integer 
    Dim vykon As Long 
    Dim praca As String 
    Dim meno As String 
    Dim er As String 
    Dim errArray(1 To 20) As String 
    Dim mbResult As Integer 
    Dim parySpolu As Integer 

    Set wb = Workbooks("Zoznam plánov") 

    er = "Nesedia páry!" 

    mbResult = MsgBox("Tieto zmeny sú nezvratné. Potvrdte, že túto operáciu si prajete vykona?", _ 
    vbYesNoCancel) 

    Select Case mbResult 

     Case vbYes 

      Workbooks("Kontrola plánov").Sheets("Summary").Activate 

      meno = Workbooks("Kontrola plánov").Sheets("summary").Cells(2, 9) 

      ' zoznam kontrolovanych planov 
      Set rngPlan = Workbooks("Kontrola plánov").Sheets("Summary").Range(Cells(2, 1), Cells(10000, 1).End(xlUp)) 

      For i = 1 To rngPlan.Rows.Count ' pocet riadkov (size) kontrolovanych planov 

       ' hodnota vykonu 
       vykon = Workbooks("Kontrola plánov").Sheets("summary").Cells(i + 1, 6) 
       ' co robil prace 
       praca = Workbooks("Kontrola plánov").Sheets("summary").Cells(i + 1, 4) 

       ' aktivuje pouzivany plan 
       Set ws = wb.Sheets("Plán " & rngPlan(i)) 

       ws.Activate 

       ' prida pracu 
       ws.Cells(10000, 1).End(xlUp).Offset(1) = praca 

       ' prida vykon 
       ws.Cells(10000, 2).End(xlUp).Offset(1) = vykon 

       ' prida meno 
       ws.Cells(10000, 3).End(xlUp).Offset(1) = meno 

       Set pvtTable = ws.PivotTables(1) 
       Set pvtField = pvtTable.PivotFields(1) 

       pvtTable.PivotCache.Refresh 

       For j = 1 To pvtField.PivotItems().Count   

        Set pvtItem = pvtField.PivotItems(j)          
        pvtItem.ShowDetail = False           
        ActiveSheet.PivotTables(1).NullString = "0"          
        If pvtItem.Value = "(blank)" Then 

        Else 
         parySpolu = pvtTable.GetPivotData("Páry", "Práca", pvtField.PivotItems(j)) 
         If parySpolu > ws.Cells(2, 7) Then 
          ws.Cells(j + 1, 11) = er 
          pvtItem.ShowDetail = True 
          MsgBox er 
         Else 
          ws.Cells(j + 1, 11) = "OK" 
         End If        
        End If 
       Next j  
      Next i 

      ' aktivuje sumarizaciu 
      Workbooks("Kontrola plánov").Sheets("summary").Activate 

     Case vbNo 
      Exit Sub 
     Case vbCancel 
      Exit Sub 
    End Select 

    Workbooks("Kontrola plánov").Sheets(1).Activate 
    MsgBox errNumbers 

End Sub 

Часть кода, где находится неправильное значение и выдается предупреждение здесь:

If parySpolu > ws.Cells(2, 7) Then 
    ws.Cells(j + 1, 11) = er 
    pvtItem.ShowDetail = True 
    MsgBox er 
Else 
    ws.Cells(j + 1, 11) = "OK" 
End If 

Я уже были предложения о том, как это сделать. Один из них использовал InputBox, но я думаю, что это не идеально подходит для этой ситуации (так как пользователь предпочел бы проверить все правильно, исходный лист, найти источник проблемы и т. Д.), И поэтому приостановка & возобновления будет лучше, я думаю. Другое предложение было сделать что-то вроде:

Public lastCellChecked As String

Sub Check_Someting() 

    Dim cell As  Excel.Range 
    Dim WS As  Excel.Worksheet 

    If Not lastCellChecked = vbNullString Then Set cell = Evaluate(lastCellChecked) 

    '// Rest of code... 

    '// Some loop here I'm assuming... 
    lastCellChecked = "'" & WS.Name & "'!" & cell.Address 
    If cell.Value > 10 Then Exit Sub '// Lets assume this is classed as an error 
    '// Rest of loop here... 

    lastCellChecked = vbNullString 
End Sub 

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

ответ

0

Excel - это событие, управляемое. Нет события = никаких действий. Итак, в основном, вопрос заключается в том, каким должно быть событие, которое запускает «продолжение» вашего кода.

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

Если вы хотите разрешить пользователю делать изменения на самом листе, то другого события использовать не будет, кроме как поймать событие «Worksheet_Change». Таким образом, в основном, если есть ошибка, требующая коррекции, вам придется остановить/остановить код (и сохранить на каком-то скрытом листе, который требует коррекции ячейки). Впоследствии вы можете использовать

Private Sub Worksheet_Change(ByVal Target As Range) 

'Assuming that you "saved" the last position here: 
'SomeHiddenSheet.Range("A1").value2 = "$D$10" <-- this is the location where an error occurred which needed fixing 

If Intersect(Target, SomeHiddenSheet.Range("A1").Value2) Is Nothing Then 
    'The user did not change the requested cell but another 
Else 
    'The user change the cell 
End If 

End Sub 

Событие, чтобы проверить, была ли изменена ячейка, которую вы запросили. Но с этим решением у вас возникла проблема, что ваш код остановился. Пользователь может изменить ячейку, которую вы попросили изменить. Но нет никакой гарантии. Фактически пользователь может решить изменить другую ячейку или вообще ничего не делать и просто сохранить/закрыть файл. Таким образом, с этим решением вы, вероятно, снова проверите все предыдущие ячейки.

0

Использовать глобальную переменную, например.ProcessPaused As Boolean и:

ProcessPaused = True 
Do While ProcessPaused 
    DoEvents 
Loop 

После того, как вы закончите коррекции значения а

Sub corrected() 
    ProcessPaused = False 
End Sub 

позволит макросу продолжить.

Реализовано в вашем случае это будет выглядеть следующим образом:

If parySpolu > ws.Cells(2, 7) Then 
    ws.Cells(j + 1, 11) = er 
    pvtItem.ShowDetail = True 
    MsgBox er 
    ProcessPaused = True 
    Do While ProcessPaused 
     DoEvents 
    Loop 
Else 
    ws.Cells(j + 1, 11) = "OK" 
End If 

И, конечно, вы должны поместить огромную кнопку:

Sub PokracovatVProcese_Click() 
    ProcessPaused = False 
End Sub 
+0

Ваш макрос практически остановится, пока вы не активируете продолжение, запустив * corrected() *, который также может быть нажатием кнопки или событием изменения рабочего листа. Я предполагаю, что вам может потребоваться найти значение в другом месте/проверить с другими значениями. Убедитесь, что вы включили обновление экрана (в заданном макросе он не отключен, поэтому это не имеет значения). – user3819867

0

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

Если у вас проблемы с производительностью (скажем, потому что у вас есть куча данных внутри), вам может понадобиться оптимизировать код. (!)

Так что, я бы предпочел, чтобы вы остановить выполнение макроса при неисправностях с сообщением предупреждения пользователя о нежелательных данных, или - лучше - убедитесь, что ошибка проверяется перед тем проблема возникает ,

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