我正在使用Bloomberg许可证的PC上的空白Excel 2007工作簿中运行宏。宏将Bloomberg函数插入到sheet1中,以获取收益率曲线数据。一些附加功能的结果取决于完成和正确显示Bberg数据的第一个功能。当我单步执行程序时,它只显示'#N / A请求数据。 。 “。而不是查询的结果,无论我走得多慢。由于某些函数依赖于填充的字符串和数字字段结果,因此程序会在该代码处遇到运行时错误。当我停止调试 - 完全结束运行程序时 - 然后出现应该填充的所有Bberg值。我希望在程序运行时显示这些值。
我尝试使用DoEvents和Application.OnTime()的组合将控制权返回给操作系统,并使程序等待很长时间进行数据更新,但都没有工作。任何想法都会有所帮助。我的代码如下。 wb 是全局级工作簿, ws1 是全局级工作表。
Public Sub Run_Me()
'Application.DisplayAlerts = False
'Application.ScreenUpdating = False
Call Populate_Me
Call Format_Me
'Application.DisplayAlerts = True
'Application.ScreenUpdating = True
End Sub
Private Sub Populate_Me()
Dim lRow_PM As Integer
Dim xlCalc As XlCalculation
Set wb = ThisWorkbook
Set ws1 = wb.Sheets(1)
'clear out any values from previous day
If wb.Sheets(ws1.Name).Range("A1").Value <> "" Then
wb.Sheets(ws1.Name).Select
Selection.ClearContents
End If
xlCalc = Application.Calculation
Application.Calculation = xlCalculationAutomatic
Range("A1").Value = "F5"
Range("B1").Value = "Term"
Range("C1").Value = "PX LAST"
Range("A2").Select
ActiveCell.FormulaR1C1 = "=BDS(""YCCF0005 Index"",""CURVE_MEMBERS"",""cols=1;rows=15"")"
BloombergUI.RefreshAllStaticData
Range("B2").Select
ActiveCell.FormulaR1C1 = "=BDS(""YCCF0005 Index"",""CURVE_TERMS"",""cols=1;rows=15"")"
BloombergUI.RefreshAllStaticData
Application.OnTime Now + TimeValue("00:00:10"), "HardCode"
'******more code*******'
End Sub
Sub HardCode()
Range("C2").Select
ActiveCell.FormulaR1C1 = "=BDP($A2,C$1)"
BloombergUI.RefreshAllStaticData
End Sub
答案 0 :(得分:6)
解决此问题的一种方法是在将bloomberg数据拉入另一个子数据库之后放置要运行的所有子等。每次拨打彭博信息时都必须这样做。如果在Application.OnTime Now + TimeValue(“00:00:15”)之后调用“master”子中的另一个子,它将失败 - 您必须将所有子跟随放入一个新的主子。
例如: 而不是
Sub Master1()
Application.Run "RefreshAllStaticData"
Application.OnTime Now + TimeValue("00:00:15"), "OtherSub1"
'This will cause the Bloomberg Data to not refresh until OtherSub2 and 3 have run
OtherSub2
OtherSub3
End Sub
应该是
Sub Master1()
Application.Run "RefreshAllStaticData"
Application.OnTime Now + TimeValue("00:00:15"), "Master2"
End Sub
Sub Master2()
OtherSub1
OtherSub2
OtherSub3
End Sub
希望有所帮助
答案 1 :(得分:4)
我用Google搜索了BloombergUI.RefreshAllStaticData并立即被带到了Excel先生页面:http://www.mrexcel.com/forum/showthread.php?t=414626
如果链接消失并接受答案,我们不应该发布只有链接的帖子答案。但是,我不确定我是否完全理解了这个问题或答案。
在可预见的未来,Google链接可能会存在。
在Excel先生中,该连锁店是:MrExcel留言板&gt;问题论坛&gt; Excel问题&gt;彭博链接和宏。
关键信息似乎是:
如果您输入WAPI&lt;在您的Bloomberg终端上GO&gt;你会找到Bloomberg API的列表和可下载的例子。
使用该区域中的帮助文件信息,我们可以使用Bloomberg数据类型库为此构建更强大的解决方案。转到工具|引用并添加对此库的引用。然后可以使用此代码填充单元格:
Sub Test2()
Dim vResults, vSecurities, vFields
Dim objBloomberg As BLP_DATA_CTRLLib.BlpData
'fill our arrays - must be 1 dimension so we transpose from the worksheet
With Application.WorksheetFunction
vSecurities = .Transpose(Sheet1.Range("B2:B4").Value)
vFields = .Transpose(.Transpose(Range("C1:H1").Value))
End With
Set objBloomberg = New BLP_DATA_CTRLLib.BlpData
objBloomberg.AutoRelease = False
objBloomberg.Subscribe _
Security:=vSecurities, _
cookie:=1, _
Fields:=vFields, _
Results:=vResults
Sheet1.Range("C2:H4").Value = vResults
End Sub
一旦您尝试了Excel先生的解决方案,也许您可以更新此答案,以便将来访问者受益。
答案 2 :(得分:1)
我从网络上收集了一些信息,并写了一下与目前为止我发现的所有内容相比,imho是一个改进版本:
Private WaitStartedAt As Double
Private Const TimeOut As String = "00:02:00"
Public Function BloomCalc(Callback As String) As Boolean
Dim rngStillToReceive As Range
Dim StillToReceive As Boolean
Dim ws As Worksheet
StillToReceive = False
If WaitStartedAt = 0 Then
WaitStartedAt = TimeValue(Now())
End If
If TimeValue(Now()) >= WaitStartedAt + TimeValue(TimeOut) Then
GoTo errTimeOut
End If
For Each ws In ActiveWorkbook.Worksheets
Set rngStillToReceive = ws.UsedRange.Find("*Requesting Data*", LookIn:=xlValues)
StillToReceive = StillToReceive Or (Not rngStillToReceive Is Nothing)
Next ws
If StillToReceive Then
BloomCalc = False
Application.OnTime Now + (TimeSerial(0, 0, 1)), Callback
Else
WaitStartedAt = 0
BloomCalc = True
End If
Exit Function
errTimeOut:
Err.Raise -1, , "BloomCalc: Timed Out. Callback = " & Callback
End Function
通过调用像DoSomething()
这样的子句,它应该是一个任意的任务Public Sub DoSomething()
DoSomethingCallback
End Function
调用“回调”函数,该函数将自行调用,直到数据刷新或达到时间限制
Public Sub AutoRunLcbCallback()
If BloomCalc("AutoRunLcbCallback") Then
MsgBox "Here I can do what I need with the refreshed data"
' for instance I can close and save the workbook
ActiveWorkbook.Close True
End If
End Sub
任何评论都表示赞赏。可能的改进可能是允许工作簿和/或工作表作为函数的输入,但我真的没有看到它的需要。
干杯
答案 3 :(得分:0)
您好我认为我找到了解决此问题的方法,我真的想与您分享。
在开始真正的答案之前我想确保每个人都了解Application.OnTime的实际工作方式。如果您已经知道,那么您可以安全地跳到下面的解决方案。
让我们做一个 TOY EXAMLPE 示例,其中包含两个子程序Sub First()和Sub Second()以及一个在外部声明的变量x,以便它在整个模块中具有范围
Dim x as integer
Sub First()
x = 3
Application.OnTime Now + TimeSerial(0, 0, 2), "Sub2"
x = 2*x
End Sub
Sub Second()
x = x + 1
End Sub
我认为命令按以下顺序执行:
事实证明,这不是VBA运作的方式;相反的是:
这与您使应用程序等待的时间无关。例如,如果在我的例子中,在
之后Application.OnTime Now + TimeSerial(0, 0, 2), "Sub2"
VBA用了10秒钟来执行
行x = 2*x
在切换到Sub Second()之前,它仍然必须完成该命令的执行。
为什么这么重要?
因为根据我刚才解释的内容,我现在可以向您展示我对OP问题的解决方案。然后,您可以根据自己的需求进行调整。
并且是的!这也适用于For Loops!
解决方案
我有两个子程序:
BLPDownload()我刷新工作簿的地方,我必须等待值下载才能执行其他代码...
BLPCheckForRefresh(),我检查是否已下载所有数据
就像之前一样,我用Module-Level Scope
声明了两个变量Dim firstRefreshDone As Boolean, Refreshing As Boolean
Sub BLPDownload()
CHECK:
我在下面做的是:
这就是诀窍。在调用Application.OnTime *
后退出子程序在BLPCheckForRefresh()内部会发生什么
最后我回调了Sub BLPDownload()
If Not firstRefreshDone Then
Application.Run "RefreshEntireWorkbook"
Application.Run "RefreshAllStaticData"
Application.OnTime Now + TimeSerial(0, 0, 4), "BLPCheckForRefresh"
Exit Sub
这一次,firstRefreshDone = True所以,如果刷新完成,它会转到AFTER_REFRESH,您可以在其中放置所需的所有代码,否则......
ElseIf Not Refreshing Then
GoTo AFTER_REFRESH
如果刷新没有完成,即如果我有#N / A请求数据的单元,它调用另一个Sub BLPCheckForRefresh(),它再次退出当前的子程序。
这个有趣的游戏一直持续到我们的UsedRange不再有#N / A请求数据
Else
Refreshing = False
Application.OnTime Now + TimeSerial(0, 0, 4), "BLPCheckForRefresh"
Exit Sub
End If
AFTER:
some code ...
End Sub
这是我检查刷新是否完成的子。
Sub BLPCheckForRefresh()
Dim rng As Range, cl As Range
Set rng = Foglio1.UsedRange
如上所述,我设置了firstRefreshDone = True的值
firstRefreshDone = True
这是循环,我遍历usedrange中寻找#N / A请求数据的每个单元格
On Error Resume Next
For Each cl In rng
If InStr(cl.Value2, "#N/A Request") > 0 Then
Refreshing = True
Exit For
End If
Next cl
On Error GoTo 0
最后我回拨Sub BLPDownload()
Call BLPDownload
End Sub
所以这是我的解决方案。我为我工作并使用另一个肮脏的技巧,它总是利用GoTo语句和另一个模块级范围变量来计算迭代次数也可以在For循环中使用这个结构。 < / p>
话虽如此,我想指出,在我看来,这个问题的最佳解决方案是使用Tony Dallimore建议的Bloomberg API。
希望这会有所帮助!!