【问题标题】:Checking existence of sheets and hiding / un-hiding based on cell values检查工作表是否存在并根据单元格值隐藏/取消隐藏
【发布时间】:2018-11-21 21:47:56
【问题描述】:

我在这方面非常业余!目前我有一个工作表,其中包含一个用户列表,然后是一个工作表名称/编号列表

总体预期是,如果用户在工作表下的单元格中有 1,那么工作表是可见的,否则工作表应该非常隐藏

此代码位于模块 1 中,但不确定它是否应该位于工作簿级别。

我在函数之外声明了以下内容,以便可以在每个函数中调用它们;

Dim lRow As Long, wsStatus As Boolean, shtloc As Integer

那么这是我的主要功能(可能应该是工作簿级别的子功能,不确定)

    Function CheckSheetPermission()

Sheet9.Visible = xlSheetVisible
For Each ws In ActiveWorkbook.Worksheets
    If ws.Name <> "Welcome" Then ws.Visible = xlSheetVeryHidden
Next ws
Sheet12.Visible = xlSheetVisible
Sheet12.Activate
With ActiveSheet
Dim sht As Worksheet
Call GetRowNum(Range("A3:A200"), LCase(Environ("UserName")))
    For Each Cell In Range("B" & lRow & ":GS" & lRow)
    If Abs(Cell.Value) = "1" Then
        shtloc = Cell(2, ActiveCell.Column).Value
        Call wsExists(Sheets(shtloc))
        If wsStatus = False Then
            Sheets(shtloc).Visible = xlSheetVisible
        End If
    Else
        shtloc = Cell(2, ActiveCell.Column).Value
         Call wsExists(Sheets(shtloc))
        If wsStatus = False Then
            Sheets(shtloc).Visible = xlSheetVeryHidden
        End If
    End If
    Next
End With
End Function

这看下面的表格,它最初是为了确保欢迎和表格 1 在代码执行之前都是临时可见的,然后为所有表格设置正确的可见性(我假设表格必须对读取单元格的代码)

工作表图片

获取行号只是查找用户并获取行号

Call GetRowNum(Range("A3:A200"), LCase(Environ("UserName")))

而那个功能码是

Function GetRowNum(rng As Range, user As String)


    On Error Resume Next
    lRow = Application.WorksheetFunction.Match(user, rng, 0) + 2
    On Error GoTo 0


End Function

目前似乎出错的地方是我调用下一个函数时;

Call wsExists(Sheets(shtloc))

我得到下标超出范围错误。这可能是因为未正确设置之前的变量或我正在调用的函数本身,但我不确定从哪里开始修改代码和检查结果以进一步隔离问题的最佳位置

在此阶段进行有限的错误处理,试图捕获错误。如果我将错误处理添加到它只是通过的主要功能,并且除了在开始时设置的那些之外没有隐藏或可见的工作表(工作表控制和欢迎)

Function wsExists(wsSheet As Worksheet)
On Error Resume Next
On Error GoTo 0
If Not wsSheet Is Nothing Then
wsStatus = "True"
Else
wsStatus = "False"
End If

End Function

如果您需要更多信息,请告诉我。

我想要实现的只是以下步骤;

  1. 检查通过循环打开文件的用户应该可以看到哪些工作表
  2. 如果存在每个工作表编号,则使用工作表编号变量以及用户名旁边行下的 0/1 值循环遍历每个工作表编号并设置工作表可见性(1 = 允许。0 = 不允许)李>

我承认,对于那些有更好理解的人来说,这可能会更好地编写脚本

###编辑

在我发现一些额外错误后提出改进建议和一些额外更改后的最终代码

这本工作簿

Private Sub Workbook_Open()

Dim ws As Worksheet
Dim shtloc As String
Dim c As Long
Dim lRow2 As Long
Sheet9.Visible = xlSheetVisible

For Each ws In ActiveWorkbook.Worksheets
    If ws.Name <> "Welcome" Then ws.Visible = xlSheetVeryHidden
