Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008
-
29 janv. 2008 à 18:31
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008
-
14 févr. 2008 à 15:17
Bonjour.
Je ne sais pas si je dois mettre ma question dans ce thème ou dans le thème base de données. Désolé si ce n'est pas au bon endroit.
J'ai un souci sur une lecture de fichier xml. (a partir d'un code en VBA)
Je dois récupérer le contenu d'une base de donnée pour mettre les informations sous une certaine forme sous une feuille excel.
Le problème est que l'exécution du code est beaucoup trop longue compte tenu de l'énormité du fichier xml.
Voici l'algo que j'utilise pour l'instant (je charge l'arbre dom et j'accède a tous mes éléments par une boucle for qui parcoure les différents items):
Dim xDoc As MSXML.DOMDocument
Dim xDomEl As MSXML.IXMLDOMElement
Dim siNbTag As Single
Dim siTagNum As Single
Dim aTagNameTab(2)
Dim iIndex As Integer
Dim sParamCode As String
Dim sType As String
Dim sTube As String
Dim sLength As String
Dim sCv As String
Dim sComment As String
Dim iNbChildTag As Integer
Set xDoc = New MSXML.DOMDocument
xDoc.validateOnParse = False
If xDoc.Load(PathFileXml) Then
For iIndex = 1 To 2
'**** exploitation des tags NumParam ou StringParam (suivant l'index de la boucle)
siNbTag = xDoc.getElementsByTagName(aTagNameTab(iIndex)).Length
If siNbTag > 0 Then
For siTagNum = 0 To siNbTag - 1
'**** récupération des données propre a chaque paramètre
sParamCode = xDoc.getElementsByTagName(aTagNameTab(iIndex)).Item(siTagNum).Attributes.getNamedItem("Mnemo").Text
sType = xDoc.getElementsByTagName(aTagNameTab(iIndex)).Item(siTagNum).Attributes.getNamedItem("Type").Text
iNbChildTag = xDomEl.getElementsByTagName("Comment").Length
If iNbChildTag > 0 Then
sComment = xDomEl.getElementsByTagName("Comment").Item(0).Text
End If
'**** Ecriture des données dans une feuille excel
Call WriteInfo(sParamCode, sType, sLength, sCv, sTube, sComment)
Next
End If
Next
End If
Ca fonctionne, mais ca met beaucoup trop de temps. Je cherche donc a changer mon algo.
J'ai cherché a parcourir en séquence l'arbre dom en testant les tags un par un pour récupérer l'info (sans m'occuper du numéro d'index des items), mais je n'ai pas trouvé comment faire. J'ai bien trouvé une méthode 'nextNode' que j'aurais aimé utiliser mais elle n'est pas disponible sur l'objet 'Element' que j'utilise. Quelqu'un pourrait-il m'aider en me disant quels objets et méthodes utiliser?
nhervagault
Messages postés6063Date d'inscriptiondimanche 13 avril 2003StatutMembreDernière intervention15 juillet 201137 1 févr. 2008 à 21:53
les requetes xpath permettent de faire des interrogations plus pousser donc plus rapide.
Tu peut prendre directement un attribut
ou un critre sur un attribut
http://jerome.developpez.com/xmlxsl/xpath/
cs_MPi
Messages postés3877Date d'inscriptionmardi 19 mars 2002StatutMembreDernière intervention17 août 201822 4 févr. 2008 à 22:55
J'avais déjà fait des recherches sur XML, il y a un bon bout de temps et je n'ai jamais donné suite par après, mais bon, voici la façon dont "il" procédait. C'est assez long à récupérer (± 5 secondes pour 10 colonnes sur 1800 lignes) puisque je laisse l'affichage (ScreenUpdating), mais ça pourrait, je pense, être optimisé...(?)
J'ai laissé les noms d'objets tels que déclarées à l'origine...
Public Sub LoadFichier()
Dim oDoc As msXML.DOMDocument
Dim fSuccess As Boolean
Dim oRoot As msXML.IXMLDOMNode
Dim oCountry As msXML.IXMLDOMNode
On Error GoTo HandleErr
Filename = OuvrirFichier("xml")
If Filename = "" Then Exit Sub
Set oDoc = New msXML.DOMDocument
' Load the XML from disk, without validating it. Wait
' for the load to finish before proceeding.
oDoc.async = False
oDoc.validateOnParse = False
fSuccess = oDoc.Load(Filename)
' If anything went wrong, quit now.
If Not fSuccess Then Exit Sub
Cells.ClearContents
' Get the root of the XML tree.
Set oRoot = oDoc.documentElement
' Inscrire les entêtes
For I = 0 To oRoot.childNodes.Item(1).childNodes.Length - 1
Range("A1").Offset(0, I) = oRoot.childNodes.Item(1).childNodes.Item(I).nodeName
Next
For Each oCountry In oRoot.childNodes I 0: J J + 1
Set oChildren = oCountry.childNodes
For Each oChild In oChildren
Range("A1").Offset(J, I) = oChild.Text
I = I + 1
Next
Next
Exit Sub
HandleErr:
MsgBox "Error " & Err.Number & ": " & Err.Description
End Sub
Peut-être est-ce plus rapide que ta méthode (?)
MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008 30 janv. 2008 à 10:54
Merci a toi nhervagault.
Je vais me documenter un peu sur les requètes xpath (que je ne connais pas du tout) et je reviendrai accepter la réponse.
J'espère seulement que c'est disponible sous VBA Excel.
En tout cas, encore merci pour cette rapide réponse.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008 1 févr. 2008 à 17:51
Merci encore pour ton aide et désolé pour la réponse tardive mais j'ai été bloqué sur autre chose.
Bref, j'ai en effet pu utiliser xDoc.SelectNodes mais a part si je n'y ai rien compris, je ne vois pas trop en quoi il va améliorer mes temps d'exécution car il me renvoie (en gros) la même chose que mon feu xDoc.getElementsByTagName et du coup mon code ne va pas plus vite avec ca. C'est peut-être plus rapide en effet mais j'ai l'impression que la grosse lenteur de mon code vient plus de l'utilisation de la boucle For qui parcourt les différents Item. Donc, en faisant le test, je n'ai pas obtenu d'amélioration.
Soit je n'ai pas compris comment utiliser tes méthodes a mon avantage, soit il me faudrait autre chose.
Le hic, est que je ne cherche pas a accéder a un seul champ mais a tous les "lister". (et yen a autour de 40000 du type NumParam et StatParam réunis)
Donc, il me faudrait plutot un moyen de passer d'un tag courant de niveau 'n', au tag suivant de niveau 'n' (de même parent quoi), sans s'occuper de la position ou l'on se trouve dans le fichier. ( pour s'affranchir du Item(iIndex) qui semble rallonger. )
Mais c'est peut-être une fausse piste.
J'en suis même venu a me demander (mais ca me parait ahurissant!!), vu que je dois forcément parcourir tous le fichier, si ca ne prnedrait pas moins de temps de parcourir ce fichier en séquence en le traitant comme un fichier ascii normal.
Bref, je patoge toujours donc si quelqu'un a une solution ou si nhervagault a une autre piste, tout est bienvenue.
Merci et si on se recroise pas ici, bon week end a tous.
cs_MPi
Messages postés3877Date d'inscriptionmardi 19 mars 2002StatutMembreDernière intervention17 août 201822 3 févr. 2008 à 14:39
Je ne suis pas vraiment certain, puisque je ne travaille pas avec xml, mais je pense que la lenteur vient du fait que tu inscris tes données à chaque tour de boucle... Peut-être pourrais-tu stocker tes infos dans un tableau (array) et une fois toutes les données lues, tu les inscris directement dans la feuille Excel (?)
Quelle version d'Excel utilises-tu ?
Et ton code est-il uniquement sous Excel ?
MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008 4 févr. 2008 à 16:44
@ nhervagault: Merci beaucoup pour le lien. Il est très interessant et m'apprend plus sur les différentes requètes que je pourrais utiliser (du style following ou d'autres du même style). C'est très puissant en fait. Je vais de ce pas faire des essais. Par contre, la puissance des requètes xPath est d'accéder rapidement aux éléments de l'arbre et je peux, comme tu l'as dit, "prendre directement un attribut ou un critere sur un attribut". Le problème, c'est que je veux presque tout récupérer et donc je ne pense pas utiliser toute la puissance qu'apporte ces requètes dans le cas d'un accés direct au cas par cas.
@ MPi: Bonjour et merci de t'être penché sur mon souci. Mais hélas, j'avais pensé au problème d'écriture dans excel a chaque boucle. J'ai donc fait le test en désactivant toute les écritures dans les feuilles et en gardant juste le parcours de l'arbre et la récupération des infos. Je n'ai même pas stocké les infos dans un tableau (donc ce n'est pas ca qui prend du temps non plus). Et malheureusement, le temps mis pour l'exécution a été très semblable (quelques minuscules secondes de gagner sur les11 premières minutes de fonctionnement- j'ai arrété ensuite-). La lenteur ne vient donc pas de là.
Sinon, j'utilise un vieil Excel: Excel 2000 (et ce serait bien si le code pouvait être compatible 97) et oui, tout mon code est sous excel.
Voila. Je vais faire des essais grace aux liens de nhervagault. Ca devrait améliorer un peu mais je ne pense pas avoir trouver réellement mon bonheur en y réfléchissant bien.... On verra.
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008 5 févr. 2008 à 12:12
@ nhervagault: Aaaargh!! Il veut pas m'utiliser toutes les requètes que j'ai vu sur ton lien!!! Il me sort des syntax error sur certaines. Je vais continuer a investiguer.
@ MPi:
En effet, je peux pas prendre ton code tel quel, mais c'est vrai que j'ai toujours préféré l'utilisation des 'for each'. Je sais pas pourquoi je n'y ai pas pensé.
En faisant une compilation des méthodes, du style, un 'for each' a la place de ma boucle 'for' et les requètes xPath pour cibler ensuite mes éléments a l'intérieur, j'arriverai peut-être a un bon gain.
Merci a vous deux, je vais essayer cet après-midi et je vous tiens au courant.
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008 6 févr. 2008 à 17:00
Bonjour a vous.
Je vous remercie pour votre aide.
Grace a vous, j'ai réussi a descendre de 2h30 d'exécution a 30 minutes. (en optant pour un mix des 2 solutions comme je l'avais dit).
30 minutes, c'est encore trop long et je vais essayer de changer encore certaines choses en espérant gagner un petit peu dans chaque boucle. On verra.
J'espère descendre en dessous des 20 minutes.
En tout cas merci pour votre aide a tous les 2 (je sais pas si on peut accepter 2 réponses mais on verra ^^)
Et si vous avez encore des conseils sur le sujet qui vous vienne, n'hésitez pas car je n'abandonne pas.
Acta_6
Messages postés29Date d'inscriptionmercredi 25 avril 2007StatutMembreDernière intervention22 avril 2008 14 févr. 2008 à 15:17
Merci pour ta remarque nhervagault.
C'est vrai que la balise n'est pas bonne. C'était une petite erreur. Mais le comportement était le même avec un nom d'attribut.
Enfin, pour l'instant, ca passe avec le mix que j'ai fait donc on va voir.
Merci en tout cas.