Je voudrais acheter sur gdax automatiquement. Mais mes entrées dans la fenêtre Montant ne sont pas reconnues. Je peux voir que sur le petit champ, qui dit: Total (LTC) ≈ 0.00000000
Mon code:
Sub test()
Dim ObjIE As New InternetExplorer
Dim Ohtml As HTMLDocument
Dim HTMLtags As IHTMLElementCollection
Dim HTMLtag As IHTMLElement
Dim HTMLobjekt As IHTMLElement
Dim item_limit As Object
Dim y As Integer
With ObjIE
.Visible = True
.navigate "https://www.gdax.com/trade/LTC-EUR"
Do Until .readyState = READYSTATE_COMPLETE: Loop
Set Ohtml = .document
End With
'Amount
Do
Set HTMLtags = Ohtml.getElementsByClassName("OrderForm_input-box_XkGmi")
DoEvents
Loop While HTMLtags.Length = 0
For Each HTMLtag In HTMLtags
If HTMLtag.Children(1).innerText = "EUR" Then
Set HTMLobjekt = HTMLtag.Children(0)
HTMLobjekt.Value = 100 ' this is the part that i excanged
End If
Next HTMLtag
'get the Total(LTC) to cross check
Do
Set HTMLtags = Ohtml.getElementsByClassName("OrderForm_total_6EL8d")
DoEvents
Loop While HTMLtags.Length = 0
For Each HTMLtag In HTMLtags
Debug.Print HTMLtag.innerText & "Total(LTC)"
Next HTMLtag
End Sub
Voici ce que dit le site lorsque le code est terminé:
et voici à quoi cela devrait ressembler, et lorsque je tape le nombre manuellement:
J'échange aussi la partie marquée avec des choses comme:
HTMLobjekt.innerText = 100
ou
HTMLobjekt.innerText = "100"
ou
HTMLobjekt.Value = "100"
mais rien n'a fonctionné.
Vous devez vous assurer que la page est entièrement chargée avant de prendre une initiative. J'ai vérifié la disponibilité d'une telle classe générée dynamiquement OrderBookPanel_text_33dbp
. Puis j'ai fait le reste ce que vous avez essayé de faire. Enfin, vous devez Focus
la cible avant de mettre ce montant dans l'espace réservé. En appliquant tout ce qui précède, votre script devrait ressembler davantage à celui-ci:
Sub Get_Value()
Dim HTML As HTMLDocument, tags As Object
Dim tag As Object, ival As Object
With CreateObject("InternetExplorer.Application")
.Visible = True
.navigate "https://www.gdax.com/trade/LTC-EUR"
While .Busy = True Or .readyState < 4: DoEvents: Wend
Set HTML = .document
Do: Set tags = HTML.querySelector("[class^='OrderBookPanel_text_']"): DoEvents: Loop While tags Is Nothing
Do: Set tag = HTML.querySelector("input[name='amount']"): DoEvents: Loop While tag Is Nothing
tag.Focus
tag.innerText = 100
Set ival = HTML.querySelector("[class^='OrderForm_total_']")
[A1] = ival.innerText
.Quit
End With
End Sub
Sortie en ce moment:
0.79139546
Pas une réponse complète, juste une direction. Ouvrez la page Web https://www.gdax.com/trade/LTC-EUR dans un navigateur (p. Ex. Chrome). Cliquez pour ouvrir le menu contextuel sur l'élément cible (étape 1 de la capture d'écran ci-dessous), cliquez sur Inspecter (2), à partir des outils de développement ouverts à droite peut voir l'élément cible (3), et qu'il existe un groupe d'écouteurs d'événements attachés à l'objet cible (4). Un des gestionnaires est input
au niveau du noeud document
. En réalité, le montant est mis à jour par ce gestionnaire d'événements, lorsque l'événement est diffusé à partir du noeud <input>
. Vous pouvez facilement vérifier cela en supprimant tous les autres gestionnaires d'événements (cliquez sur leur Remove boutons). Mais si vous supprimez particulièrement ce gestionnaire input
(5), il n'y aura aucune mise à jour (jusqu'à ce que vous rechargiez la page Web).
Par conséquent, pour imiter l'activité de l'utilisateur, vous devez créer cet objet événement input
et le répartir vers le noeud cible <input>
. Remarque Le noeud <input>
et l'événement de contrôle input
sont des choses complètement différentes ayant simplement le même nom.
L'exécution du gestionnaire d'événements de suivi dans IE peut être effectuée dans le débogueur. Ouvrez les outils de développement IE (appuyez sur F12), allez à l'onglet du débogueur (étape 1 de la capture d'écran ci-dessous), Points d'arrêt onglet (2), cliquez sur Ajouter un point d'arrêt d'événement (3), choisissez saisissez événement (4). Désormais, tout événement d'entrée mettra en pause l'exécution du code et ouvrira la fenêtre du débogueur (5).
Si vous essayez de saisir la zone de texte montant sur la page Web, le débogueur affichera le code de la fonction de gestionnaire d'événements:
Vous pouvez reprendre l'exécution (F5), ou faire un pas en avant/arrière/dehors. Pour voir l'objet d'événement transmis à la fonction, saisissez arguments
dans la console. Un appel est généré pour le gestionnaire d'événement standard après la saisie manuelle:
J'ai testé le code de test ci-dessous pour déclencher cet événement à partir de VBA:
Sub Test()
Dim oEvt As Object
With CreateObject("InternetExplorer.Application")
.Visible = True
.Navigate "https://www.gdax.com/trade/LTC-EUR"
Do While .ReadyState < 4 Or .Busy
DoEvents
Loop
With .Document
Do While IsNull(.querySelector("div.OrderForm_input-box_XkGmi input"))
DoEvents
Loop
Set oEvt = .createEvent("Event")
oEvt.initEvent "input", True, False, .parentWindow, 1
With .querySelector("div.OrderForm_input-box_XkGmi input")
.Focus
.Value = "1000"
.dispatchEvent oEvt
Stop
End With
End With
End With
End Sub
En conséquence, les mêmes actions que si vous saisissez le montant manuellement sont exécutées. Cela fonctionne sans aucune erreur. Mais Total (LTC) n'est pas mis à jour. Le débogueur interrompt également l'exécution et la sortie de l'objet événement est la suivante:
La seule différence est que la propriété isTrusted
est True
pour l'appel standard et False
pour l'appel via VBA. J'imagine que c'est pourquoi la mise à jour est ignorée quelque part dans le code du gestionnaire. J'ai essayé de retracer l'exécution du code complet jusqu'à l'achèvement du gestionnaire d'événements, mais il semble que ce soit un énorme travail d'ingénierie inverse, pour lequel je ne peux pas consacrer de temps pour le moment.
Actuellement, je suis coincé dans mes enquêtes à ce stade.
Désolé, je n’ai pas pu me rendre au travail, mais j’ai laissé tomber le problème.
J'ai réussi à trouver la syntaxe correcte pour créer et déclencher un événement dans les versions ultérieures d'Internet Explorer (grâce à this SO answer ). J'ai réussi à soulever un événement d'entrée pour la zone de saisie, suivi de omegastripes excellente lead .
Donc, cela fonctionne pour un fichier local que je donne ci-dessous qui a la même structure essentielle de la page réelle.
Mais lorsque je lance le code sur la page réelle, cela ne fonctionne tout simplement pas et je ne sais pas pourquoi.
Dans la mesure du possible, je fournis javascript à IE pour l'exécuter afin de minimiser les problèmes liés au pont d'interopérabilité VBA/COM/MSHTML. Je le fais en appelant window.execScript
en transmettant le javascript sous forme de chaîne.
J'espère que quelqu'un pourra ramasser ce ballon et le faire passer par-dessus la ligne de but. Pour moi, j'ai atteint la fin.
Voici le fichier HTML local
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input id="Button1" type="button" value="Programmatically write textbox value" onclick="TestAlert()" />
<form class="OrderForm_form_25r0u">
<ul class="OrderForm_trade-type_2QyK4">
<li class="OrderForm_trade-type-tab_uWGMp OrderForm_active_Di-9p">MARKET</li>
<li class="OrderForm_trade-type-tab_uWGMp">LIMIT</li>
<li class="OrderForm_trade-type-tab_uWGMp">STOP</li>
</ul>
<ul class="OrderForm_toggle_120Ka">
<li class="OrderForm_toggle-tab_bZZnC OrderForm_buy_38n5g OrderForm_active_Di-9p">BUY</li>
<li class="OrderForm_toggle-tab_bZZnC OrderForm_sell_3vYRQ">SELL</li>
</ul>
<div class="market-order">
<div class="OrderForm_section_2Znad">
<div class="OrderForm_section-header_fwFDB">Amount</div>
<div class="OrderForm_input-box_XkGmi">
<input type="number" step="0.01" min="0" name="amount" placeholder="0.00" value="" autocomplete="off" oninput="myOnInputHandler()">
<span>EUR</span>
</div>
</div>
</div>
<div class="OrderForm_order-total_3Mkdz">
<div>
<b>Total</b>
<span>(LTC)</span>
<b>≈</b>
</div>
<div class="OrderForm_total_6EL8d" >0.00000000</div>
</div>
</form>
<script language="javascript">
function myOnInputHandler() {
print_call_stack();
alert('you input something');
}
function print_call_stack() { console.trace(); }
function print_call_stack2() {
var stack = new Error().stack;
console.log("PRINTING CALL STACK");
console.log(stack);
}
function TestAlert() { setInputBox(document); }
function setInputBox() {
try {
var inputBox = document.querySelector('div.OrderForm_input-box_XkGmi input'); inputBox.value = 100; if (document.createEvent) { var event2 = document.createEvent("HTMLEvents"); event2.initEvent("input", true, true); event2.eventName = "input"; inputBox.dispatchEvent(event2); }
return ({ success: true });
}
catch (ex) {
return ({ exception: ex, myMsg: '#error in setInputBox!' });
}
}
</script>
</body>
</html>
Voici la VBA
Option Explicit
'* Tools - References
'* MSHTML Microsoft HTML Object Library C:\Windows\SysWOW64\mshtml.tlb
'* SHDocVw Microsoft Internet Controls C:\Windows\SysWOW64\ieframe.dll
'* Shell32 Microsoft Shell Controls And Automation C:\Windows\SysWOW64\Shell32.dll
Private Function ReacquireInternetExplorer(ByVal sMatch As String) As Object
Dim oShell As Shell32.Shell: Set oShell = New Shell32.Shell
Dim wins As Object: Set wins = oShell.Windows
Dim winLoop As Variant
For Each winLoop In oShell.Windows
If "C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE" = winLoop.FullName Then
Dim sFile2 As String
sFile2 = "file:///" & VBA.Replace(sMatch, "\", "/")
If StrComp(sFile2, winLoop.LocationURL, vbTextCompare) = 0 Then
Set ReacquireInternetExplorer = winLoop.Application
GoTo SingleExit
End If
End If
Next
SingleExit:
End Function
Sub test()
Dim objIE As InternetExplorer
Set objIE = New InternetExplorer
Dim oHtml As HTMLDocument
Dim HTMLtags As IHTMLElementCollection
Dim sUrl As String
sUrl = "C:\Users\Simon\source\repos\WebApplication2\WebApplication2\HtmlPage1.html"
'sUrl = "http://localhost:50367/HtmlPage1.html"
sUrl = "https://www.gdax.com/trade/LTC-EUR"
objIE.Visible = True
objIE.Navigate sUrl
If StrComp(Left(sUrl, 3), "C:\") = 0 Then
Stop '* give chance to clear the activex warning box for the local file
Set objIE = ReacquireInternetExplorer(sUrl)
End If
Do Until objIE.readyState = READYSTATE_COMPLETE: DoEvents: Loop
Set oHtml = objIE.Document
Do
'* wait for the input box to be ready
Set HTMLtags = oHtml.getElementsByClassName("OrderForm_input-box_XkGmi")
DoEvents
Loop While HTMLtags.Length = 0
Dim objWindow As MSHTML.HTMLWindow2
Set objWindow = objIE.Document.parentWindow
'* next line would be really useful if it worked because it prints the stack trace in the console window
'* and we would be able to see the needle in the haystack where te order total gets updated
'* works on local file but not on https://www.gdax.com/trade/LTC-EUR **sigh**
objWindow.execScript "var divTotal = document.querySelector('div.OrderForm_total_6EL8d'); divTotal.onchange = function() { console.trace(); }"
'* next line sets the input box and raises an event, works on local file but not on GDAX
objWindow.execScript "var inputBox = document.querySelector('div.OrderForm_input-box_XkGmi input'); inputBox.value = 100; if (document.createEvent) { var event2 = document.createEvent('HTMLEvents'); event2.initEvent('input', false, false); event2.eventName = 'input'; inputBox.dispatchEvent(event2); }"
'get the Total(LTC) to cross check
Do
'* wait for the order total div to be ready
Set HTMLtags = oHtml.getElementsByClassName("OrderForm_total_6EL8d")
DoEvents
Loop While HTMLtags.Length = 0
Dim divTotal As HTMLDivElement
Set divTotal = oHtml.querySelector("div.OrderForm_total_6EL8d")
Debug.Print divTotal.innerText & " Total(LTC)"
Stop
End Sub