在自动计算之前等待外部数据加载? Excel中/ VBA

时间:2015-03-21 22:07:19

标签: excel vba excel-vba

第一次发布海报,一直在寻找解决这个问题但却没有运气的问题。

解释我的问题: 条款: OPC =用于过程控制的对象链接和嵌入(OLE) (允许其他应用程序使用PLC标签中的数据) PLC =可编程逻辑控制器(用于过程控制的计算机) SCADA =监控和数据采集(显示PLC值并允许控制的接口)

我有一个excel工作簿,它在PLC对某些值进行排序后的特定时间由SCADA系统(WonderWare> Intouch,软件)自动打开。此工作簿使用OPC客户端填充其单元,使用此方法访问它们:

=OPCLINK|EAST!'r[BELLWWPOWER]DailyValues_Z3[1,21]'

这种方法效果很好但是有很多单元格要填充,所以需要几秒钟。

我想要自动发生的是,在将具有公式的所有单元格更改为这些公式的值之前,填充这些单元格并完成任何计算。然后将工作簿保存在新工作簿名称(“PowerReports-YesterdaysDate”)下,并删除VBA代码并关闭两个工作簿(不保存原始工作簿,以保留公式)。

这一切都运行良好,除了它发生得太快,新保存的副本最终在所有带有OPC链接的单元格中只有“#N / A”。当我将第一张工作表的私有子作为“Worksheet_Activate()”而不是“Worksheet_Calculate()”时,代码将不会自动显示并等待鼠标单击其中一个工作表单元格(仅供参考:SCADA系统打开此工作簿到表1自动开始表1的代码)。在这种情况下,新副本将成功保存,但当代码统计信息自动过快时。如何在计算完成之前等待外部数据加载?

我尝试过的东西(我不知道它们是如何成功实施的......)像: -Application.Calculate -Application.RefreshAll -Timers - 从PLC获取标志 - 检查剩余的#N / As

似乎一个循环或类似的东西马上运行它不会让外部数据刷新。

Private Sub Worksheet_Calculate()

    ' When first sheet "Main" is activated, all formulas are replaced
    ' with their calculated values. The second sheet, "Monthly Values" is then activated

    Dim rng As Range, r As Range
    Set rng = Range("A1:D52")

    For Each r In rng
        If r.HasFormula Then
            r.Value = r.Value
        End If
    Next r

    Worksheets("Monthly Data").Activate

End Sub

Private Sub Worksheet_Activate()
    ' When second sheet "Monthly Values" is activated, all formulas are replaced
    ' with their calculated values. The sub routine, "SaveWithoutMacros" is then called

    Dim rng As Range, r As Range
    Set rng = Range("A1:BJ84")

    'Worksheets("Monthly Data").Calculate
    'If Not Application.CalculationState = xlDone Then
    'DoEvents
    'End If

    For Each r In rng
        If r.HasFormula Then
            r.Value = r.Value
        End If
    Next r

    Call SaveWithoutMacros
End Sub

Sub SaveWithoutMacros()
    'Purpose : To save a copy of the active workbook without macros

    Dim vFilename As String
    Dim wbActiveBook As Workbook
    '----------------------------------------------------------------------
    'Following two lines causes an error in Excel 97 - comment them out

    Dim VBComp As VBIDE.VBComponent
    Dim VBComps As VBIDE.VBComponents
    '----------------------------------------------------------------------

    ' Save to filename in format (yesterdays date) "PowerReports-DD-MM-YYYY"
    vFilename = ("D:\PowerReports\" & "PowerReport-" _
    & Format(Date - 1, "DD-MMM-YYYY") & ".xls")

    ActiveWorkbook.SaveCopyAs vFilename
    Set wbActiveBook = Workbooks.Open(vFilename)

    'Now strip all VBA, modules, userforms from the copy
    'This code is from Chip Pearson's website http://www.cpearson.com

    Set VBComps = wbActiveBook.VBProject.VBComponents

    For Each VBComp In VBComps
        Select Case VBComp.Type
        Case vbext_ct_StdModule, vbext_ct_MSForm, vbext_ct_ClassModule
            VBComps.Remove VBComp
        Case Else
            With VBComp.CodeModule
                .DeleteLines 1, .CountOfLines
            End With
        End Select
    Next VBComp
    wbActiveBook.Save ' saves new version after code is stripped

    ThisWorkbook.Saved = True ' sets save flag to true, does not actually save
    Application.Quit ' quits entire application, all workbooks
End Sub

对于冗长的帖子感到抱歉,看到其他人因为不够详细而被扯掉,哈哈。

2 个答案:

答案 0 :(得分:0)

现在这应该对您有用,通过仅测试最后填充的单元格,然后在将它们更改为值之前确保所有数据都已存在

基本上告诉workheet_calculate在最后一个单元格有公式

之前什么都不做

注意:请参阅此SCADA情况下修改后的代码以下的OP答案

 Private Sub Worksheet_Calculate()

        Dim rngLastCell As Range
        Set rngLastCell = Range("D52")

        If rngLastCell.HasFormula Then

            Dim rng As Range, r As Range
            Set rng = Range("A1:D52")


            For Each r In rng
                If r.HasFormula Then
                    r.Value = r.Value
                End If
            Next r

            Worksheets("Monthly Data").Activate
       End If
    End Sub

答案 1 :(得分:0)

结束了!感谢史蒂文·马丁给我一个跳跃点让这个工作,直到你发布你的答案,我不认为if语句在没有循环的情况下对我有用。

这对我有用:

 Private Sub Worksheet_Calculate()

    Dim rngLastCell As Range
    Set rngLastCell = Range("D52")

    If WorksheetFunction.IsNA(rngLastCell) = False Then
        Dim rng As Range, r As Range
        Set rng = Range("A1:D52")

        For Each r In rng
            If r.HasFormula Then
                r.Value = r.Value
            End If
        Next r

        Worksheets("Monthly Data").Activate
   End If
End Sub

然后同样的IF语句在第二张表的代码中检查“#N / A”,现在就像一个魅力。