我有一个简单的宏,我根据结构级别(1-8)对行进行分组,即创建大纲。当我在有 76k 行的 Excel 上运行宏时,需要一些时间,但可以完成任务。但之后,如果运行宏的行数增加,就会挂起 excel,我必须从任务管理器中终止该进程。
Sub GroupReport()
'Define Variables
Dim StartCell As Range
Dim StartRow As Long
Dim LevelCol As Integer
Dim LastRow As Long
Dim CurrentLevel As Integer 'iterative counter'
Dim i As Long
Dim j As Integer
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Set StartCell = Cells(5, 1)
StartRow = StartCell.Row
LevelCol = StartCell.Column
LastRow = ActiveSheet.UsedRange.Rows.Count
' Cells.ClearOutline
'inarr = Range(Cells(5, 1), Cells(LastRow, 19))
For i = StartRow To LastRow
CurrentLevel = Cells(i, LevelCol)
Rows(i).Select
For j = 1 To CurrentLevel - 1
On Error Resume Next
Selection.Rows.Group
Next j
Next i
Application.ScreenUpdating = True
End Sub
我尝试关闭手动计算和屏幕更新来提高性能,但没有多大帮助。我尝试将数据复制到变量数组,但无法理解如何循环它。
我真的很感激任何建议/帮助,使其适用于 4L 的 excel 并提高性能。
我会限制与工作表的交互数量,例如Select方法、实际行数而不是UsedRange.Rows.Count,并使用数组来加快处理速度。这是对您的代码的一些接触。
子 My2ndAdjOptimized()
Dim ws As Worksheet
Dim StartRow As Long, LastRow As Long
Dim LevelCol As Long
Dim CurrentLevel As Integer
Dim i As Long, j As Long
Dim LevelArr As Variant
' Define the working sheet
Set ws = ThisWorkbook.ActiveSheet
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
' Start the timer
Dim StartTime As Double
StartTime = Timer
StartRow = 5
LevelCol = 1
LastRow = ws.Cells(ws.Rows.Count, LevelCol).End(xlUp).Row
' Read data into an array
LevelArr = ws.Range(ws.Cells(StartRow, LevelCol), ws.Cells(LastRow, LevelCol)).Value
' Iterate over rows to group them
For i = 1 To UBound(LevelArr, 1)
CurrentLevel = LevelArr(i, 1)
For j = 1 To CurrentLevel - 1
ws.Rows(StartRow + i - 1).Group
Next j
Next i
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
' Display runtime
MsgBox "Runtime: " & Round(Timer - StartTime, 2) & " seconds"
结束子
我使用 Python 中的 openpyxl 库实现了相同的逻辑,并观察到性能的大幅提升。对于 10,000 行的数据集,该操作只需 1.77 秒即可完成。 这是我的Python代码。
import openpyxl
from time import time
def group_rows_based_on_levels(filename):
# Load workbook and select active sheet
wb = openpyxl.load_workbook(filename)
ws = wb.active
start_time = time()
start_row = 5
level_col = 1
# Determine the last row with data in the level column
last_row = ws.max_row
for i in range(start_row, last_row + 1):
current_level = ws.cell(row=i, column=level_col).value
if current_level is not None:
for _ in range(current_level - 1):
ws.row_dimensions[i].outlineLevel += 1
ws.row_dimensions[i].hidden = True
# Save the changes
wb.save(filename)
runtime = round(time() - start_time, 2)
print(f"Runtime: {runtime} seconds")
# Example usage
group_rows_based_on_levels("your_file.xlsx")