【发布时间】:2015-03-24 05:13:34
【问题描述】:
第一次发帖,一直在寻找解决这个问题的方法,但还没有运气。
解释我的问题: 条款: 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 -定时器 - 尝试从 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
抱歉,帖子太长了,看到其他人因为不够详细而被扯掉,哈哈。
【问题讨论】:
-
worksheet.Calcuate 将在填充工作表时一直运行,它对您来说效果不佳。 SCADA 是否总是写入相同的单元格,它是否总是以相同的单元格(可能是 D52)完成,因为您可以将其用作参考点,然后仅保存值(使用 .calulate 来查看该单元格是否有值)
-
是的,它总是填充相同的单元格。仅保存值部分正在工作,但在加载外部 OPC 数据之前,因此由于缺少参考,计算的答案为 #N/A。如何使用 .calculate 检查外部数据是否已加载?
-
在每次单元格值更改时。Calculate 会调用您粘贴或未填充的所有单元格,因此在写入每个单元格时,公式都会更改为值。我现在给你写一个答案,告诉你该怎么做