【问题标题】:Conditionally unhide worksheets in Excel/vba有条件地取消隐藏 Excel/vba 中的工作表
【发布时间】:2019-09-18 09:17:38
【问题描述】:

如果一组工作表满足特定条件,我会尝试取消隐藏它们。这使用由命令按钮触发的用户表单,带有选择选项和另一个命令按钮。预期的行为是,一旦做出选择并按下按钮,所有符合条件的工作表都将被取消隐藏。 Target 字出现在第一行的不同位置,并且在该行之前的所有单元格都是空的。理想情况下,该过程将扫描工作簿中每个工作表的第一行中的每个单元格,直到遇到Target,取消隐藏工作表,然后移动到下一个工作表以重新开始该过程,直到所有工作表与工作簿已经检查过了。

激活用户表单上的命令按钮后,我得到以下信息:

Private Sub ContinueCommand_Click()
Dim Valid As Boolean, wks As Worksheet, c As Integer, actCol As Long    
    actCol = ActiveSheet.Range("A1").End(xlToRight).Column
    For Each wks In ActiveWorkbook.Worksheets
        For c = 1 To actCol
            If ActiveCell.Value = "Target" Then
                wks.Visible = xlSheetVisible
                Exit For
            End If
        Next c
    Next wks
    Valid = True
If Valid = True Then
Unload Me
End If
End Sub

我从多个来源借用,包括使用 ActiveCell 的 heredetermining if a value existsunhidding worksheetsFinding values within a rangesearching for a string。任何帮助将不胜感激。

【问题讨论】:

  • 不要使用ActiveCell。相反,您可能想要If wks.Cells(1, actCol) ... 之类的东西,假设“目标”字符串在第 1 行。
  • 可以用wks.Visible = Not IsError(Application.Match("Target",wks.Range("1:1"),0))替换IF和内循环
  • 另外,如果你说Target 之前的所有单元格都是空的,那么目标将在wks.Range("A1")wks.Range("A1").End(xlToRight) 中。无需再次遍历row 1 中的所有单元格。
  • 您可以将actCol= 行向下移动到下一行下方,除非所有工作表的列数相同,否则您会遗漏一些。

标签: excel vba userform


【解决方案1】:

正如我在我的 cmets 中所说,您选择的实现方式存在一些问题。

不需要您的For c = 1 To actCol 循环。这很容易看出,因为c 并没有真正在循环中的任何地方使用。

假设您的目标值在wks.Range("A100")(第 1 行第 100 列)中。

然后,您的代码将执行完全相同的操作 100 次,并得出完全相同的结果。这就是导致您使用 Exit For 的原因,这是一种不好的做法。

如果我正确理解了您的初始帖子,如果 Target 存在于特定工作表中,则 Target 之前的所有单元格都是空的。

如果是这种情况,Target 将位于 wks.Range("A1")wks.Range("A1").End(xlToRight) 中。如果它不在这两个单元格中,那么它在这个特定的工作表中根本不存在,这意味着第一行完全是空的。除了这两个之外,您无需再检查任何单元格。

您的代码不会检查Target 是否在wks.Range("A1") 中。

您还使用了Application.Match,这让我相信您可能被以下普遍误解所误导:wks.Range("A1").End(xlToRight) 是从A1 开始的一系列单元格,一直延伸到最后一个非空单元格在第一行。

事实上,wks.Range("A1").End(xlToRight) 是一个单个单元格,而不是一系列单元格。选择A1,然后按CTRL+right arrow,将准确显示它是哪个单元格。

我可能遗漏了一些东西,但根据您在最初帖子中的描述,我会执行以下操作:

Dim sht As Worksheet
For Each sht In ThisWorkbook.Worksheets
    If sht.Range("A1").Value = "Target" Or sht.Range("A1").End(xlToRight).Value = "Target" Then
        sht.Visible = xlSheetVisible
    Else
        MsgBox "target was not found in " & sht.Name
    End If
Next sht

【讨论】:

    【解决方案2】:

    我要感谢 BruceWayne、Scott Craner、Stavros Jon、Darell H,他们帮助我更接近这个答案。最终结果如下所示:

    Private Sub ContinueCommand_Click()
    Dim wks As Worksheet    
        For Each wks In ActiveWorkbook.Worksheets
           If Not IsError(Application.Match("Target", wks.Range("A1").End(xlToRight), 0)) Then
                    wks.Visible = xlSheetVisible
                End If
        Next wks
    Unload Me
    End Sub
    

    如果以后有人在让这个工作时遇到问题,请告诉我,我会发布更完整的版本。

    【讨论】:

    • 不需要您的For c = 1 To actCol 循环。这很容易看出,因为c 并没有真正在循环中的任何地方使用。假设您的 Target 值位于第 1 行第 100 列。然后,您的代码将执行完全相同的操作 100 次,并得出完全相同的结果。 如果“目标”之前的所有单元格都为空,则Target 将位于wks.Range("A1")wks.Range("A1").End(xlToRight) 中。如果它不在这两个单元格中,那么它在这个特定的工作表中根本不存在,这意味着第一行完全是空的。
    • 谢谢@Stavros,我根据您的建议修改了我的代码。我不确定我的问题是否不够完整,但我无法让您的版本正确运行。
    • 很高兴我能帮上忙。你有什么问题?既然您已经修改了代码,唯一的问题是如果“BRK”在 cell A1 中,则相应的工作表将不会被隐藏。应该考虑到这种可能性,除非它不可能发生。你知道得更多。
    • 我将BRK 改回Target 以消除与本文其余部分的混淆。这对 A1 来说是正确的,是的,它不可能在那个单元格中,这就是我删除它的原因,但这是一个很好的呼吁。问题是,当我运行您的代码时,它返回了所有工作表,而不仅仅是 Target 的工作表,就好像 if 语句不存在一样。切线地,MsgBox 将通知每个不满足条件的页面,提示消息多次出现,这可能与第一个问题有关。
    猜你喜欢
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 2019-07-05
    • 1970-01-01
    • 2015-12-06
    • 2011-02-25
    相关资源
    最近更新 更多