从“查找”无限循环中退出

时间:2019-03-25 18:30:04

标签: excel vba

我已经用Find创建了一个Do循环,以将Sheet1的A列内的“ Hello”替换为“ Hi”,但前提是字符串“ XYZ”不在B列的同一行中。

当Find不能替换“ Hello”时,因为在B列中存在“ XYZ”,由于FindNext总是在第1列中找到“ Hello”,因此我们进入了无限循环

是否可以避免无限循环而不会使 Loop While 非常复杂?

Please see this image of columns in sheet1

Sub CallMask()
    Call Masks("Hello", "XYZ")
End Sub

Sub Masks(sMask_I As String, sNoReplace_I As String)
    With Sheets("Sheet1").Columns(1)
        Dim CellToReplace As Range
        Set CellToReplace = .Find(What:=sMask_I, LookIn:=xlValues, _
            SearchDirection:=xlNext, MatchCase:=True, Lookat:=xlPart)
        If Not CellToReplace Is Nothing Then
            Dim InitialAddress As String
            InitialAddress = CellToReplace.Address
            Dim MaskRow As Long
            Dim Mask As String
            On Error Resume Next
            Do
                MaskRow = WorksheetFunction.Match(sMask_I, _
                  Sheets("Sheet1").Range("C1:C" & Rows.Count), 0)
                Mask = Sheets("Sheet1").Range("D" & MaskRow).Value2
                If Sheets("Sheet1").Cells(CellToReplace.Row, 2) <> sNoReplace_I Then
                    CellToReplace.Value2 = Replace(CellToReplace.Value2, sMask_I, Mask)
                End If
                Set CellToReplace = .FindNext(CellToReplace)
            Loop While Not CellToReplace Is Nothing And CellToReplace.Address _
              <> InitialAddress
            On Error GoTo 0
        End If
    End With
End Sub

3 个答案:

答案 0 :(得分:0)

您可以尝试以下方法:

Option Explicit

Sub CallMask()
    Call Masks("Hello", "XYZ", "Hi")
End Sub

Sub Masks(sMask_I As String, sNoReplace_I As String, Replacement As String)
    Dim C As Range
    With ThisWorkbook.Sheets("Sheet1")
        For Each C In .Range("A1", "A" & .Cells(.Rows.Count, 1).End(xlUp).Row)
            If C Like "*" & sMask_I & "*" And C.Offset(0, 1) <> sNoReplace_I Then
                C.Replace sMask_I, Replacement
            End If
        Next C
    End With

End Sub

答案 1 :(得分:0)

在循环中使用Find()时,通常更容易将其抽象为单独的方法:

<!DOCTYPE html>
<html>
  <head>
    <style>
      .myclass[data-count] {
        position: relative;
      }

      .myclass[data-count][content='0'] {
        display: none;
      } 

      .myclass[data-count]:after {
        position: absolute;
        content: attr(data-count);
      }
    </style>
  </head>
  <body>
    <div>
      <div>
        <i class='myclass' id="comment" data-count='0' </i>
      </div>
    </div>
  </body>
</html>

答案 2 :(得分:0)

我已经测试了Damian,AJD和Mathieu建议的数组。这是最快的代码。

1600行的时间是:

  1. 我的新代码数组:8毫秒
  2. 带有后续代码的达米安代码:132毫秒
  3. 蒂姆·威廉姆斯(Tim Williams)带有“单独方法”的代码:402毫秒
  4. 我的第一个查找代码:511毫秒

这是新代码:

Sub CallMask()
    Call Masks("Hello", "XYZ")
End Sub

Sub Masks(ByVal sMask_I As String, ByVal sNoReplace_I As String)

    With ThisWorkbook.Sheets("Sheet1")
        Dim ArrayRangeToMask As Variant
        ArrayRangeToMask = .Range("A1:B" & .Cells(.Rows.Count, 2).End(xlUp).Row)

        Dim MaskRow As Long
        Dim Mask As String
        MaskRow = WorksheetFunction.Match(sMask_I, .Range("C1:C" & Rows.Count), 0)
        Mask = .Range("D" & MaskRow).Value2

        Dim RowMasking As Long
        For RowMasking = 1 To UBound(ArrayRangeToMask)
            If InStr(ArrayRangeToMask(RowMasking, 1), sMask_I) And _
              ArrayRangeToMask(RowMasking, 2) <> sNoReplace_I Then
                ArrayRangeToMask(RowMasking, 1) = _
                  Replace(ArrayRangeToMask(RowMasking, 1), sMask_I, Mask)
            End If
        Next RowMasking

        .Range("A1:B" & .Cells(.Rows.Count, 2).End(xlUp).Row) = ArrayRangeToMask
    End With

End Sub