Macro takes more time to be executed when activated through button inside sheet in Excel 2019

元气小坏坏 提交于 2019-12-11 14:24:35

问题


I have a macro in excel 2019 which runs in less than 1 second directly through VBE (by pressing F5), or when I configure a button to the macro in the Ribbon (through options>customize ribbon).

However, when I create a button (FormControlButton) inside the sheet area, and associate the same macro to this button, the macro takes at least 7 seconds to run.

In any case, the macro runs normally, without any error message, just the delay when activated through the button inside the sheet. Other macros are slower as well, but this one is the most noticeable.

If this information helps, my macro builds a jagged array with data (~4000 records) that is in another sheet, then sorts the array by bubble/quicksorting (tested both to check if the problem could be here, and it wasn't), then filters it and returns data in a new sheet.

The macros where designed in excel 2010, and I noticed the problem right after our company updated microsoft office from 2010 to 2019. (Our windows was updated the same day from 2007 to 10, but I think the problem is in excel, as I tested it again in some of our PCs that still had office 2010 and the macros worked as fast as if run through VBE). Creating and editing macros is not prohibited by administrators.

Does anybody have an idea of what may be happening?

Adding more information as requested:

I didn't add code because it's not a problem of a specific macro, but I noticed the ones that slowed down the most are the ones that interact with arrays. Besides that, as it didn't happen when I used buttons inside a sheet in office 2010, maybe it's a bug in office 2019.

One thing in common in all my macros is that I follow microsoft's recommendations to speed up macros, and I use this chunk of code in them:

Sub SubName()

Call DeactivateSystemFunctions

'Rest of the code

Call ReactivateSystemFunctions

End Sub

Where

Sub DeactivateSystemFunctions()

Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
Application.ActiveSheet.DisplayPageBreaks = False
Application.EnableEvents = False

End Sub


Sub ReactivateSystemFunctions()

Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.Calculation = xlCalculationAutomatic
Application.ActiveSheet.DisplayPageBreaks = True
Application.EnableEvents = True

End Sub

I don't use .activate or .select in any of my macros, and while formatting I always try to put the max inside a With/End With

Thanks in advance


回答1:


Well, I'm posting an answer to my own question because this is what worked for me, maybe it will work for you too if you encounter the same problem.

My macro was working fine through VBE but taking too many time when activated through a FormControlButton inside my sheet. As @RonRosenfeld suggested, I had to set a timer to each specific part of my code to find where the problem was. I put the timer at the beggining of my code and I had to move the command to stop the timer to each part of it until I found where it was getting slow.

My macro creates a jagged array and then sorts it through Quicksorting, and as the quicksort I made takes more than one criteria to sort, I thought the problem might be occurring there, as it is a recursive method.

But actually the problem was happening when I was printing the results of the sorted jagged array in another worksheet I create using the same macro. I print data this way:

NewSheet.Cells(NewSheetRow, Column1) = SortedArray(RecordNumber)(DesiredInfo1 - 1)
NewSheet.Cells(NewSheetRow, Column2) = SortedArray(RecordNumber)(DesiredInfo7 - 1)
NewSheet.Cells(NewSheetRow, Column3) = SortedArray(RecordNumber)(DesiredInfo14 - 1)

'As my jagged array is built with data from a Source Worksheet:
'RecordNumber is the (Row - 1) in the source worksheet
'DesiredInfoX is the Column in the source worksheet

The problem happened only when printing specific Columns. The source sheet has different columns, each with a different data format. The only data format that slowed things down was strings.

I went to the source worksheet and noticed some problems:

  • As the file went from excel 2000 to 2010 to 2019 and data was not migrated but simply saved from .xls to .xlsm, when I went to the end of the source sheet, I noticed it had only 65536 rows (not 1048576 as expected), but had 16384 columns (last=XFD). It was only happening with the source sheet, which is the one we have more data in. Other sheets in the same workbook had the expected 1048576 rows and 16384 columns.

  • After we started using excel 2019, some of the data that was supposed to be String(Text), was formatted as GENERAL/NUMBER. I can't affirm it was not human error, but our source sheet is filled by macro, not by human, and the macro forces formatting of each data.

What I did to solve the problem: I migrated all data from all sheets, to a new workbook using VBA, not copy/paste. After passing the values to the new source sheet, I forced the formatting of each column. All macros had to be migrated as well.

After that, the FormControlButton inside the sheet is working as fast as activating the macro directly through VBE by pressing F5.

If anybody needs:

'###Timer code
'Got it from https://www.thespreadsheetguru.com/the-code-vault/2015/1/28/vba-calculate-macro-run-time
'Put this part in the beggining of your code
Dim StartTime As Double
Dim SecondsElapsed As Double

'Remember time when macro starts
  StartTime = Timer



'Put this part where you want the timer to stop
'Determine how many seconds code took to run
  SecondsElapsed = Round(Timer - StartTime, 2)

'Notify user in seconds
  MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation


'###Migration macro:
Sub Migrate()

Call DeactivateSystemFunctions

'Source File
Dim XLApp As Object
Dim WbSource As Object
Dim WsSource As Object

Set XLApp = CreateObject("Excel.Application")
XLApp.Visible = False    

Set WbSource = XLApp.Workbooks.Open("C:\FolderFoo\FolderBar\Desktop\SourceFileName.Extension")
Set WsSource = WbSource.Worksheets("SourceWorksheetName")


'Destination File. May be set as source file or if using this workbook by simply:
Dim WsDest As Worksheet    
Set WsDest = ThisWorkbook.Worksheets("DestinationSheetName")


Dim BDR As Long
Dim BDC As Long

Dim UltR As Long
Dim UltC As Long

UltR = WsSource.Cells(Rows.Count, 1).End(xlUp).Row
UltC = WsSource.Cells(1, Columns.Count).End(xlToLeft).Column

For BDR = 1 To UltR

    For BDC = 1 To UltC

        If WsSource.Cells(BDR, BDC) <> vbEmpty Then

            WsDest.Cells(BDR, BDC) = WsSource.Cells(BDR, BDC)

        End If

    Next BDC

Next BDR

'Format your columns as needed    
With WsDest
.Columns(Column1Number).NumberFormat = "0"
.Columns(Column2Number).NumberFormat = "dd/mm/yyyy"
.Columns(Column3Number).NumberFormat = "@"
.Columns(Column4Number).NumberFormat = "@"
.Columns(Column5Number).NumberFormat = "0.000"
End With


WbSource.Close SaveChanges:=False

Call ReactivateSystemFunctions

End Sub


来源:https://stackoverflow.com/questions/57256541/macro-takes-more-time-to-be-executed-when-activated-through-button-inside-sheet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!