【问题标题】:VBA .Findnext stuck on LoopVBA .Findnext 卡在循环上
【发布时间】:2023-03-21 06:00:02
【问题描述】:

我一直在尝试制作一个宏来突出显示整个行的日期,如果它们落入特定的日期间隔。我遇到的问题是:当宏找到某个日期时,它会为该日期的整行着色,然后应该使用 .findnext 进入下一个 .find。但是宏在这里陷入了循环

Do While Not c Is Nothing
     c.EntireRow.Interior.Color = vbCyan
     Set c = Dates.FindNext
Loop

c 值为 2021.03.01(作为 StartDate) 我的代码如下所示:

        Private Sub CommandButton2_Click()
Dim c As Range
Dim first As String
Dim last As String
Dim StartDate As Date
Dim EndDate As Date
Dim DateLooper As Date

    first = CLng(Range("E2").Value)
    last = CLng(Range("G2").Value)

For Each Cell In ActiveSheet.Range("H2:H" & Cells(Rows.Count, 8).End(xlUp).Row)
  Sheet = Cell
  StartDate = first
  EndDate = last

  For DateLooper = StartDate To EndDate
    Set Dates = Worksheets(Sheet).Range("P:P")
    Set c = Dates.Find(What:=DateLooper)

        Do While Not c Is Nothing
        c.EntireRow.Interior.Color = vbCyan
        Set c = Dates.FindNext(c)
        Loop

  Next DateLooper
Set c = Nothing
Next Cell
End Sub

这里有什么问题?感谢您的时间和帮助。 也许是因为 c 是一个日期?

【问题讨论】:

  • 日期可能很棘手,但如果 c 不是空的话,你的 Do 循环将永远不会结束。退出的常用方法是存储第一个找到的单元格的地址,然后循环,直到你回到那个地址,这意味着你回到了你开始的地方。
  • H:H 列是否已排序?
  • H:H 列有多少行?我的意思是一个近似值...

标签: vba loops date find do-while


【解决方案1】:

使用标准突出显示整行单元格

  • 将开始和结束日期写入变量(E2G2)。
  • 循环遍历包含工作表名称的列 (H)。
  • 在每个工作表 (dws) 中,循环访问日期 (DateLooper),并尝试在日期列 (P) 的单元格 (dCell) 中查找日期。
  • 如果找到,突出显示单元格的整行。

守则

Option Explicit

Private Sub CommandButton2_Click()
    
    Dim ws As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    Dim sws As Worksheet: Set sws = ActiveSheet
    Dim StartDate As Date: StartDate = sws.Range("E2").Value
    Dim EndDate As Date: EndDate = sws.Range("G2").Value
    Dim wrg As Range
    Set wrg = sws.Range("H2", sws.Cells(sws.Rows.Count, "H").End(xlUp))
    
    Dim dws As Worksheet
    Dim drg As Range
    Dim dCell As Range
    Dim wCell As Range
    Dim DateLooper As Date
    Dim fAddr As String
    
    For Each wCell In wrg.Cells ' loop through list of worksheet names
        Set dws = wb.Worksheets(wCell.Value)
        Set drg = dws.Range("P2", dws.Cells(dws.Rows.Count, "P").End(xlUp))
        For DateLooper = StartDate To EndDate ' loop through dates
            Set dCell = drg.Find(What:=DateLooper) ' find dates
            If Not dCell Is Nothing Then
                fAddr = dCell.Address
                Do
                    dCell.EntireRow.Interior.Color = vbCyan
                    Set dCell = drg.FindNext(dCell)
                Loop Until dCell.Address = fAddr
            End If
            Set dCell = Nothing
        Next DateLooper
    Next wCell

End Sub

【讨论】:

  • 您好,我已经尝试了您的代码,直到某一刻一切正常。如果具有所需日期的单元格与另一个单元格合并(2 个单元格中的 1 个日期),则 ,,Loop 直到 dCel.Adress = fAddr 返回错误,因为上一行将 dCell 设置为空,因此 Adress 返回 varbiable 或未设置对象.在 ,,Loop until,, ?? 之前需要另一个 ,, is nothing" 处理程序
  • 您没有提到任何合并的单元格。当代码遇到合并的单元格时,您希望发生什么?
  • 是的,这些合并的单元格很少见,但它们仍然存在。我希望代码能突出显示合并单元格的整行。
  • 也许与 ,,MergeArea.Rows.Count,,, ?
【解决方案2】:

请尝试下一个方法。未经测试,但它应该足够快。它在数组元素之间迭代,并将要着色的范围放在一个联合范围中,一次着色,最后:

Private Sub CommandButton2_Click()
 Dim StartDate As Date, rngCol As Range, EndDate As Date
 Dim firstRow As Long, arrD, i As Long, rngH As Range

 Set rngH = Range("H2:H" & cells(rows.count, 8).End(xlUp).row)
 arrD = rngH.value
 StartDate = Range("E2").value
 EndDate = Range("G2").value
 firstRow = rngH.Find(what:=Date, LookIn:=xlValues, lookat:=xlWhole).row - 1lookat:=xlWhole).row - 1
  For i = firstRow To UBound(arrD)
    If CDate(arrD(i, 1)) = EndDate Then Exit For
    If CDate(arrD(i, 1)) = StartDate Then
        If rngCol Is Nothing Then
            Set rngCol = cells(i + 1, 1)
        Else
            Set rngCol = Union(rngCol, cells(i + 1, 1))
        End If
    End If
  Next i
  If Not rngCol Is Nothing Then rngCol.EntireRow.Interior.Color = vbCyan
End Sub

假设 H:H 列按升序排序。

【讨论】:

  • 感谢您的时间和帮助,但我已经开始分析VBasic2008的另一个代码,因为它是我的代码修改版本。
  • @baxius:我只尝试提供最快的方式。如果你不方便,我没有问题。
【解决方案3】:

将 fAddress 变量和条件添加到循环

Private Sub CommandButton2_Click()
Dim c As Range
Dim first As String
Dim last As String
Dim StartDate As Date
Dim EndDate As Date
Dim DateLooper As Date
dim fAddress as String
    first = CLng(Range("E2").Value)
    last = CLng(Range("G2").Value)

For Each Cell In ActiveSheet.Range("H2:H" & Cells(Rows.Count, 8).End(xlUp).Row)
  Sheet = Cell
  StartDate = first
  EndDate = last

  For DateLooper = StartDate To EndDate
    Set Dates = Worksheets(Sheet).Range("P:P")
    Set c = Dates.Find(What:=DateLooper)
    if not c is nothing then 
        fAddress  = c.address
        Do 
           c.EntireRow.Interior.Color = vbCyan
           Set c = Dates.FindNext(c)
        Loop While Not c Is Nothing and fAddress  <> c.address
    end if
  Next DateLooper
Set c = Nothing
Next Cell
End Sub

【讨论】:

  • true 应该是字符串类型变量比较或没有地址属性。
  • 使用If Not c Is Nothing Then,您已经确定c 是“某物”(单元格范围)。因此,在Do...Loop 中它永远不会一无所有,因为FindNext 总是会找到“某物”,即使它始终是相同的“某物”。只有通过检查地址,您才能避免死循环,因此在Loop While... 中,Not c Is Nothing And 部分是多余的。
  • 是的,我只是专注于添加代码的必要部分。甚至没有测试它:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
相关资源
最近更新 更多