VBA类似的代码在一张工作表上完美地工作,但不是其他的

我为我的一个工作表写了下面的代码。

Sub Hide_Projects() Application.ScreenUpdating = False i = 6 For i = 6 To 350 Cells(9, i).Select If Selection.Value = "Project" Then ActiveCell.EntireColumn.Hidden = True Else ActiveCell.EntireColumn.Hidden = False End If Next i Application.ScreenUpdating = True End Sub 

它工作正常,没有崩溃或滞后,每次我都需要它。 但是,当我在不同的工作表上使用类似的代码时,只有这次应用于行而不是列时,即使代码是相同的,它也会崩溃我的Excel或大约2分钟运行。 这是第二个代码:

 Sub Hide_Projects_5yr() Application.ScreenUpdating = False i = 6 For i = 6 To 350 Cells(i, 7).Select If Selection.Value = "Project" Then ActiveCell.EntireRow.Hidden = True Else ActiveCell.EntireRow.Hidden = False End If Next i Application.ScreenUpdating = True End Sub 

有没有人有任何想法,为什么这样呢?

谢谢!

很明显, 比隐藏更快。 我试过这个:

 Option Explicit Public Sub TestingSpeed() Dim lngCount As Long Dim dtTime As Date Columns.Hidden = False rows.Hidden = False dtTime = Now For lngCount = 1 To 300 rows(lngCount).Hidden = True Next lngCount Debug.Print "Rows: -> "; DateDiff("s", dtTime, Now()) dtTime = Now For lngCount = 1 To 300 Columns(lngCount).Hidden = True Next lngCount Debug.Print "Cols: -> "; DateDiff("s", dtTime, Now()) End Sub 

结果如下(以秒为单位):

 Rows: -> 9 Cols: -> 2 

差异呈指数级增长。

有了1000个样本,就是这样的:

 Rows: -> 11 Cols: -> 1 

有了这样的10.000

 Rows: -> 19 Cols: -> 10 

你的工作表很可能不是你打算工作的那个人。 总是最好避免SelectActiveCell ,因为你依赖于光标的位置。 不知道你需要假的情况下,除非你一遍又一遍地使用同一张表,它可能被隐藏。

 Sub Hide_Projects_5yr() Application.ScreenUpdating = False Dim ws as Worksheet Set ws = Sheets("YourSheetName") For i = 6 To 350 If ws.Cells(i, 7).Value = "Project" Then ws.Cells(i, 7).EntireRow.Hidden = True Else ws.Cells(i, 7).EntireRow.Hidden = False End If Next i Application.ScreenUpdating = True End Sub 

你可以尝试给你的代码完整的地址到你的单元格? 另外,不使用select命令是个好主意。 这是我对你的代码的修改:

 Sub Hide_Projects() Application.ScreenUpdating = False With ThisWorkbook.Sheets("Put the name of your sheet here") For i = 6 To 350 If .Cells(9, i).Text = "Project" Then .Columns(i).Hidden = True Else .Columns(i).Hidden = False End If Next i End With Application.ScreenUpdating = True End Sub 

你的第二个代码看起来像这样:

 Sub Hide_Projects_5yr() Application.ScreenUpdating = False With ThisWorkbook.Sheets("Put the name of your second sheet here") For i = 6 To 350 If .Cells(i, 7).Text = "Project" Then .Rows(i).Hidden = True Else .Rows(i).Hidden = False End If Next i End With Application.ScreenUpdating = True End Sub 

让我知道如果错误消息不断出现。

您的主要放缓是多次从工作表中读取数据的结果。 首先将单元格值加载到数组中,然后循环。

你也可以通过一开始就隐藏所有的行来获得一些速度,如果“=”项目条件为真则隐藏,同样,这减less了对工作表的调用次数;当前版本设置“隐藏“每一行的属性。

 Application.ScreenUpdating = False Dim i As Long Dim j As Long Dim tempArr As Variant tempArr = Range(Cells(6, 7), Cells(350, 7)).Value Rows("6:350").Hidden = False j = 1 For i = LBound(tempArr, 1) To UBound(tempArr, 1) If tempArr(i, 1) = "Project" Then Rows(j + 5).Hidden = True End If j = j + 1 Next Application.ScreenUpdating = True 

