0

我在 Excel 2019 中有一个宏,它直接通过 VBE(按 F5)或当我在功能区中为宏配置按钮时(通过选项>自定义功能区)在不到一秒的时间内运行。

当我在工作表区域内创建一个按钮(FormControlButton)并关联宏时,至少需要七秒钟。

宏运行时没有任何错误消息。其他宏也较慢,但这个是最引人注目的。

我的宏用另一张表中的数据(约 4000 条记录)构建了一个锯齿状数组,然后通过冒泡/快速排序对数组进行排序(测试两者是否可能存在问题,但不是),然后过滤它并在新工作表中返回数据。

在 Excel 2010 中设计的宏,我在我们公司从 2010 年到 2019 年更新 Microsoft Office 后立即注意到了这个问题。(Windows 从 2007 年到 10 年在同一天更新,但我认为问题出在 Excel 中,因为我对其进行了测试再次在仍然具有 Office 2010 并且宏的工作速度与通过 VBE 运行一样快的一些 PC 中)。管理员不禁止创建和编辑宏。

根据要求添加更多信息:

我没有添加代码,因为这不是特定宏的问题,但我注意到最慢的是与数组交互的那些。除此之外,由于我在 Office 2010 中使用工作表内的按钮时没有发生这种情况,可能是 Office 2019 中的一个错误。

我所有宏的一个共同点是我遵循微软的建议来加速宏,我使用了这段代码:

Sub SubName()

    Call DeactivateSystemFunctions

    'Rest of the code

    Call ReactivateSystemFunctions

    End Sub

在哪里

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

我不使用.activate.select在我的任何宏中,并且在格式化时,我总是尝试将最大值放在 With/End With 中。

4

2 回答 2

0

我的宏通过 VBE 运行良好,但通过工作表内的 FormControlButton 激活时花费了太多时间。正如@RonRosenfeld 建议的那样,我必须为代码的每个特定部分设置一个计时器,以找出问题所在。我将计时器放在代码的开头,我不得不将停止计时器的命令移动到它的每个部分,直到我发现它变慢了。

我的宏创建了一个锯齿状数组,然后通过快速排序对其进行排序,并且由于我所做的快速排序需要多个标准进行排序,我认为问题可能在那里发生,因为它是一种递归方法。

但实际上,当我在使用相同宏创建的另一个工作表中打印排序锯齿状数组的结果时,问题就发生了。我这样打印数据:

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

该问题仅在打印特定列时发生。源工作表有不同的列,每列都有不同的数据格式。唯一减慢速度的数据格式是字符串。

我去了源工作表并注意到一些问题:

  • 由于文件从 excel 2000 到 2010 到 2019 并且数据没有迁移,而只是从 .xls 保存到 .xlsm,当我转到源工作表的末尾时,我注意到它只有 65536 行(不是预期的 1048576) , 但有 16384 列 (last=XFD)。它只发生在源工作表上,这是我们拥有更多数据的工作表。同一工作簿中的其他工作表具有预期的 1048576 行和 16384 列。

  • 在我们开始使用 excel 2019 之后,一些应该是 String(Text) 的数据被格式化为 GENERAL/NUMBER。我不能肯定这不是人为错误,但我们的源表是由宏而不是人为填充的,并且宏强制每个数据的格式。

我为解决问题所做的工作:我将所有工作表中的所有数据迁移到使用 VBA 的新工作簿,而不是复制/粘贴。将值传递给新的源工作表后,我强制格式化每一列。所有宏也必须迁移。

之后,工作表内的 FormControlButton 的工作速度与通过按 F5 直接通过 VBE 激活宏一样快。

如果有人需要:

'###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
于 2019-08-05T15:28:32.220 回答
-1

TLDR:我遇到了同样的问题,我认为是鼠标指针的问题。

我的解决方案:

Dim Cursor As XlMousePointer
Cursor = Application.Cursor
Application.Cursor = xlWait

-- YOUR CODE HERE --

Application.Cursor = Cursor

长版:我在我的一个宏中注意到了一个类似的问题,它似乎发生在单独操作大量单元格时(即循环通过数百或数千个单元格并更改它们的值)。

当您从 FormButton 或 ActiveX Button 启动鼠标指针时,您可能会注意到鼠标指针的变化,但是当您从 VBE 启动宏时,它不会这样做。

在我的例子中,如果我将焦点从 Excel 窗口上移开,宏甚至开始运行得更快——就像将鼠标移到 Windows 开始菜单按钮或 Windows 任务栏中的应用程序上一样简单,可以提高宏的性能。

我没有进一步研究,但我得出结论,鼠标指针的不稳定变化实际上是性能的杀手,所以我做了以下事情:

在更改单元格之前,我将鼠标指针设置为“默认”以外的其他值。当你这样做时,它会保持在那里并且在你操作单元格时不会改变。之后,我将鼠标指针设置为它在宏之前的任何状态。

从那以后我没有同样的问题。

于 2020-10-05T19:32:16.880 回答