2

我正在研究一个 VBA 宏,我遇到了一些非常奇怪的行为。

它可以正常工作Application.ScreenUpdating = True,甚至在屏幕更新关闭并使用 VBA 调试器单步执行宏时也可以正常工作。

不幸的是,仅在屏幕更新关闭的情况下运行宏会导致Find函数在以下代码中失败:

Application.StatusBar = "Extracting data and updating tables..."
Application.ScreenUpdating = False
Application.DisplayAlerts = False

Workbooks.Open FileName:=Save_folder & "new_data.xls"
Workbooks("new_data.xls").Sheets("data").Range("B9:B39").Copy

Dim tempdate As Date, startCell As Range

tempdate = DateAdd("d", -1, Now)
tempdate = DateSerial(Year(tempdate), Month(tempdate), 1) 'Start of the month
Dim strdate As String
strdate = Format(tempdate, "Short Date")

Set startCell = ThisWorkbook.Sheets("Raw Data").Cells.Find(What:=CDate(strdate), After:=ThisWorkbook.Sheets("Raw Data").Range("A1"), LookIn:=xlFormulas _
 , LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)

If startCell Is Nothing Then
    MsgBox "Couldn't find a date equal to the start of yesterday's month."
    Exit Sub
Else
    startCell.Offset(0, 1).PasteSpecial xlPasteValues, Transpose:=False
End If

在调用上方添加这个简短的代码片段来Cells.Find解决问题:

'Wait one second, to appease the Excel object creation gods
Application.StatusBar = "Wait one second..."
Application.Wait Now + TimeValue("00:00:01")
Application.StatusBar = "Pasting values..."

抛出一个MsgBox或提示等也允许Find成功。

我的问题是,我为什么要等?

4

2 回答 2

6

我无法产生这种行为。看截图

Sub Sample()
    Dim tempdate As Date, startCell As Range
    Dim strdate As String

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

    tempdate = DateAdd("d", -1, Now)
    tempdate = DateSerial(Year(tempdate), Month(tempdate), 1) 'Start of the month

    strdate = Format(tempdate, "Short Date")

    Set startCell = ThisWorkbook.Sheets("Raw Data").Cells.Find(What:=CDate(strdate), LookIn:=xlFormulas _
     , LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)

    If startCell Is Nothing Then
        MsgBox "Couldn't find a date equal to the start of yesterday's month."
    Else
        MsgBox "Found"
    End If

    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub

快照

在此处输入图像描述

更新

如果您的代码中发生了很多事情,请使用DoEvents以便代码将控制权传递给操作系统,以便操作系统可以处理其他事件。

于 2012-08-01T15:53:47.203 回答
0

我在尝试解决相同的问题时遇到了这个线程,我能够通过在运行任何 .Find 函数之前简单地激活工作表来绕过 DoEvents 技巧。

您的代码和我的代码之间唯一押韵的是它们都使用 .Find 函数。也许这就是阻塞操作系统的原因。

于 2015-02-13T00:43:36.663 回答