aforpien
Messages postés118Date d'inscriptionlundi 6 novembre 2000StatutMembreDernière intervention12 mai 2010
-
26 févr. 2009 à 18:15
aforpien
Messages postés118Date d'inscriptionlundi 6 novembre 2000StatutMembreDernière intervention12 mai 2010
-
3 mars 2009 à 13:26
Bonsoir à tous,
Dans le cadre de la création d'un logiciel de supervision au seins de mon entreprise, je suis confronté au problème suivant :
J'utilise l'utilitaire WMIC afin de récupérer des informations sur les disques durs et lecteurs DAT.
Cet utilitaire me génère un fichier texte, alimenté de toutes les données. la première ligne indique le nom des colonnes, et les informations suivent sur les lignes suivants, colonnes par colonnes.
Tout d'abord j'ai pensé récupérer toutes ces informations par rapport à leurs position, mais le problème est que lorsque j'interroge des serveurs ayant par exemple un disque ou lecteur de marque différente, les colonnes sont agrandies.
Résultat : les informations que je récupère sont fausses car il y a un décalage.
Ma question est donc : Comment puis-je faire pour à coup sur récupérer les bonnes informations même si les colonnes n'ont pas la même taille d'un fichier à l'autre ?
Car à la base j'avais pensé créé un type, mais le problème d'un type est qu'il faut déclarer la longueur champs.
J'ai ensuite penser à splitter tout les espace pour récupérer les valeurs dans un tableau, mais le problème est que je peux avoir plusieurs dizaines d'espaces si le nom de la colonne est long.
Donc soit j'enlève un espace a chaque fois, et il en reste une multitude d'autres, soit je les supprimes tous, et la ma chaine de caractère est complètement collée donc inexploitable.
Existe-t-il un moyen de récupérer toutes ces infos dans un tableau même si la longeur des colonnes est variable ?
Ou bien j'ai pensé à copier le contenu du fichier texte dans un fichier excel, pour récupérer les meme colonnes partout, mais mon problème est le même, so I need Help please !!!
Merci
Cordialement,
r1r2
Messages postés22Date d'inscriptionmardi 23 janvier 2007StatutMembreDernière intervention31 mars 2010 27 févr. 2009 à 12:01
Bonjour,
La position et la longueur des colonnes est effectivement variable en fonction des valeurs contenues dans chaque fichier. Par contre, ce qui est intéressant, c'est que les libellés des entêtes ne contiennent pas d'espace et que les colonnes sont bien alignées à gauche.
entete1 entete2 entete3
x yyyyy yyyy zzz
Voici donc un exemple de code (certainement optimisable) qui devrait fonctionner (je l'ai notamment testé sur le résultat de la commande wmic /OUTPUT:<nomfichier> DISKDRIVE et le résultat m'a semblé correct)
Pour que cela fonctionne, il faut rajouter dans le projet VBA une référence à la bibliothèque Microsoft Scripting Runtime.
Sub RecupInfosFichierWMIC(strNomFichier As String)
Dim objFSO As FileSystemObject
Dim objTxtStream As TextStream
Dim strFic As String
Dim strLignes() As String, Colonnes() As String
Dim nbColonnes As Integer
Dim PositionColonnes() As Integer, Position As Integer
Dim LongueurColonnes() As Integer, LngColonne As Integer
Dim iLigne As Integer, iColonne As Integer
Dim strValeur As String
'Ouverture du fichier et récupération des lignes '
'(fichier créé par une commande du type WMIC /OUTPUT:strNomFichier )
Set objFSO = New FileSystemObject
Set objTxtStream = objFSO.OpenTextFile(Filename:=strNomFichier, _
Format:=TristateUseDefault)
strFic = objTxtStream.ReadAll
objTxtStream.Close
Set objFSO = Nothing
strLignes = Split(strFic, vbCrLf)
'Détermination de la postion de début de chaque colonne
'heureusement, le libellé d'une colonne ne contient pas d'espace
Colonnes = Split(strLignes(0), Chr(32))
'Le problème c'est que les entêtes de Colonnes sont séparés par un nombre variable
'd'espaces (fonction de la longueur des valeurs)
Position = 1
nbColonnes = 0
ReDim PositionColonnes(0)
For iColonne = 0 To UBound(Colonnes)
LngColonne = Len(Colonnes(iColonne))
If LngColonne = 0 Then ' C'était un espace
Position = Position + 1
Else 'C'est un libellé de colonne
ReDim Preserve PositionColonnes(nbColonnes)
PositionColonnes(nbColonnes) = Position
nbColonnes = nbColonnes + 1
Position = Position + LngColonne + 1
End If
Next
nbColonnes = UBound(PositionColonnes)
'Détermination de la longueur de chaque colonne
ReDim LongueurColonnes(nbColonnes)
For iColonne = 0 To nbColonnes - 1
LongueurColonnes(iColonne) = PositionColonnes(iColonne + 1) _
- PositionColonnes(iColonne)
Next
LongueurColonnes(nbColonnes) = Len(strLignes(0)) - PositionColonnes(nbColonnes)
'On a maintenant la position et la longueur de chaque champ
For iLigne = 0 To UBound(strLignes)
For iColonne = 0 To nbColonnes
strValeur = Trim(Mid$(strLignes(iLigne), PositionColonnes(iColonne), _
LongueurColonnes(iColonne)))
ActiveSheet.Cells(iLigne + 1, iColonne + 1).Value = strValeur
Next
Next
End Sub
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201578 26 févr. 2009 à 19:15
Salut
Pourrais-tu donner un exemple de la ligne d'entête et d'une ligne de données ?
-1- Es-tu sûr que les espaces entre colonnes soient vien des espaces ?
Se pourrait-il que, selon l'outil avec lequel tu affiche ce fichier texte, il remplace de lui-même des caractères 'non-imprimables' en espace ?
Cela peut arriver avec WordPad, par exemple.
--> Envoie ton fichier texte dans un éditeur hexadécimal comme "Hackman" et vérifie que le caractère qui précède la première lettre d'une colonne est un espace = Ascii 32 ou 20 hexa
-2- Est-ce que la largeur des colonnes est aussi respectée dans la ligne des noms de colonnes ?
Exemple
Colonne 1 Colonne 2 Colonne 3
Donnée 1 Donnée 2 Donnée 3
c'est à dire, est-ce que les emplacements des premières lettres des noms de colonnes coincide avec les premières lettres des données des lignes suivantes
Vala
Jack, MVP VB NB : Je ne répondrai pas aux messages privés
<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
aforpien
Messages postés118Date d'inscriptionlundi 6 novembre 2000StatutMembreDernière intervention12 mai 2010 27 févr. 2009 à 09:58
Merci beaucoup pour ta réponse.
Je vais vérifier pour s'il s'agit de caractères 'non imprimable' mais à priori non, je ne pense pas car les espaces sont la pour monter qu'il y a une colonne mais qu'elle est vide, ou bien c'est pour séparer les colonnes, ou lorsque le contenu de la colonne est plus petit que la donnée qui l'alimente.
Par contre oui, les emplacements des premières lettres des noms de colonnes coïncident avec les premières lettres des données des lignes suivantes.
Mon souci est qu'il y a encore des colonnes à droite des celles-ci, au moins une vingtaine.
Et lorsque par exemple le nom du lecteur dans la colonne caption est différent de celui-ci, toutes mes autres données sont décalées et je ne peux donc pas récupérer les infos par rapports aux positions...
Je chercher désespérément !!!
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201578 27 févr. 2009 à 16:56
Re
Pas eu le courage de tout lire (pressé)
Si la 1ere ligne donnant le nom des colonnes est au même endroit que les données, alors il te faut détecter la position du premier caractère de chaque colonne pour en connaitre la largeur.
Il faudra surement supprimer un (ou deux) espace car il doit y avoir une séparation naturelle entre les colonnes.
Ce que je ferai :
- un tableau avec les noms de colonnes + un Split pour les récupérer
Dim sTemp As String
Dim NomColonne() As String
sTemp = maLigne
Do While Instr(sTemp, " ") ' 2 espaces
sTemp = Replace(sTemp, " ", " ") ' Remplace 2 spaces par un seul
Loop
NomColonne = Split(sTemp, " ")
- un autre tableau avec les longueurs, sachant que son index se réfère à celui du 1er tableau
Dim Largeur() As Long
Redim Largeur(0 To UBound(NomColonne))
- une méthode d'analyse :
Un boucle pour rechercher dans la ligne à quel emplacement on trouve les lettres qui suivent un espace
Dim DernierChar As String
Dim DernierPos As Long
Dim monIndex As Integer
DernierChar = " " ' espace
DernierPos = 0
monIndex = 0
For r = 1 To Len(maLigne)
sTemp = Mid$(maLigne, r, 1)
If sTemp <> " " Then
If DernierChar = " " Then
' NomColonne commence
If DernierPos <> 0 Then
Largeur(monIndex) = r - DernierPos - 1
monIndex = monIndex + 1
End If
DernierPos = r
End If
End If
DernierChar = sTemp
Next r
Largeur(monIndex) = r - DernierPos - 1
A retravailler, surement
A partir de là, le découpage à la lecture des champs dans les lignes suivantes doit reposer sur le contenu de Largeur()
Vala
Jack, MVP VB NB : Je ne répondrai pas aux messages privés
<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Vous n’avez pas trouvé la réponse que vous recherchez ?
aforpien
Messages postés118Date d'inscriptionlundi 6 novembre 2000StatutMembreDernière intervention12 mai 2010 2 mars 2009 à 17:19
Un énorme merci à vous deux, je vais tester ces deux solutions dès ce soir et vous ferai parvenir mes résultats demain.
Encore un grand merci à vous deux
aforpien
Messages postés118Date d'inscriptionlundi 6 novembre 2000StatutMembreDernière intervention12 mai 2010 3 mars 2009 à 13:26
R1r2, un grand merci pour ton code, il fonctionne à merveille, et j'ai pu réussir à le comprendre. C'est vraiment super sympa de ta part, je te remercie vraiment beaucoup.
Merci également à Jack, qui m'a permis de comprendre le principe de fonctionnement, l'algo de ce que je voulais représenter.
Vraiment merci, les membres de ce site sont toujours aussi efficace !!!