遍历所有工作表并查找范围内的值。如果找到然后执行一些操作并转到

Posted

技术标签:

【中文标题】遍历所有工作表并查找范围内的值。如果找到然后执行一些操作并转到【英文标题】:Loop through all sheets and look for value in range. If found then do some action and GoTo 【发布时间】:2022-01-17 13:24:21 【问题描述】:

我在下面有一段非常简单的代码。我需要它遍历工作簿中的所有工作表并查找范围内的特定值。如果找到,则执行一些操作(获取工作表名称并存储在临时工作表中)并转到另一行以完成其余代码。 只有一个工作表将包含此值或不包含此值。因此,如果在任何这些工作表中都找不到此值,我想从 Step2 运行代码。工作簿甚至可以包含 20-30 张。

如果我在禁用 Else 的情况下运行此代码,它工作正常。它找到工作表,完成 If 并执行其余代码

但是,如果在任何工作表中都找不到值,我想转到第 2 步到其他子页面。但是每当我有这个 Else: GoTo Step2: enabled 它就会进入 Step2: 就在检查第一张没有搜索值的工作表之后。

知道我做错了什么。这是一段简单的代码,我对此感到很疯狂:)

Sub ProjectGCA1 ()

 Application.ScreenUpdating = False
 
 Dim ws, shGCA1 As Worksheet
    Dim wb As Workbook
        Dim i, j As Long
        
    Set wb = ThisWorkbook
               wb.Sheets.Add.Name = "Temporary storage"
            j = wb.Sheets.Count

   For i = 1 To j
    
        If wb.Sheets(i).Range("A4") = "Project Name: GCA1" Then
            Set shGCA1 = wb.Sheets(i)
            wb.Sheets("Temporary storage").Range("A1").Value = "Project Name: GCA1"
                wb.Sheets("Temporary storage").Range("B1").Value = wb.Sheets(i).Name
       
           'Else: GoTo Step2:

        End If
    Next i
Step1: 

' -----------------------rest of the code to work on shGCA1------------------------
' -----------------------rest of the code to work on shGCA1------------------------

Step2
Call ProjectGCA2

End Sub

【问题讨论】:

【参考方案1】:

如果您在循环中激活 else within,那么循环当然会在第一次迭代时保留。如果找到工作表,您需要在循环完成后检查。 据我了解,您正在将shGCA1 设置为您找到的工作表,因此您可以检查它是否已设置。如果您没有这样的变量,只需创建一个布尔变量并在找到某些内容时将其设置为 True。重要的是在循环完成后检查它。

For i = 1 To j
    If wb.Sheets(i).Range("A4") = "Project Name: GCA1" Then
        Set shGCA1 = wb.Sheets(i)
        wb.Sheets("Temporary storage").Range("A1").Value = "Project Name: GCA1"
        wb.Sheets("Temporary storage").Range("B1").Value = wb.Sheets(i).Name
        ' If you are sure there is at most one sheet, you can leave the loop now:
        Exit For
    End If
Next i

If Not shGCA1 Is Nothing then
    ' Do your stuff with the sheet.
Else
    ' Do the stuff if no sheet was found
End If

如果程序的行为不清楚,我强烈建议使用调试器并逐行执行代码(使用 F8)

【讨论】:

感谢您的帮助。这似乎很明显,不知道我为什么要为此苦苦挣扎。非常感谢。经验教训:)【参考方案2】:

单元格中包含字符串的参考工作表

您可以使用以下函数来引用找到的工作表:
Function RefWorksheetWithStringInCell( _
    ByVal wb As Workbook, _
    ByVal CellAddress As String, _
    ByVal CellString As String, _
    Optional ByVal MatchCase As Boolean = False) _
As Worksheet
    Const ProcName As String = "RefWorksheetWithStringInCell"
    On Error GoTo ClearError
    
    Dim CompareMethod As VbCompareMethod
    CompareMethod = IIf(MatchCase = False, vbTextCompare, vbBinaryCompare)
    
    Dim ws As Worksheet
    For Each ws In wb.Worksheets
        If StrComp(CStr(ws.Range(CellAddress).Value), CellString, _
                CompareMethod) > 0 Then
            Set RefWorksheetWithStringInCell = ws
            Exit For
        End If
    Next ws