如果您真的关心速度,也可以通过检查包含“Project”的连续行来减less工作表的行程数量。 这个版本的运行速度是另一个速度的两倍(在200k行的样本上testing)。 不过,它使代码变得更加复杂。

 Application.ScreenUpdating = False Dim i As Long Dim j As Long Dim k As Long Dim tempArr As Variant Dim consBool As Boolean tempArr = Range(Cells(6, 7), Cells(350, 7)).Value Rows("6:350").Hidden = False j = 1 For i = LBound(tempArr, 1) To UBound(tempArr, 1) consBool = True If tempArr(i, 1) = "Project" Then k = i Do Until consBool = False If k = UBound(tempArr, 1) Then consBool = False ElseIf tempArr(k + 1, 1) = "Project" Then k = k + 1 Else consBool = False End If Loop Rows(j + 5 & ":" & k + 5).Hidden = True j = j + 1 + (k - i) i = k Else j = j + 1 End If Next Application.ScreenUpdating = True 

下面是如果我要在一个更大的项目中实现这个function的样子。 在其他优化中,我添加了一些function(它可以检查部分匹配,检查多个列的条件,并做一个“倒置”模式,隐藏所有行包含您的标准),并确保您需要指定您的工作表。

 Option Explicit Sub exampleMacro() Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Call hideRows(ThisWorkbook.Sheets("Example WS"), 6, 350, "Project", 7, 7) Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = True End Sub Sub hideRows(ws As Worksheet, startRow As Long, endRow As Long, valCrit As String, Optional startCol As Long = 1, Optional endCol As Long = 1, Optional invert As Boolean = False, Optional checkAll As Boolean = False) 'Hides rows in a range (startRow to endRow) in a worksheet (ws) 'Hides when row contains a value (valCrit; partial strings are accepted) in a column or series of columns (startCol to endCol) 'In inverted mode (invert), hides rows that do *not* contain value 'If (checkAll) is True, all columns must contain value to be hidden/unhidden 'Usage examples: 'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10) -> hides rows that contain a cell in columns 1-10 with exact value "Foo" 'Call hideRows(exampleWS, 1, 1000, "*Foo*", 1, 10) -> hides rows that contain a cell in columns 1-10 that contains partial string "*Foo*" 'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10, True) -> hides rows that contain no cells in columns 1-10 with exact value "Foo" 'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10, False, True) -> hides rows in which all cells in columns 1-10 contain the exact value "Foo" 'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10, True, True) -> hides rows in which no cells in columns 1-10 contain the exact value "Foo" Dim loopCounter As Long Dim rowCounter As Long Dim colCounter As Long Dim endConsRow As Long Dim tempArr As Variant Dim toAdd As Long Dim toHide As String Dim consBool As Boolean Dim tempBool As Boolean Dim rowStr As String Dim goAhead As Boolean Dim i As Long If startRow > endRow Then toAdd = endRow - 1 Else toAdd = startRow - 1 End If ws.Rows(startRow & ":" & endRow).Hidden = False tempArr = ws.Range(ws.Cells(startRow, startCol), ws.Cells(endRow, endCol)).Value loopCounter = 1 For rowCounter = LBound(tempArr, 1) To UBound(tempArr, 1) For colCounter = LBound(tempArr, 2) To UBound(tempArr, 2) goAhead = False If tempArr(rowCounter, colCounter) Like valCrit Then If (Not checkAll) Or (colCounter = UBound(tempArr, 2)) Then If invert Then loopCounter = loopCounter + 1 Exit For End If goAhead = True End If ElseIf checkAll Or colCounter = UBound(tempArr, 2) Then If Not invert Then loopCounter = loopCounter + 1 Exit For End If goAhead = True End If If goAhead Then endConsRow = rowCounter consBool = True Do Until consBool = False tempBool = False For i = LBound(tempArr, 2) To UBound(tempArr, 2) If endConsRow = UBound(tempArr, 1) Then Exit For ElseIf tempArr(endConsRow + 1, i) Like valCrit Then If (Not checkAll) Or (i = UBound(tempArr, 2)) Then If Not invert Then endConsRow = endConsRow + 1 tempBool = True End If Exit For End If ElseIf checkAll Or i = UBound(tempArr, 2) Then If invert Then endConsRow = endConsRow + 1 tempBool = True End If Exit For End If Next If Not tempBool Then consBool = False End If Loop rowStr = loopCounter + toAdd & ":" & endConsRow + toAdd If toHide = "" Then toHide = rowStr ElseIf Len(toHide & "," & rowStr) > 255 Then ws.Range(toHide).EntireRow.Hidden = True toHide = rowStr Else toHide = toHide & "," & rowStr End If loopCounter = loopCounter + 1 + (endConsRow - rowCounter) rowCounter = endConsRow Exit For End If Next Next If Not toHide = "" Then ws.Range(toHide).EntireRow.Hidden = True End If End Sub