第一次发布海报,一直在寻找解决这个问题但却没有运气的问题。
解释我的问题: 条款: 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
对于冗长的帖子感到抱歉,看到其他人因为不够详细而被扯掉,哈哈。
答案 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”,现在就像一个魅力。