web-dev-qa-db-ja.com

ブルームバーグのデータは、ExcelVBAマクロが終了するまで入力されません

ブルームバーグライセンスのPCで、空白のExcel2007ブックでマクロを実行しています。マクロは、イールドカーブデータを取得するBloomberg関数をsheet1に挿入します。一部の追加関数の結果は、最初の関数がBbergデータを終了して正しく表示することに依存しています。プログラムをステップスルーすると、「#N/ARequestingData」のみが表示されます。 。 。」どんなにゆっくり行っても、クエリの結果の代わりに。一部の関数は、入力される文字列および数値フィールドの結果に依存しているため、プログラムはそのコードで実行時エラーに遭遇します。デバッグを停止すると(プログラムの実行が完全に終了します)、入力されているはずのすべての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

エンドサブ

プライベートサブ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

サブHardCode()

Range("C2").Select
ActiveCell.FormulaR1C1 = "=BDP($A2,C$1)"
BloombergUI.RefreshAllStaticData

エンドサブ

9
Diana Tortolini

この問題を回避する方法は、ブルームバーグデータを別のサブにプルした後に実行するすべてのサブなどを配置することです。ブルームバーグ情報を呼び出すたびにこれを行う必要があります。 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

お役に立てば幸いです

6
CoreyB

BloombergUI.RefreshAllStaticDataをグーグルで検索すると、すぐにこのMr Excelページに移動しました: http://www.mrexcel.com/forum/showthread.php?t=414626

リンクが消えて回答を受け取った場合のリンクのみの回答を投稿することは想定されていません。しかし、質問や答えを十分に理解して要約できるかどうかはわかりません。

グーグルのリンクはおそらく近い将来存在するでしょう。

Mr Excel内のチェーンは、MrExcelメッセージボード>質問フォーラム> Excel質問>ブルームバーグリンクとマクロです。

重要な情報は次のようです。

ブルームバーグ端末でWAPI <GO>と入力すると、ブルームバーグAPIのリストとダウンロード可能な例が表示されます。

その領域のヘルプファイル情報を使用して、ブルームバーグデータ型ライブラリを使用してこれに対するより堅牢なソリューションを構築できます。ツールに移動|参照し、このライブラリへの参照を追加します。次に、このコードを使用してセルにデータを入力できます。

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氏のソリューションを試してみたら、将来の訪問者のためにこの回答を更新できるかもしれません。

4
Tony Dallimore

私はウェブの周りからいくつかの情報を集め、これまでに見つけたすべてのものと比較して改善されたバージョンである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

コメントをいただければ幸いです。考えられる改善点は、ワークブックやワークシートを関数の入力にすることですが、実際にはその必要性はわかりませんでした。

乾杯

1
Dave

こんにちは、私はこの問題の解決策を見つけたと思います。これを皆さんと共有したいと思います。

本当の答えから始める前にApplication.OnTimeが実際にどのように機能するかを全員が理解していることを確認したい。そして、あなたがすでに知っているなら、あなたは安全に以下にスキップすることができます解決策

TOY EXAMLPEの例を2つのサブルーチンSub First()とSub Second()で作成し、1つの変数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

コマンドは次の順序で実行されると思いました。

  1. x = 3
  2. Application.OnTime Now + TimeSerial(0、0、2)、 "Sub2"
  3. 次に、2秒間待機した後、Sub Second()でx = x + 1、したがって4
  4. 最後に、Sub First()に戻ります。ここでx = 2 * xであるため、最終的にxは8に等しくなります。

これはVBAの動作方法ではないことがわかりました。代わりに発生するのは:

  1. x = 3
  2. Application.OnTime Now + TimeSerial(0、0、2)、 "Sub2"
  3. ここで、Sub First()の残りのコードは、Sub Second()に切り替える前に、THE ENDまで実行されます。
  4. したがって、x = 2 * xは、Sub First()の最後まで表示されるコードのすべての行とともにすぐに実行されます。これで、xは6に等しくなります。
  5. 最後に、2秒間待機した後、Sub Second()、x = x + 1の命令を実行するため、最終的にxは7に等しくなります。

これは、アプリケーションを待機させる時間とは関係なく発生します。たとえば、私の例では、

Application.OnTime Now + TimeSerial(0, 0, 2), "Sub2" 

VBAはラインを実行するのに10秒かかりました

x = 2*x

sub Second()に切り替える前に、そのコマンドの実行を終了する必要があります。

なぜISこれは重要ですか?

私が今説明したことに照らして、OPの質問に対する私の解決策を示すことができるからです。次に、それをニーズに適合させることができます。

そしてYES !!!これはForループでも機能します!

解決策

2つのサブルーチンがあります。

  1. BLPDownload()ブックを更新し、他のコードを実行するために値がダウンロードされるのを待つ必要があるもの...

  2. BLPCheckForRefresh()ここで、すべてのデータがダウンロードされたかどうかを確認します

前と同じように、モジュールレベルのスコープで2つの変数を宣言します

Dim firstRefreshDone As Boolean, Refreshing As Boolean

Sub BLPDownload()

CHECK:

私がすぐ下で行うことは次のとおりです。

  • ブックを更新するようにVBAに既に指示したかどうかを確認します。もちろん、マクロを初めて実行するときは、まだ実行していません。したがって、firstRefreshDone = Falseであり、ifステートメントのこのブロックにステップインします。
  • 次に、他のサブルーチンBLPCheckForRefresh()を呼び出し、現在のサブルーチンを終了します。

そしてこれがトリックです。Application.OnTime*を呼び出した後にサブルーチンを終了するには

BLPCheckForRefresh()内で何が起こるか

  • firstRefreshDone = Trueの値を設定しました
  • usedRangeに、#N/Aリクエストデータのセルがあるかどうかを確認します。持っている場合、Refreshing = Trueの値。
  • 最後に、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データを要求しているセルがある場合は、他のサブルーチン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ループでも使用できます。

私の意見では、この問題の最善の解決策は、TonyDallimoreによって提案されたBloombergAPIを使用することであると指摘したいと思います。

お役に立てれば!!

0
Hard Core