Récupérer Tableau Page Web
Bonsoir Steelson,
Bonsoir à tous,
Suite du topo toujours très intéressante.
Je n'ai pas encore pris le temps de tout tester mais dès que je peux j'applique.
Si je ne me trompe pas, il reste encore le point 4 sur le fonctionnement asynchrone. Mais bien sûr prends ton temps.
Je ne sais pas si ma question est toujours dans le sujet mais je me lance.
Cela fait un moment que je tente de récupérer des données d'une base MySQL dans Excel mais sans succès. Cette base est hébergée chez ionos et ils me disent que ce n'est pas possible d'y accéder avec un connecteur ODBC sur un serveur partagé, il faudrait un serveur dédié.
J'ai vu pas mal de tuto à ce sujet, mais tous utilisent la connexion via ODBC.
Y-a-t-il une autre possibilité d'obtenir ces données sans passer par le connecteur ODBC ?
Si cette question n'est pas dans le sujet, j'ouvrirai un nouveau post ultérieurement.
Merci et bonne semaine
Bonjour,
Cela fait un moment que je tente de récupérer des données d'une base MySQL dans Excel mais sans succès. Cette base est hébergée chez ionos et ils me disent que ce n'est pas possible d'y accéder avec un connecteur ODBC sur un serveur partagé, il faudrait un serveur dédié.
J'ai vu pas mal de tuto à ce sujet, mais tous utilisent la connexion via ODBC.
Y-a-t-il une autre possibilité d'obtenir ces données sans passer par le connecteur ODBC ?
Si cette question n'est pas dans le sujet, j'ouvrirai un nouveau post ultérieurement.
Je ne peux pas te répondre sur ce point. Par contre il existe quelques spécialistes pointus sur cette question ici je pense. Donc repose ta question en ouvrant un autre sujet en mentionnant ODBC dans le sujet afin de capter leur attention.
Si je ne me trompe pas, il reste encore le point 4 sur le fonctionnement asynchrone.
Il reste un bout du point 3 : lorsque le site demande une "authentification tacite", plus explicitement renvoie un "jeton" ou "token" qui est joint de façon cachée au formulaire. Dans ce cas, j'utilise aussi une simulation avec navigateur, mais la seule façon dont j'ai réussi à le faire est via CreateObject("internetexplorer.application") et IE.navigate ... on parcours ensuite le site ouvert dans IE à la recherche des zones à renseigner et on clique virtuellement sur le bouton submit (IE renvoie alors les paramètres y compris le jeton). La réponse est alors copiée/collée dans le presse-papier. Toutefois elle ne comporte pas les balises html qui nous permettent ci-dessus de trouver facilement l'information car ce n'est pas un code source.
Voici un exemple (mais cela reste pointu donc tout à fait exceptionnel) https://forum.excel-pratique.com/viewtopic.php?p=838369#p838369
Option Explicit
Sub RecherchePrix()
'Dim IE As New InternetExplorer 'en référencant
Dim IE As Object 'en Late Binding
Dim IEDoc As HTMLDocument
Dim InputZoneTexte As HTMLInputElement
Dim MyHTML_Element As HTMLElementCollection
Dim pp As New DataObject, obj As Object, a As Object, cel As Range, resultat As String, resultat1 As String, resultat2 As String
Set IE = CreateObject("internetexplorer.application") 'en Late Binding
'Chargement d'une page Web
IE.navigate "https://www.prix-carburants.gouv.fr"
'Affichage de la fenêtre IE
IE.Visible = True
'Attente chargement
WaitIE IE
'on pointe le membre du document
Set IEDoc = IE.Document
WaitDoc IEDoc
'on pointe notre zone de texte
Set InputZoneTexte = IEDoc.all("_recherche_recherchertype[localisation]")
'on définit le texte que l'on veut saisir dans zone de rech
InputZoneTexte.Value = Range("A1").Value
InputZoneTexte.FireEvent "OnPaste"
'on pointe le bouton rech
For Each MyHTML_Element In IEDoc.getElementsByTagName("input")
If MyHTML_Element.Type = "submit" And MyHTML_Element.Value = "Voir la liste des stations" Then
MyHTML_Element.Click
Exit For
End If
Next
'Attente la fin de chargement
WaitIE IE
WaitDoc IEDoc
Application.SendKeys ("^a")
Application.SendKeys ("^c")
Application.Wait Now + TimeValue("00:00:01")
'Permet de quitter la page web
IE.Quit
'libération de la variable
Set IE = Nothing
Set IEDoc = Nothing
With pp
.GetFromClipboard
resultat = Split(.GetText(1), Range("A2").Value)(1)
Set obj = CreateObject("vbscript.regexp")
obj.Pattern = "[0-9][\.]([0-9])+"
Set a = obj.Execute(resultat)
If a.Count > 0 Then resultat1 = a(0) Else resultat1 = ""
obj.Pattern = "([0-9])+[\/]([0-9])+[\/]([0-9])+"
Set a = obj.Execute(resultat)
If a.Count > 0 Then resultat2 = a(0) Else resultat2 = ""
End With
Set cel = Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
cel = resultat2
cel.Offset(0, 1) = resultat1
End Sub
Sub WaitIE(IE As InternetExplorer)
Do Until IE.readyState = READYSTATE_COMPLETE And (Not IE.Busy)
DoEvents
Loop
End Sub
Sub WaitDoc(doc As HTMLDocument)
Do While Not doc.readyState = "complete"
DoEvents
Loop
End Sub
Si je ne me trompe pas, il reste encore le point 4 sur le fonctionnement asynchrone.
Pour terminer en apothéose, pour le point 4 lorsque les données sont appelées en "asynchrone" (AJAX = Asynchronous JavaScript and XML). En clair, la page est chargée. Une fois chargée elle appelle certains chapitres sans que toute la page soit rechargée, ceci à une certaine fréquence définie par le code source, ou bien en fonction du scoll qui permet de descendre dans la page.
Pour cela ... il n'y a pas de solutions ! ... (pour ma part).
Conclusion, il faut rester simple et efficient, avec une bonne fiabilité, donc
- éviter les sendkeys entre application excel et navigateur source de difficultés,
- privilégier les outils type
- PowerQuery
- recherche textuelle de l'information (split),
- recherche au moyen de getElementsByTagName, getElementsByClassName ou getElementById
- decodage d'un json.
Le reste relève plutôt de la bidouille.
Bonjour à tous,
Bonjour Steelson,
Me revoilà après un quelques jours de silence.
Tout d'abord, un très grand merci Steelson pour ce tuto qui m'a beaucoup aidée.
J'ai pris le temps de tout lire et de presque tout tester.
J'ai beaucoup aimé la partie json. Cela permet de récupérer facilement et rapidement les infos. Mais ce n'est pas toujours facile de trouver ces adresses.
Néanmoins, j'ai deux questions en suspens :
1) L'instruction obj.PutInClipboard me pose problème. Quand j'exécute un bout de code contenant cette instruction via un clic sur un bouton de commande (comme tu me l'as proposé Steelson dans ma demande initiale), tout se passe bien. Les tableaux s'affichent correctement dans la feuille.
En revanche, quand j'exécute le même bout de code en pas à pas, cette instruction me renvoie deux symboles "?". Quelle est l'explication à ce phénomène ?
2) Plutôt que de coller la totalité d'un tableau, je souhaiterais manipuler une à une les données d'un tableau. J'ai du mal à manipuler les éléments hiérarchiques d'un tableau (ligne, colonne et cellule).
Par exemple, j'aimerais coller chaque valeur (chaque cellule) d'un tableau récupéré dans une cellule particulière de ma feuille, chaque cellule n'étant pas nécessairement adjacente. Comment dois-je procéder ?
Merci d'avance pour vos réponses.
1) L'instruction
obj.PutInClipboardme pose problème. Quand j'exécute un bout de code contenant cette instruction via un clic sur un bouton de commande (comme tu me l'as proposé Steelson dans ma demande initiale), tout se passe bien. Les tableaux s'affichent correctement dans la feuille.En revanche, quand j'exécute le même bout de code en pas à pas, cette instruction me renvoie deux symboles "
?". Quelle est l'explication à ce phénomène ?
Comment fais-tu le pas à pas ?
Hypothèses : soit tu modifies le presse-papier par une action quelconque, soit c'est le pas à pas qui le modifie ... car tout passe par le presse-papier.
2) Plutôt que de coller la totalité d'un tableau, je souhaiterais manipuler une à une les données d'un tableau. J'ai du mal à manipuler les éléments hiérarchiques d'un tableau (ligne, colonne et cellule).
Par exemple, j'aimerais coller chaque valeur (chaque cellule) d'un tableau récupéré dans une cellule particulière de ma feuille, chaque cellule n'étant pas nécessairement adjacente. Comment dois-je procéder ?
Il faudrait voir avec PowerQuery comment faire. Là ce n'est pas ma spécialité (ni ma tasse de thé).
Pour ce qui est de la méthode que je propose ...
- soit on poursuit en copiant la totalité du tableau dans un onglet provisoire et ensuite on va à la pêche ...
il faut savoir qu'ici excel réagit bien quand on met dans le presse papier un tableau html complet commençant pas<table____et finissant par</table>et c'est cette propriété particulière d'excel que j'exploite
- soit on change de solution et on passe par un getElementsByTagName("td") car td caractérise une cellule d'un tableau ... mais il faudrait pouvoir l'identifier, or ce n'est pas sûr que chaque td ait un identifiant !
- ou pouvoir le repérer en comptant la xième cellule qui t'intéresse
Je préfère la première solution avec une copie intégrale du tableau et ensuite y puiser les seuls éléments intéressants.
As-tu un site et un exemple à explorer ?
Voici un exemple où je récupère quelques valeurs d'un tableau par INDIRECT
=SIERREUR(INDIRECT($A2&"!A3");"en attente ...")Sub Maj()
Dim URL$, obj As New DataObject
For n = 2 To Sheets("URL").Range("C" & Rows.Count).End(xlUp).Row
DoEvents
URL = Sheets("URL").Range("C" & n).Value
ActiveWorkbook.Sheets.Add After:=Worksheets(Worksheets.Count)
ActiveSheet.Name = Sheets("URL").Range("A" & n)
'On Error Resume Next
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", URL, False
.Send
If .Status = 200 Then
i = 1
txt = Split(.responsetext, "Dernières transactions")(1)
txt = "<table" & Split(Split(txt, "<table")(i), "</table>")(0) & "</table>"
obj.SetText txt
obj.PutInClipboard
Application.Wait Now + TimeValue("00:00:01")
ActiveSheet.Paste
End If
End With
Next
Sheets("URL").Select
End Sub
Bonsoir à tous,
Bonsoir Steelson,
Tout d'abord, désolée pour mon manque de réactivité mais j'ai pas mal de boulot en ce moment et avant de répondre, j'aime bien tout tester et avancer par moi-même.
1)
Comment fais-tu le pas à pas ?
Je pose un point d'arrêt dans l'éditeur VBA et j'avance à coup de F8.
Hypothèses : soit tu modifies le presse-papier par une action quelconque, soit c'est le pas à pas qui le modifie ... car tout passe par le presse-papier.
Je pensais que c'était le pas à pas qui modifiait l'action.
Car avec le fichier statoprono.xlsm, un clic sur le bouton "RELEVER" dans la feuille (et sans point d'arrêt dans l'éditeur) renvoie correctement les deux tableaux.
Mais avec le fichier table et indirect.xlsm de ton dernier message, les feuilles sont bien créées mais aucun tableau ne s'affiche dans les feuilles, seulement les deux points d'interrogation. Bizarre !
2) Je souhaite manipuler les données champ par champ car j'aimerais, en finalité, importer ces données dans une table Access. Pour l'instant, j'appréhende les différentes fonctionnalités sous Excel, c'est plus simple. Mais à terme, je souhaite importer tout dans Access.
Voici un exemple de page que je souhaiterais récupérer et intégrer dans une ou plusieurs tables d'une base Access : le tableau Arrivée définitive et les tableaux Rapports.
[https][://www.][geny][.com/]arrivee-et-rapports-pmu?id_course=1132126&info=2020-03-09-Bordeaux-Le+Bouscat-pmu-Prix+Kamok (désolée pour le bricolage, mais n'ayant pas encore dépassé les 10 messages, l'adresse est refusée).
Pour le moment, je récupère des infos sur des pages de Geny, mais je ne souhaite pas nécessairement me cantonner aux courses. Je pourrai très bien, par la suite, récupérer des prix de carburant (comme déjà proposé dans ton tuto) ou encore des cours de bourse, ou autre…
Voilà, si tu as des suggestions sur ce 2ème point, je suis preneuse.
Encore merci.
en pas à pas ? ou sans intervention ?Mais avec le fichier table et indirect.xlsm de ton dernier message, les feuilles sont bien créées mais aucun tableau ne s'affiche dans les feuilles, seulement les deux points d'interrogation.
Je souhaite manipuler les données champ par champ car j'aimerais, en finalité, importer ces données dans une table Access. Pour l'instant, j'appréhende les différentes fonctionnalités sous Excel, c'est plus simple.
- soit tu fais une macro qui va lire le tableau enregistré ... cela te donnera l'accès à chaque champ
- soit en VBA tu effectues un getElementsByTagName("TD"), je pense que c'est plus risqué car les tableaux ne sont pas toujours de la même taille
Tous les tableaux de la page ...
Ensuite il faut aller à la pêche !
Tu peux essayer aussi avec PowerQuery (je ne suis pas spécialiste)
Une nouvelle fois merci pour ton intervention Steelson.
1) Concernant le fichier table et indirect.xlsm :
en pas à pas ? ou sans intervention ?
- en pas à pas, les tableaux ne s'affichent jamais et les colonnes D, E et F de la feuille URL ne se mettent pas à jour.
- sans intervention, c'est très bizarre car des fois (très rarement), tout fonctionne et à d'autres moments, certains tableaux s'affichent et pas toujours les mêmes. C'est très aléatoire.
2)
- soit tu fais une macro qui va lire le tableau enregistré ... cela te donnera l'accès à chaque champ
Ta solution de faire une macro qui va lire le tableau enregistré me semble intéressante mais je ne sais pas bien manipuler les tableaux en mémoire. Peux-tu m'indiquer quelques pistes pour aller lire les infos dans un tableau sans l'avoir collé, au préalable, dans une feuille car, dans Access, je n'ai pas moyen de coller le tableau quelque part ? Il faut que je puisse accéder aux éléments directement dans le tableau mémorisé.
3) Fichier geny aspirer tous les tableaux.xlsm
La récupération des tableaux se passe bien et à chaque exécution de la macro. Ce qui est en contradiction avec mes explications du point n°1. Bizarre mais tant mieux !
Néanmoins, en mode pas à pas, les tableaux ne s'affichent toujours pas.
La macro fait bien le travail mais cela ne répond pas à mon besoin d'importer chaque élément dans un champ d'une table Access.
4)
Tu peux essayer aussi avec PowerQuery
Power Query est un bien bel outil mais n'est pas développé dans Access. J'évite donc de m'en servir.
Peux-tu m'indiquer quelques pistes pour aller lire les infos dans un tableau sans l'avoir collé, au préalable, dans une feuille
Avec ma méthode d'importer un tableau dans le presse-papier, ce n'est pas possible, il faut l'avoir collé au préalable.
Il faudrait utiliser getElementsByTagName("TD") ... un exemple de Pierrep56
Merci Steelson pour l'info.
J'ai commencé à "jouer" avec getElementsByTagName("TD") et c'est effectivement ce qui semble convenir à ce que je souhaite.
Le fichier que tu m'as joint est également d'une bonne aide.
Je pense pouvoir m'en sortir avec toutes ces informations.
Merci encore.