Excel不对Excell单元格上的循环脚本执行VBA

时间:2015-05-10 00:23:32

标签: excel vba excel-vba

我有一个Excel电子表格,其中包含用于计算固定范围内给定数据的加载项功能。按下F9或Shift-F9键,所有工作表都能正常工作。

我正在用VBA写一个for循环。它将范围从包含所有数据的一个工作表复制到另一个工作表。然后一次手动计算一个工作表,暂停,甚至计算两次,以确保每个工作表的执行。如果我在调试模式中通过整个for循环逐行手动逐步执行VBA代码,一切正常。但是,如果我按F5并以全速运行整个VBA循环。代码为for循环的许多(不是全部)连续迭代产生相同的结果,而我知道结果应该都是不同的。我的猜测是工作表变得陈旧,不会被新数据取代。

以下是我的VBA代码。如果有人看一看并帮助解决这个问题我真的很感激。有问题的代码的主要部分是“sht.Calculate”。

Option Base 1
#If VBA7 Then
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 'For 64 Bit Systems
#Else
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'For 32 Bit Systems
#End If

Function runCalibrate()
Dim xl As Workbook
Set xl = ThisWorkbook
nRowPerBlock = 15
yrs = Array("2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015")

Application.Calculation = xlCalculationManual

strikeSentinel = Array(1, 13)
maturitySentinel = Array(1, 10)

nRow = maturitySentinel(2) - maturitySentinel(1) + 1
nCol = strikeSentinel(2) - strikeSentinel(1) + 1
For j = 1 To UBound(yrs)
    Set a = Worksheets(yrs(j)).Cells(3, 2)
    For i = 0 To 11
        b = a.Offset(1 + nRowPerBlock * i, 1).Resize(nRow, nCol)
        xl.Sheets("SPX").Range("p4:ab13") = b

        'refresh required worksheets
        Call RefreshSheetNX(xl.Sheets("TODAY"))
        Call RefreshSheetNX(xl.Sheets("USD"))
        Call RefreshSheetNX(xl.Sheets("SPX"))
        Call RefreshSheetNX(xl.Sheets("EQ Model"))
        Call RefreshSheetNX(xl.Sheets("EQ Calibration"))

        c = xl.Sheets("EQ Calibration").Range("c18:c32")
        xl.Sheets("calibration time series").Cells(38, 2 + 12 * (j - 1) + i).Resize(15, 1) = c
    Next i
Next j

End Function

Function RefreshSheetNX(sht As Worksheet)
    On Error Resume Next
    sht.Cells.Dirty
    sht.Calculate
    Call Sleep(1000)
    sht.Calculate
    Call Sleep(1000)
End Function

正如Byron所说,我使用'Application.CalculateFullRebuild',如下面的代码所示。但当我通过'Application.CalculateFullRebuild'时,它根本没有反应。

Option Base 1
#If VBA7 Then
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 'For 64 Bit Systems
#Else
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'For 32 Bit Systems
#End If

Function runCalibrate()
Dim xl As Workbook
Set xl = ThisWorkbook
nRowPerBlock = 15
yrs = Array("2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015")

Application.Calculation = xlCalculationManual

strikeSentinel = Array(1, 13)
maturitySentinel = Array(1, 10)

nRow = maturitySentinel(2) - maturitySentinel(1) + 1
nCol = strikeSentinel(2) - strikeSentinel(1) + 1
For j = 1 To UBound(yrs)
    Set a = Worksheets(yrs(j)).Cells(3, 2)
    For i = 0 To 11
        b = a.Offset(1 + nRowPerBlock * i, 1).Resize(nRow, nCol)
        xl.Sheets("SPX").Range("p4:ab13") = b

        'refresh required worksheets
'        Call RefreshSheetNX(xl.Sheets("TODAY"))
'        Call RefreshSheetNX(xl.Sheets("USD"))
'        Call RefreshSheetNX(xl.Sheets("SPX"))
'        Call RefreshSheetNX(xl.Sheets("EQ Model"))
'        Call RefreshSheetNX(xl.Sheets("EQ Calibration"))
        Application.CalculateFullRebuild            

        c = xl.Sheets("EQ Calibration").Range("c18:c32")
        xl.Sheets("calibration time series").Cells(38, 2 + 12 * (j - 1) + i).Resize(15, 1) = c
    Next i
Next j

End Function

1 个答案:

答案 0 :(得分:0)

考虑使用Application.CalculateFullRebuild代替对每张工作表的Calculate多次调用。它将强制重新计算所有内容并重建依赖关系(顾名思义)。

根据公式在工作表之间的相关性,您可能无法触发正确的计算顺序,一次处理每个工作表。完全重建方法是刷新电子表格的“核选项”。具体来说,调用sht.Cells.Dirty然后调用sht.Calculate可能只会强制刷新当前工作表而不考虑其他工作表上的更改。