Next ws
Sheet12.Visible = xlSheetVisible
Sheet12.Activate
With Sheet12
    lRow2 = Module2.lRow2(Range("A3:A5"), LCase(Environ("UserName")))


        For c = 2 To ActiveWorkbook.Worksheets.Count + 1
        shtloc = Cells(1, c).Value2
             With Cells(lRow2, c)
             perm = Cells(lRow2, c).Value2
                Select Case perm
                    Case ("V")
                    'Visible
                        Sheets(shtloc).Visible = xlSheetVisible
                    Case ("P")
                    'visible protected
                        Sheets(shtloc).Visible = xlSheetVeryHidden
                        Sheets(shtloc).Protect Password:="*********"
                    Case ("D")
                    'Access denied
                        Sheets(shtloc).Visible = xlSheetVeryHidden
                    End Select
             End With
        Next c

End With

End Sub

模块

Function lRow2(rng As Range, user As String)

    On Error Resume Next
    With ActiveSheet
    lRow2 = Application.WorksheetFunction.Match(user, rng, 0)

    lRow2 = lRow2 + 2

    End With
End Function

我不再检查工作表是否存在,因为我计算工作表并且不继续下一个循环到等待新工作表创建被填充的空白单元格......也加快了代码速度

【问题讨论】:

  • 你可能想看看不同的答案here

标签: excel vba


【解决方案1】:

您的代码中有一些错误。为了避免混淆,我会做的一件事是在你的 for 循环中使用不同的迭代器。而不是

For Each Cell In Range("B" & lRow & ":GS" & lRow)

我会用

For Each currentCell In Range("B" & lRow & ":GS" & lRow)

这样可以避免我注意到的第一个错误:

shtloc = Cell(2, ActiveCell.Column).Value

这行不会返回你想要的。首先,您需要在“Cell”末尾添加一个“s”。其次,您的工作表名称在第 1 行,第三,您的代码不清楚当前激活了哪个单元格,这可能会返回奇怪的行为。尝试将其替换为:

shtloc = Cells(1, currentCell.Column).Value

现在您的主要错误是您尝试通过触发错误来检查工作表是否存在。这会产生超出范围的错误。

您应该使用不同的函数来检查读取的工作表名称是否存在。这个答案正好提供了你想要的

https://stackoverflow.com/a/6040454/10645669

Function sheetExists(sheetToFind As String) As Boolean sheetExists = False For Each sheet In Worksheets If sheetToFind = sheet.name Then sheetExists = True Exit Function End If Next sheet End Function


另一方面,在我看来,您使用的是全局变量,因为您没有正确地从函数中返回值。比如

Function wsExists(wsSheet As Worksheet)
On Error Resume Next
On Error GoTo 0
If Not wsSheet Is Nothing Then
wsStatus = "True"
Else
wsStatus = "False"
End If

End Function

可以写成:

Function wsExists(wsSheet As Worksheet) as boolean
On Error Resume Next
On Error GoTo 0
If Not wsSheet Is Nothing Then
wsExists = "True"
Else
wsExists = "False"
End If

End Function

这允许您直接在代码中使用该函数,如下所示:

If wsExists(Sheets(shtloc)) = False Then

不再使用全局变量,也不再使用关键字 call。

此外,根据经验,如果编写的代码没有返回任何内容,那么它应该是一个“子”。只需声明不带括号的参数,就可以在不使用关键字 call 的情况下调用它们。示例:

subCalled argument1, argument2, argumentN

【讨论】:

  • 感谢您的所有反馈,我一定会接受所有这些 cmets。我将根据上述代码重新编写代码并确认结果。
  • 你好。在查看您的更改时,我发现了另一个问题。在我完成它们之前,我需要做一个额外的更正。我引用的工作表编号来自数字而不是我想要确保的名称,即使它重命名它也不会开始倒下。但它把它当作一个索引号而不是代号,这也意味着如果标签重新排序权限会改变。关于我如何在这些单元格中使用代号但仍显示选项卡名称(供参考),是否有任何建议,以便用户在设置权限时知道哪个工作表是什么?
猜你喜欢
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-08
  • 1970-01-01
  • 2018-04-13
相关资源
最近更新 更多