J'exécute une macro dans un classeur Excel 2007 vierge sur un PC doté d'une licence Bloomberg. La macro insère des fonctions de Bloomberg dans le folio 1 qui extrait les données de la courbe de rendement. Les résultats de certaines fonctions supplémentaires dépendent de la finalisation et de l'affichage correct des données Bberg par les premières fonctions. Lorsque je parcours le programme, il n’affiche que «# N/A Requesting Data». . ' au lieu des résultats de la requête, peu importe la lenteur avec laquelle je vais. Étant donné que certaines fonctions dépendent des résultats de chaîne et de champ numérique, le programme génère une erreur d'exécution avec ce code. Lorsque j'arrête le débogage (arrêt complet du programme), toutes les valeurs Bberg qui auraient dû être renseignées apparaissent. Je veux que ces valeurs apparaissent pendant que le programme est toujours en cours d'exécution.
J'ai essayé d'utiliser une combinaison de DoEvents et Application.OnTime () pour restituer le contrôle au système d'exploitation et pour que le programme attende la mise à jour des données pendant une longue période, mais cela n'a pas fonctionné. Toutes les idées seraient utiles. Mon code est ci-dessous. wb est un classeur de niveau global et ws1 est une feuille de calcul de niveau global.
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
Un moyen de résoudre ce problème consiste à placer tous les sous-produits, etc. que vous souhaitez exécuter après avoir extrait les données bloomberg dans un autre sous-répertoire. Vous devez le faire chaque fois que vous appelez des informations Bloomberg. Si vous appelez un autre sous-maître dans le sous-maître "maître" après Application.OnTime Now + TimeValue ("00:00:15"), la tentative échouera - vous devez placer tous les sous-suivants dans un nouveau sous-maître.
Par exemple: au lieu de
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
CA devrait etre
Sub Master1()
Application.Run "RefreshAllStaticData"
Application.OnTime Now + TimeValue("00:00:15"), "Master2"
End Sub
Sub Master2()
OtherSub1
OtherSub2
OtherSub3
End Sub
J'espère que cela pourra aider
J'ai cherché Google pour BloombergUI.RefreshAllStaticData et j'ai été immédiatement dirigé vers cette page de M. Excel: http://www.mrexcel.com/forum/showthread.php?t=414626
Nous ne sommes pas supposés poster des réponses qui ne sont que des liens au cas où ce lien disparaîtrait et prend la réponse avec elle. Cependant, je ne suis pas sûr de bien comprendre la question ou la réponse pour la résumer.
Le lien Google existera probablement dans un avenir prévisible.
Au sein de M. Excel, la chaîne est la suivante: MrExcel Message Board> Forum aux questions> Questions Excel> Liens Bloomberg et macros.
Les informations clés semblent être:
Sur votre terminal Bloomberg, si vous tapez WAPI <GO>, vous trouverez une liste des API Bloomberg et des exemples téléchargeables.
En utilisant les informations du fichier d'aide dans cette zone, nous pouvons créer une solution plus robuste à l'aide de la bibliothèque de types de données Bloomberg. Aller aux outils | Références et ajouter une référence à cette bibliothèque. Ce code peut ensuite être utilisé pour renseigner les cellules:
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
Une fois que vous aurez testé la solution de M. Excel, vous pourrez peut-être mettre à jour cette réponse pour le bénéfice des futurs visiteurs.
J'ai rassemblé des informations sur le Web et écrit ce qui est imho est une version améliorée par rapport à tout ce que j'ai trouvé jusqu'à présent:
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
Cela devrait être une tâche arbitraire en appelant un sous-marin comme DoSomething ()
Public Sub DoSomething()
DoSomethingCallback
End Function
Cela appelle une fonction de "rappel" qui s'appellera jusqu'à ce que les données soient actualisées ou que le délai imparti soit atteint
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
Tout commentaire est apprécié. Une amélioration possible pourrait être de permettre au classeur et/ou à la feuille de calcul d’être une entrée de la fonction, mais je n’en ai pas vraiment vu la nécessité.
À votre santé
Bonjour, je pense avoir trouvé une solution à ce problème et je souhaite vraiment la partager avec vous.
Avant de commencer avec la vraie réponse Je veux m'assurer que tout le monde comprend comment Application.OnTime fonctionne réellement . Et si vous le savez déjà, vous pouvez passer en toute sécurité à LA SOLUTION ci-dessous.
Faisons un TOY EXAMLPE example avec deux sous-routines Sub First () et Sub Second () et une variable x déclarée à l'extérieur, de sorte qu'elle ait une portée à l'intérieur du module entier
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
Je pensais que les commandes étaient exécutées dans l'ordre suivant:
Il s'avère que ce n'est pas ainsi que fonctionne VBA; ce qui se passe à la place est:
Cela se produit indépendamment du temps d'attente de l'application. Donc, par exemple si dans mon exemple, après
Application.OnTime Now + TimeSerial(0, 0, 2), "Sub2"
VBA a pris 10 secondes pour exécuter la ligne
x = 2*x
il devra toujours terminer l'exécution de cette commande avant de passer à Sub Second ().
POURQUOI IS CECI IMPORTANT?
Parce que, à la lumière de ce que je viens d’expliquer, je peux maintenant vous montrer ma solution à la question OP. Ensuite, vous pourrez l'adapter à vos besoins.
Et oui!!! Cela fonctionne aussi avec For Loops!
LA SOLUTION
J'ai deux sous-routines:
BLPDownload () un où je rafraîchit un classeur et je dois attendre que les valeurs soient téléchargées pour pouvoir exécuter un autre code ...
BLPCheckForRefresh () où je vérifie si toutes les données ont été téléchargées
Donc, comme avant, je déclare deux variables avec une étendue de niveau module
Dim firstRefreshDone As Boolean, Refreshing As Boolean
Sub BLPDownload()
CHECK:
Ce que je fais juste en dessous est de:
Et c'est le truc. Pour quitter le sous-programme après avoir appelé Application.OnTime *
Dans BLPCheckForRefresh (), ce qui se passe est
enfin je rappelle le sous BLPDownload ()
If Not firstRefreshDone Then
Application.Run "RefreshEntireWorkbook"
Application.Run "RefreshAllStaticData"
Application.OnTime Now + TimeSerial(0, 0, 4), "BLPCheckForRefresh"
Exit Sub
Cette fois-ci cependant, firstRefreshDone = True, donc, si l'actualisation est également terminée, il passe à AFTER_REFRESH où vous pouvez mettre tout le code que vous voulez, sinon ...
ElseIf Not Refreshing Then
GoTo AFTER_REFRESH
si l'actualisation n'est pas terminée, c'est-à-dire si j'ai des cellules avec # N/A Requesting Data, elle appelle l'autre BLPCheckForRefresh Sub) et quitte à nouveau le sous-programme actuel.
Ce jeu amusant continue encore et encore jusqu'à ce que nous n'ayons plus de # N/A Demande de données dans notre UsedRange
Else
Refreshing = False
Application.OnTime Now + TimeSerial(0, 0, 4), "BLPCheckForRefresh"
Exit Sub
End If
AFTER:
some code ...
End Sub
C'est le sous-dossier où je vérifie si l'actualisation est terminée.
Sub BLPCheckForRefresh()
Dim rng As Range, cl As Range
Set rng = Foglio1.UsedRange
Comme expliqué ci-dessus, j'ai défini la valeur de firstRefreshDone = True
firstRefreshDone = True
Et c’est la boucle où je passe par chaque cellule de la gamme used à la recherche de # N/A Requesting Data
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
Enfin, je rappelle le sous-téléchargement BLP ()
Call BLPDownload
End Sub
C'est donc ma solution. Je travaille pour moi et avec un autre truc sale qui exploite toujours les instructions GoTo et une autre variable Scope au niveau du module qui tient compte du nombre d'itérations il est également possible d'utiliser cette structure dans les boucles For.
Cela étant dit, je tiens à souligner qu'à mon avis, la meilleure solution à ce problème consiste à utiliser l'API Bloomberg, comme l'a suggéré Tony Dallimore.
J'espère que cela t'aides!!