寻找简化代码的方法

时间:2017-07-07 15:02:45

标签: excel vba excel-vba

我在该宏中添加另一个函数时遇到问题我曾经在工作中使用的Excel工作簿中激活或停用列。我在运行它时只是添加了以下功能之一,从而得到了堆栈空间错误。

大多数情况下,我使用If( ; 1; 0)来管理激活部分,并使用If( ; TRUE; FALSE)来锁定/解锁部分。我想要的功能是基于相同的想法,使用验证码清除单元格的Clearcontents并将其锁定。如果验证码为假,那么,我希望解锁单元格,以便用户可以写入值。这是我希望锁定的,未锁定的函数已经执行过15次的代码行。

If Range("AS16") = "Vrai" Then
Range("AA16").ClearContents
Range("AA16").Locked = True
Else:
Range("AA16").Locked = False
End If

这是我现在正在使用的代码。

Private Sub Worksheet_Change(ByVal Target As Range)
ActiveSheet.Unprotect ("Francis")
Dim Cell As Range
Set Cell = ActiveCell
Application.ScreenUpdating = False

For Each cellule In Range("S50:X50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule

For Each cellule In Range("S50:X50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule

For Each cellule In Range("I50:J50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule

For Each cellule In Range("I50:J50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule

If Range("AR16") = "Vrai" Then
Range("K16").Locked = False
Range("O16").Locked = False
Else:
Range("K16").Locked = True
Range("O16").Locked = True
End If

If Range("AR18") = "Vrai" Then
Range("K18").Locked = False
Range("O18").Locked = False
Else:
Range("K18").Locked = True
Range("O18").Locked = True
End If

If Range("AR20") = "Vrai" Then
Range("K20").Locked = False
Range("O20").Locked = False
Else:
Range("K20").Locked = True
Range("O20").Locked = True
End If

If Range("AR22") = "Vrai" Then
Range("K22").Locked = False
Range("O22").Locked = False
Else:
Range("K22").Locked = True
Range("O22").Locked = True
End If

If Range("AR24") = "Vrai" Then
Range("K24").Locked = False
Range("O24").Locked = False
Else:
Range("K24").Locked = True
Range("O24").Locked = True
End If

If Range("AR26") = "Vrai" Then
Range("K26").Locked = False
Range("O26").Locked = False
Else:
Range("K26").Locked = True
Range("O26").Locked = True
End If

If Range("AR28") = "Vrai" Then
Range("K28").Locked = False
Range("O28").Locked = False
Else:
Range("K28").Locked = True
Range("O28").Locked = True
End If

If Range("AR30") = "Vrai" Then
Range("K30").Locked = False
Range("O30").Locked = False
Else:
Range("K30").Locked = True
Range("O30").Locked = True
End If

If Range("AR32") = "Vrai" Then
Range("K32").Locked = False
Range("O32").Locked = False
Else:
Range("K32").Locked = True
Range("O32").Locked = True
End If

If Range("AR34") = "Vrai" Then
Range("K34").Locked = False
Range("O34").Locked = False
Else:
Range("K34").Locked = True
Range("O34").Locked = True
End If

If Range("AR36") = "Vrai" Then
Range("K36").Locked = False
Range("O36").Locked = False
Else:
Range("K36").Locked = True
Range("O36").Locked = True
End If

If Range("AR38") = "Vrai" Then
Range("K38").Locked = False
Range("O38").Locked = False
Else:
Range("K38").Locked = True
Range("O38").Locked = True
End If

If Range("AR40") = "Vrai" Then
Range("K40").Locked = False
Range("O40").Locked = False
Else:
Range("K40").Locked = True
Range("O40").Locked = True
End If

If Range("AR42") = "Vrai" Then
Range("K42").Locked = False
Range("O42").Locked = False
Else:
Range("K42").Locked = True
Range("O42").Locked = True
End If

If Range("AR44") = "Vrai" Then
Range("K44").Locked = False
Range("O44").Locked = False
Else:
Range("K44").Locked = True
Range("O44").Locked = True
End If

Application.ScreenUpdating = True
Application.Goto Cell

'ActiveSheet.Protect Password:="Francis"
End Sub 

非常感谢你的帮助。

度过美好的一天!

3 个答案:

答案 0 :(得分:4)

您通常不希望在该特定处理程序中运行性能代价高昂的代码。每次单元格更改时都会调用 ... 包括更改单元格的Worksheet_Change属性值。

这就是你如何从堆栈空间中运行 :你的处理程序正在修改单元格的Locked状态,这会触发Locked事件,这会修改单元格{{1状态,触发Worksheet_Change事件,修改单元格的Locked状态,触发Worksheet_Change事件,最终导致调用堆栈。

因此,为了防止意外递归,您需要阻止Excel在处理工作表事件时触发:

Locked

至于简化代码,一旦您的代码按预期工作,这就更像是Code Review Stack Exchange的授权。

  

如果任何C#dev正在阅读此内容,那么这个特殊情况现在在Rubberduck的GitHub存储库中有一个问题:#3109 Prevent accidental recursion in Worksheet_Change and Workbook_SheetChange handlers;一旦执行了检查,Rubberduck将能够在您处理Worksheet_Change时警告您,而不会禁用应用程序事件。

答案 1 :(得分:2)

Out of stack错误是由Change事件引起的,如@Mat

所述

试试这个版本也可以关闭和打开事件

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim cellule As Range, r As Long, isVrai As Boolean

    ActiveSheet.Unprotect "Francis"
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
    End With

    For Each cellule In Union(Range("I50:J50"), Range("S50:X50"))
        With cellule
            Select Case .Value2
                Case "1": .EntireColumn.Hidden = False
                Case "0": .EntireColumn.Hidden = True
            End Select
        End With
    Next
    For r = 16 To 44 Step 2
        isVrai = (Range("AR" & r).Value2 = "Vrai")
        Range("K" & r).Locked = Not isVrai
        Range("O" & r).Locked = Not isVrai
        If isVrai Then Range("AR" & r).ClearContents
    Next

    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With
    'ActiveSheet.Protect Password:="Francis"
End Sub

答案 2 :(得分:0)

此部分可以简化:

dump_classifier_and_data(modelwithpca, dataset, features)  

以下内容(但请注意,这将取消隐藏任何非零值)。

For Each cellule In Range("S50:X50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule

For Each cellule In Range("S50:X50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule

For Each cellule In Range("I50:J50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule

For Each cellule In Range("I50:J50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule

本节:

For Each cellule in Range("S50:X50")
    cellule.EntireColumn.Hidden = (cellule.Value = "0")
Next
For Each cellule in Range("I50:J50")
    cellule.EntireColumn.Hidden = (cellule.Value = "0")
Next

可以使用If Range("AR16") = "Vrai" Then Range("K16").Locked = False Range("O16").Locked = False Else: Range("K16").Locked = True Range("O16").Locked = True End If If Range("AR18") = "Vrai" Then Range("K18").Locked = False Range("O18").Locked = False Else: Range("K18").Locked = True Range("O18").Locked = True End If ....

上的循环进行简化
Range("AR16:AR44")