VBA脚本单独运行,但不在活动的x命令按钮上运行

时间:2018-05-14 15:24:24

标签: excel vba excel-vba

我有一个脚本,用于在工作簿中搜索某些条件,并在满足该条件时隐藏行。一切都很好。问题是我正在尝试为脚本创建一个命令按钮,并且在使用按钮时它不会运行。我正在尝试使用命令按钮制作工作表,以便我可以将工作表提供给其他人,他们可以将其复制到工作簿中并使用脚本而无需创建自己的模块。

这是我正在使用的脚本:

Dim ws As Worksheet

For Each ws In ActiveWorkbook.Worksheets
    ws.Visible = xlSheetVisible
Next ws

Dim starting_ws As Worksheet
Set starting_ws = ActiveSheet

For Each ws In ThisWorkbook.Worksheets
    ws.Activate
    Application.ScreenUpdating = False

    Rows("1:1000").Hidden = False
    on error resume next

    For Each c In Range("B6:D1000")
        If c.Value <> "Criteria" And c.Value <> "Criteria 1" And c.Value <> "Criteria 2" And c.Value <> "Criteria 3" And c.Offset(0, 1).Value = 0 And c.Offset(0, 1).Value <> "" And c.Offset(0, 2).Value = 0 And c.Offset(0, 2).Value <> "" Then Rows(c.Row).Hidden = True
    Next c

Next
starting_ws.Activate

自己模块中的脚本运行正常。只有当我将脚本发送到命令按钮源代码时才会失败。它不会给出任何错误消息。该脚本看起来像是在工作簿中运行,然后在第二页上停止。我确实有&#34;接下来的错误恢复&#34;只是因为它会停止在工作簿末尾的受保护工作表上失败。我将创建一个条件来跳过受保护的页面并删除&#34; on error resume next&#34;。这是我稍后会做的事情。如果我有问题,我会打开一个新问题。任何帮助,将不胜感激。谢谢!

编辑:

我已经进行了更改,现在脚本在没有错误的情况下运行所有​​工作表,但现在它实际上不会隐藏我想隐藏的行。现在是代码:

Private Sub CommandButton3_Click()
    Dim ws As Worksheet

        For Each ws In ActiveWorkbook.Worksheets
        ws.Visible = xlSheetVisible
        Next ws

        Dim starting_ws As Worksheet
        Set starting_ws = ActiveSheet
        If ActiveSheet.ProtectContents = False Then
            For Each ws In ThisWorkbook.Worksheets
                ws.Activate 'Line 12 here

                    Rows("1:1000").Hidden = False

                    For Each c In Range("B6:D1000")
                        If c.Value <> "Criteria" And c.Value <> "Criteria1" And c.Value <> "Criteria2" And c.Value <> "Criteria3" And c.Offset(0, 1).Value = 0 And c.Offset(0, 1).Value <> "" And c.Offset(0, 2).Value = 0 And c.Offset(0, 2).Value <> "" Then Rows(c.Row).Hidden = True
                    Next c

                Next
            Else
        End If
        starting_ws.Activate
    Application.ScreenUpdating = True
 End Sub

请耐心等待我,因为我对VBA很新。我试图学习它虽然如此有建设性的反馈总是有帮助的。对于&#34; ws.Activate&#34;我仍然有点困惑。第12行。我需要这部分代码吗?该工作簿有十五种不同的工作表,我希望它可以循环使用。我虽然需要&#34; ws.Activate&#34;在下一页开始。是这样的吗?再次感谢所有的帮助。

编辑:我更改了代码并使用PEH的回答更新了

在查看PEH的评论之后,我查看了我的代码并对其进行了修改。这是我现在的代码,它运行得很好。我不是把它作为答案发布,因为我可以做更多的事情来清理它。这是代码:

