How to prevent a macro from freezing / turning white the Excel window?

前端 未结 1 1779
醉梦人生
醉梦人生 2021-02-04 22:38

So at work I am working on a macro/UserForm in Excel for someone. It works great (I think) and does exactly what it needs to do and takes under 1 minute to run, going through ~7

1条回答
  •  孤独总比滥情好
    2021-02-04 23:19

    As @stuartd mentioned in the comments, DoEvents will probably allow the user to interact with Excel while the macro is running, and prevent Excel from becoming unresponsive.

    An alternative approach is to speed up your code, so that it finishes before the user has reason to believe that it has crashed. In this vein, here are some suggestions:

    1. Turn off Screen Updating: It is a lot of work for Excel to render the screen. You can free those resources to work on what you need done by adding Application.ScreenUpdating = False to the beginning of your code, and Application.ScreenUpdating = True to the end.

    2. Turn off Calculations: If you have a lot of formulas running, this can slow down what happens when you place a value into the workbook, as it needs to recalculoate. My preferred way of dealing with this is to store the current calculation setting, turn off calculations, and then restore the original setting at the end.

    Dim Calc_Setting as Long
    Calc_Setting = Application.Calculation
    Application.Calculation = xlCalculationManual
    'Your code here
    Application.Calculation = Calc_Setting
    
    1. Use Worksheet Variables: You keep accessing your Worksheets by name. For repeated access, it should be faster to store that in a variable. Along with this, don't use Activate or Select. Fully reference you calls to Cells, so that it accesses the right worksheet.

    Dim oldsheet as Worksheet, newsheet as Worksheet
    Set oldsheet =  Worksheets(CStr(oldsheetname))
    Set newsheet =  Worksheets(CStr(newsheetname))
    oldsheet.Cells(place, x3) = ...
    
    1. Use Variant Arrays: This should speed up your code the most, but also has a caveat. Excel and VBA are slow when they interact. Within your inner loop, VBA is accessing Excel 7 times. By pulling those interactions out of the loops, we can achieve a serious performance boost. The issue is that reading/writing arrays to Excel Ranges is still bound by the 2003 size limits (65536 rows, ...). If you expect to have more data than this, you will need to do some gymnastics to make it work.

    Dim inVal as Variant, Output as Variant
    
    inVal = Range(oldsheet.Cells(1,x1-2),oldsheet.Cells(x2+3-x1,y)).Value
    redim output(1 to (x2-x1) * (y-x3) + 2, 1 to x3+2)
    'These numbers are not tested, you should test.
    
    'Loops to fill output.  This will need to be 1 entry at a time.
    
    newsheet.Cells(x1,x1).Resize(Ubound(output,1), Ubound(output,2)).Value
    

    0 讨论(0)
提交回复
热议问题