ProcExit:
    Exit Function
ClearError:
    Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
              & "    " & "Run-time error '" & Err.Number & "':" & vbLf _
              & "    " & Err.Description
    Resume ProcExit
End Function
然后您可以通过以下方式重写您的代码:
' Now the loop is in the function.
Set shGCA1 = RefWorksheetWithStringInCell(wb, "A4", "Project Name: GCA1")

If shGCA1 Is Nothing Then ' not found
    ProjectGCA2 ' 'Call' is considered deprecated
    Exit Sub
Endif    

wb.Worksheets("Temporary storage").Range("A1").Value = "Project Name: GCA1"
wb.Worksheets("Temporary storage").Range("B1").Value = shGCA1.Name
' Continue...
这里有一个函数可以让您控制添加工作表,例如如果它已经存在:
Function RefAddedWorksheet( _
    ByVal wb As Workbook, _
    ByVal WorksheetName As String, _
    Optional ByVal DoKeepExisting As Boolean = False) _
As Worksheet
    Const ProcName As String = "RefAddedWorksheet"
    On Error GoTo ClearError ' e.g. invalid sheet name

    Dim sh As Object ' e.g. chart
    Dim DoesWorksheetExist As Boolean
    
    On Error Resume Next
        Set sh = wb.Sheets(WorksheetName)
    On Error GoTo ClearError
    
    If Not sh Is Nothing Then ' sheet already exists
        If sh.Type = xlWorksheet Then ' is worksheet
            If DoKeepExisting Then ' keep
                DoesWorksheetExist = True ' flag it existing
            'Else ' don't keep
            End If
        'Else ' is chart
        End If
        If Not DoesWorksheetExist Then ' not flagged existing
            Application.DisplayAlerts = False ' delete without confirmation
                sh.Delete
            Application.DisplayAlerts = True
        'Else ' flagged existing
        End If
    'Else ' sheet doesn't exist
    End If
    
    If Not DoesWorksheetExist Then ' not flagged existing
        Set sh = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
        On Error Resume Next
            sh.Name = WorksheetName
        On Error GoTo ClearError
    'Else ' flagged existing
    End If
    
    If StrComp(sh.Name, WorksheetName, vbTextCompare) = 0 Then ' valid name
        Set RefAddedWorksheet = sh
    Else ' invalid name
        Application.DisplayAlerts = False ' delete without confirmation
            sh.Delete
        Application.DisplayAlerts = True
    End If

ProcExit:
    Exit Function
ClearError:
    Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
              & "    " & "Run-time error '" & Err.Number & "':" & vbLf _
              & "    " & Err.Description
    Resume ProcExit
End Function
在您的代码中,您可以例如按以下方式使用它:
Const wsTempName As String = "Temporary storage"
Const wsTempDoKeepExisting As Boolean = False

Dim wsTemp As Worksheet
Set wsTemp = RefAddedWorksheet(wb, wsTempName, wsTempDoKeepExisting)

If wsTemp Is Nothing Then ' highly unlikely (if invalid name e.g. 'History')
    MsgBox "Could not create the '" & wsTempName & "' worksheet.", _
        vbCritical
    Exit Sub
End If
请注意,该函数将工作表添加到工作簿中的最后一张工作表之后。

【讨论】:

以上是关于遍历所有工作表并查找范围内的值。如果找到然后执行一些操作并转到的主要内容,如果未能解决你的问题,请参考以下文章

如果我编辑另一个工作表并切换回来,则不显示易失性 UDF 的结果

遍历数据透视表并删除相同的值

Oracle - 遍历表并检查属性中的值

Java工作日计算工具类

在 c++ 中将值转换为范围内的值,使用 boost 或 std 进行优化

使用 oracle SQL 查找日期范围内的星期几