简体   繁体   中英

Excel goes into a “not responding” mode when i run my vba code. Is this ok? is there a way to eliminate this?

When I click the button to run my code I get the blue loading circle and if I wait about 150s my code will run, sometimes going into "not responding" mode, and everything is outputted correctly. But if I click the button to start my code and wait 10s and then click the window and force it into "not responding" mode my code will finish with all the correct output in about 30s.

Option Explicit
Option Base 1
Private Sub CommandButton1_Click()
    Dim loadtypemax As Single, column As Single, row As Single
    Dim loadtype As String, number As String
    Dim loadcombosmax As Single

    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    loadtypemax = ((Cells(Rows.count, "L").End(xlUp).row))
    loadcombosmax = ((Cells(Rows.count, "E").End(xlUp).row))

    column = 6
    For row = 2 To loadcombosmax
        If Cells(row, column) > 0 Then
            number = Cells(row, column)
            loadtype = Cells(row, (column - 2))

            If number = "" Then
            ElseIf number > 0 Then
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 1) = "Load"
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 2) =
                ActiveWorkbook.Worksheets("Load Cases").Cells(row, column).Value
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 4) = "Title"
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 5) =
                ActiveWorkbook.Worksheets("Load Cases").Cells(row, column - 4).Value
            End If

        ElseIf Cells(row, column) = "" Then
        End If

        If Cells(row, column) > 0 Then
            Call LRFD(loadtype, number, loadcombosmax)
        End If

    Next row
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

End Sub

Sub LRFD(loadtype As String, number As String, loadcombosmax As Single)
    Dim countrow As Single, countcolumn As Single, row As Single, column As Single


    Application.Calculation = xlCalculationManual
    Worksheets("STAADloadcombos").Activate

    countrow = ActiveWorkbook.Worksheets("LRFD").Cells(Rows.count,
    "A").End(xlUp).row
    countcolumn = (loadcombosmax - 1) * 2

    For row = 1 To countrow
        For column = 4 To countcolumn Step 2
            If loadtype = ActiveWorkbook.Worksheets("LRFD").Cells(row, column).Value
            Then
            Call STAADloadcombos(column, number, countrow, countcolumn, row)
        End If
    Next column
Next row

Application.Calculation = xlCalculationAutomatic

End Sub

Sub STAADloadcombos(column As Single, number As String, countrow As Single, countcolumn As Single, row As Single)
    Dim r As Integer, rowrow As Single, c As Integer
    Dim rr As Single

    Application.Calculation = xlCalculationManual

    r = row * 2
    rowrow = r - 1

    ActiveWorkbook.Worksheets("STAADloadcombos").Cells(rowrow, 3) =
    ActiveWorkbook.Worksheets("LRFD").Cells(row, 1).Value
    ActiveWorkbook.Worksheets("STAADloadcombos").Cells(rowrow, 2) =
    ActiveWorkbook.Worksheets("LRFD").Cells(row, 2).Value
    ActiveWorkbook.Worksheets("STAADloadcombos").Cells(rowrow, 1) = "Load Comb"

    For c = 1 To countcolumn Step 2
        If ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) = "" Then
            ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) = number
            c = countcolumn
        End If
    Next c

    For c = 2 To countcolumn Step 2
        If ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) = "" Then
            ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) =
            ActiveWorkbook.Worksheets("LRFD").Cells(row, column - 1).Value
            c = countcolumn
        End If
    Next c

    Application.Calculation = xlCalculationAutomatic

End Sub

Private Sub CommandButton2_Click()

    Worksheets("STAADloadcombos").Range("A1:BA500").ClearContents
    Worksheets("STAADloadtypes").Range("A1:BA500").ClearContents

End Sub

Are there any ways I can clean up my code to make it run faster? I read about the screenupdating and calculation application commands and put them in but they didn't seem to spend anything up. Did I put them in correctly?

Yes, this is normal.

Excel and VBA are single-threaded, meaning only one instruction can ever be executed at any given time. This means when Excel is busy executing inefficient VBA code, it can't respond to application events such as the user clicking somewhere or activating another worksheet.

You can add DoEvents calls in strategic places in your code to give Excel a chance do execute handlers for other events; your code will resume at the next instruction and Excel will appear more responsive.

However it will also make your code execute slower, since DoEvents essentially allows other code to run - and while that other code is running, your code is essentially put on hold.

Moreover , allowing Excel to respond to user actions can have disastrous consequences on code that's written against ActiveSheet (implicitly or explicitly) - because you don't know whether the ActiveSheet will be the same before vs. after DoEvents returns.

Toggling Application.ScreenUpdating , Application.EnableEvents and Application.Calculation off, contrary to the popular belief, does not speed up your code . It merely cuts whatever other code can execute in response to your actions.

For example whenever you write into a cell, Excel evaluates whether that cell had dependant cells, and then recalculates these cells: turning off automatic calculation prevents that. Excel also fires a Worksheet.Change event on that modified worksheet, and a Workbook.WorksheetChange event on that workbook - if there's VBA code handling these events, it will be invoked. Turning off EnableEvents prevents that. Excel also repaints its UI every time: turning off ScreenUpdating prevents that. The net result is that your code indeed completes faster, but it's not any more efficient than it was before.

Changing your code to be more efficient would be too broad for this site. Present your code to reviewers on Code Review Stack Exchange for that.

I been tried with the Application.ScreenUpdating, Application.EnableEvents, Application.Calculation, DoEvents and Application.Wait (Now + TimeValue("0:00:10")), and unfortunately the lasted options can not to resolve that problem, looking at the Microsoft WebPage say me if a program say me "Not Responding" is

  1. For Security reasons
  2. Because is too heavy or complicated
  3. Because the program don´t sent any FeedBack to user about to do.

So, In my case I tried showing and MsgBox to user with the finality to provide a FeedBack for the Win10 operative system and the customer, but is so boring that the user click yes, yes, yes, yes, ok, ok, ok, ok and viewing on others forums about VBA for MsgBox (automatly close), they suggest me that code CreateObject("WScript.Shell").PopUp "Please Wait", 1 and tada!! I going to stop see the "Not Responding Message", and if the user don´t to press any click or button for disable the message don´t worry the program going to execute after the message close after 1 second in my case this solve me a lot of problems, i hope to help you, good lucky.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM