【问题标题】:speed up the processing of excel vba加快excel vba的处理
【发布时间】:2016-02-25 02:17:15
【问题描述】:

我已经创建了 excel vba 文件。但是,运行整个文件需要很长时间,因为总行数高达 270,000 行。有谁知道我怎样才能加快运行过程?任何帮助将非常感激。提前致谢。

Sub datemodifiedFile()
Dim File1 As Object
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set File1 = fso.getfile("C:\Users\Meg\Desktop\Master File.xlsx")
If Sheets("today").Range("B1").Value = File1.DateLastModified Then
Else
Sheets("today").Range("B1").Value = File1.DateLastModified
Dim WbB As Workbook
Set WbB = Workbooks.Open(Filename:="C:\Users\Meg\Desktop\Master File.xlsx", ReadOnly:=True)
Dim SheetB As Worksheet
Dim lastrow As Long
Set SheetB = WbB.Sheets("Sheet1")
        SheetB.Select
        Rows("1:1").Select
        'Selection.AutoFilter
        'ActiveSheet.Range("A:V").AutoFilter Field:=20, Criteria1:=""
        Columns("A:V").Select
        Selection.Copy
        ThisWorkbook.Activate
        Sheets("today").Select
        Range("C1").Select
        Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
               :=False, Transpose:=False
        'Columns("A:X").Select
        'ActiveSheet.Range("$A$1:$X$750001").RemoveDuplicates Columns:=Array(3, 4, 6), _
        Header:=xlYes
        Application.CutCopyMode = False
        lastrow = Sheets("today").Range("D" & Rows.Count).End(xlUp).Row
        Sheets("today").Cells(lastrow, 3).EntireRow.Delete
WbB.Close False
End If
End Sub
Sub dltnew()
        Dim i As Long
        Dim lrow As Long
        lrow = Sheets("today").Range("C" & Rows.Count).End(xlUp).Row
        For i = 2 To lrow
        If Sheets("today").Cells(i, 2).Value = "NEW" Then
        Sheets("today").Cells(i, 2).Value = ""
        Sheets("today").Cells(i, 1).Value = ""
End If
Next i
End Sub
Sub comdate()
Dim Sheet1 As Worksheet
Dim Sheet3 As Worksheet
Dim lrow As Long
Dim i As Long
Set Sheet1 = ThisWorkbook.Sheets("main")
Set Sheet3 = ThisWorkbook.Sheets("today")
Sheet3.Range("A1").Value = Date
Sheet3.Range("A1").NumberFormat = "dd/mm/yyyy"
Sheet3.Range("A1").Font.Color = Sheet3.Range("A1").Interior.Color
Sheet3.Columns("A:A").EntireColumn.Hidden = False
If Sheet1.Range("B1").Value <> Sheet3.Range("A1").Value Then
   Sheet1.Range("B1").Value = Sheet3.Range("A1").Value
    lrow = Sheet1.Range("C" & Rows.Count).End(xlUp).Row
    For i = 2 To lrow
    If Sheet1.Cells(i, 2).Value = "NEW" Then
    Sheet1.Cells(i, 2).Value = ""
    End If
    Next i
    End If
End Sub
Sub Con()
Dim LasRow As Long
Application.ScreenUpdating = False
LasRow = Sheets("today").Range("C" & Rows.Count).End(xlUp).Row
Sheets("today").Range("A2:A" & LasRow).Formula = "=C2&G2&I2"
ActiveSheet.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
Sub Compare()
    Dim mrow As Range, trow As Long
    With Worksheets("main")
        Set mrow = .Range("A2", .Range("A" & Rows.Count).End(xlUp))
    End With
    trow = Worksheets("today").Range("A" & Rows.Count).End(xlUp).Row

    With Worksheets("today")
        For j = 2 To trow
            If mrow.Find(What:=.Range("A" & j).Value, LookIn:=xlValues, LookAt:=xlWhole) Is Nothing _
             Then .Range("B" & j).Value = "NEW"
        Next j
    End With
End Sub
Sub getnew()
Dim Sheet1 As Worksheet
Dim Sheet3 As Worksheet
Dim lastrow As Long
Dim i As Long
Dim erow As Long
Set Sheet1 = ThisWorkbook.Sheets("main")
Set Sheet3 = ThisWorkbook.Sheets("today")
lastrow = Sheet3.Range("C" & Rows.Count).End(xlUp).Row
For i = 2 To lastrow
    If Sheet3.Cells(i, 2).Value = "NEW" Then
    erow = Sheet1.Range("C" & Rows.Count).End(xlUp).Row + 1
    Sheet3.Cells(i, 2).EntireRow.Copy Destination:=Sheet1.Range("A" & erow)
    Application.CutCopyMode = False
    Sheet1.Select
    Range("A1:X750001").Select
    Selection.Sort Key1:=Range("G2"), Order1:=xlAscending, Key2:=Range("C2") _
        , Order2:=xlAscending, Header:=xlGuess, OrderCustom:=1, MatchCase:= _
        False, Orientation:=xlTopToBottom
End If
Next i
End Sub
Sub hidecellvalue()
Dim Sheet1 As Worksheet
Dim lastrow As Long
Dim k As Long
Set Sheet1 = ThisWorkbook.Sheets("main")
lastrow = Sheet1.Range("B" & Rows.Count).End(xlUp).Row
For k = 2 To lastrow
If Sheet1.Cells(k, 1).Value <> "NEW" Then
Sheet1.Cells(k, 1).Font.Color = Sheet1.Cells(k, 1).Interior.Color
'Sheet1.Columns("A:A").EntireColumn.Hidden = False
End If
Next k
End Sub
Sub hideSh1column()
Dim Sheet1 As Worksheet
Set Sheet1 = ThisWorkbook.Sheets("main")
Sheet1.Columns("A:A").EntireColumn.Hidden = True
Sheet1.Columns("D:F").EntireColumn.Hidden = True
Sheet1.Columns("H:H").EntireColumn.Hidden = True
Sheet1.Columns("L:L").EntireColumn.Hidden = True
Sheet1.Columns("N:N").EntireColumn.Hidden = True
Sheet1.Columns("P:P").EntireColumn.Hidden = True
End Sub
Sub HideSheet3()
Sheets("today").Visible = xlSheetVisible
End Sub

【问题讨论】:

  • 哪个部分花费的时间最多?您可以使用Debug.PrintTimer 输出每个部分需要多长时间。代码太多,因此有助于集中精力解决问题区域。
  • 这个代码转储可能更适合作为Code Review - Excel 的[性能] 问题。阅读他们的What topics can I ask about here?,如果您觉得合适,可以考虑迁移问题。
  • 嗨蒂姆·威廉姆斯。感谢您的建议,我发现 Sub Compare() 运行时间最长。它无休止地运行,没有显示任何时间。
  • 嗨吉普。谢谢你的建议。我想知道如何才能转到 Code Review - Excel,因为我是新来的。
  • 如果您单击edit,您可以将此问题的源代码复制到记事本中,以准备在 Code Review 上创建另一个问题。这个问题可以是deleted。当您在 Code Review 上发帖时,请添加一些有关此代码实际完成的内容的说明。将不胜感激添加指向一些示例数据的链接;不得不重现甚至可能不准确的数据以用于测试目的是令人厌烦的。

标签: vba excel


【解决方案1】:

我会从删除代码中的 .activateselect 开始,然后用适当的 sheet.cell/range 选择替换它。 然后我会在你的代码开始时添加这个

Dim previousScreenUpdating As Boolean
previousScreenUpdating = Application.ScreenUpdating
Application.ScreenUpdating = False
Dim previousCalculation As XlCalculation
previousCalculation = Application.Calculation
Application.Calculation = xlCalculationManual

这在你的代码的末尾

Application.ScreenUpdating = previousScreenUpdating
Application.Calculation = previousCalculation

【讨论】:

    【解决方案2】:

    这应该快得多。

    您应该始终尝试尽可能多地使用数组,而不是逐个单元格地查看数据。

    此外,当您在大循环中检查内容时,使用 Find() 总是会胜过基于字典的查找。

    Sub Compare()
    
        Dim mrow As Range, trow As Long, arr, r As Long
        Dim d As Object, rngV As Range
        Dim arrV, arrN, wsT As Worksheet, wsM As Worksheet
    
        Set d = CreateObject("Scripting.Dictionary")
    
        Set wsM = Worksheets("Main")
        Set wsT = Worksheets("today")
    
        'get all unique values in ColA on Main
        arr = wsM.Range(wsM.Range("A2"), wsM.Cells(wsM.Rows.Count, 1).End(xlUp)).Value
        For r = 1 To UBound(arr, 1)
            d(arr(r, 1)) = 1
        Next r
    
        Set rngV = wsT.Range(wsT.Range("A2"), wsT.Cells(wsT.Rows.Count, 1).End(xlUp))
        arrV = rngV.Value                 'values from colA as array
        arrN = rngV.Offset(0, 1).Value    'values from colB as array
    
        'check colA against the dictionary and update colB array as needed
        For r = 1 To UBound(arrV, 1)
            If Not d.exists(arrV(r, 1)) Then arrN(r, 1) = "NEW"
        Next r
        'repopulate ColB with updated data
        rngV.Offset(0, 1).Value = arrN
    
    End Sub
    

    【讨论】:

    • 嗨蒂姆·威廉姆斯。这确实快了很多。我想知道如何修改代码并加快 Sub getnew() 的运行,以及一次更新太多新信息的情况?
    • 为什么每次复制“新”行时都要重新使用工作表 - 当然您只需要在完成复制后执行一次吗? Luboš 对提高总体执行速度有很好的建议。
    • 嗨蒂姆·威廉姆斯。这是因为我有分类为不同类别的数据,并且“新”行可能会添加到工作表的中间,而不是一直添加到最后一行。因此,每次将其复制到另一张纸上时,都需要使用它来匹配其类别。例如,如果 broccoli 是“NEW”,那么它将被添加到蔬菜类中,而如果是橙色,它将被添加到水果类中。
    • 我知道为什么您可能需要排序,但不明白为什么在完成循环后多次排序会给您带来与运行单次排序不同的结果。单一排序仍将按类别对所有内容进行分组。
    • 嗨蒂姆·威廉姆斯。我明白你的意思了。非常感谢。之间,我想知道是否还有其他更快的循环方式? “新”可能位于 Sheets(“main”) 中的第 5、7、10、25、100 行。我在想是否可以完全收集所有“新”行并在 Sheets(“today”) 中的页面底部复制,然后将它们整理出来,这样会更快吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多