Sub HideAllDoubleZeros() iAnswer = MsgBox(&#34;你想运行Hide all Double Zeros?&#34;&amp; Chr(10)_ &安培; &#34;单击否将取消脚本。&#34;,_ vbYesNoCancel + vbQuestion + vbDefaultButton1,&#34;现在隐藏零&#34;)     如果iAnswer = vbYes那么     Dim Ws As Worksheet

    For Each ws In ActiveWorkbook.Worksheets
        ws.Visible = xlSheetVisible
        Next ws

        Dim starting_ws As Worksheet
        Set starting_ws = ActiveSheet
        For Each ws In ThisWorkbook.Worksheets
        ws.Activate *'This is Line 16*
        If ActiveSheet.ProtectContents = False Then

        Dim c As Variant
        Application.ScreenUpdating = False
        ws.Rows.Hidden = False

            For Each c In Range("B6:D1000")
                If c.Value <> "criteria" _
                    And c.Value <> "criteria1" _
                    And c.Value <> "criteria2" _
                    And c.Value <> "criteria3" _
                    And c.Offset(0, 1).Value = 0 _
                    And c.Offset(0, 1).Value <> vbNullString _
                    And c.Offset(0, 2).Value = 0 _
                    And c.Offset(0, 2).Value <> vbNullString _
                Then Rows(c.Row).Hidden = True
            Next c
        Else
            MsgBox ws.Name
        End If
        Next
            starting_ws.Activate *'This is Line 38*
ElseIf iAnswer = vbNo Then
End If

Exit Sub

End Sub

我添加了一个评论框,询问他们是否只想运行脚本以防止意外点击。我试图采取&#34; ws.Activate&#34;超出第16行,但当我这样做时,我收到了#34;运行时错误&#39; 1004&#39;:应用程序定义或对象定义错误&#34;。我也尝试删除&#34; ws.activate&#34;从第38行开始,然后我收到了#34;错误400&#34;。所以现在我把它们放回脚本中。现在一切都很好。您还有什么建议可以清理代码或提高代码效率吗?我希望了解更多关于VBA编码的信息,所以如果你能在PEH的答案中包含你为什么这样做的评论,我将不胜感激。

2 个答案:

答案 0 :(得分:0)

我建议您先从正确处理错误开始。

以下是我在几乎每个例程中使用的一些代码。

import collections
d = collections.defaultdict(list)
for i in dataset:
  d[i[0]].append(i[1:])

results = {a:min(b, key=lambda x:int(x[-1])) for a, b in d.items()}

答案 1 :(得分:0)

  1. 删除所有 .Activate
  2. 直接使用Rows
  3. 这样的表格引用所有 Rangews.Rows
  4. 而不是Rows("1:1000").Hidden = False使用Rows.Hidden = False,因此当您的行数超过1000行时,您不需要延长它。
  5. 将它减少到一个循环只会使它更快。
  6. 每个ws测试一次,不仅是活动的保护。
  7. 如果不需要,请删除else部分(请参阅注释)。
  8. Option Explicit
    
    Private Sub CommandButton3_Click()
        Application.ScreenUpdating = False 'if you turn it false don't forget
                                           'to turn it true in the end!
        Dim ws As Worksheet
        For Each ws In ThisWorkbook.Worksheets
            ws.Visible = xlSheetVisible 'make worksheet visible
    
            If ws.ProtectContents = False Then
                ws.Rows.Hidden = False 'unhide rows / make all rows visible
    
                Dim EachCell As Variant
                For Each EachCell In ws.Range("B6:D1000")
                    If EachCell.Value <> "Criteria" And _
                       EachCell.Value <> "Criteria1" And _
                       EachCell.Value <> "Criteria2" And _
                       EachCell.Value <> "Criteria3" And _
                       EachCell.Offset(0, 1).Value = 0 And _
                       EachCell.Offset(0, 1).Value <> vbNullString And _
                       EachCell.Offset(0, 2).Value = 0 And _
                       EachCell.Offset(0, 2).Value <> vbNullString Then
                        ws.Rows(EachCell.Row).Hidden = True
                    End If
                Next EachCell
            Else
                'here eg give a message when a sheet is protected
                'or do nothing
            End If
        Next ws
    
        Application.ScreenUpdating = True
    End Sub