2009-06-25 8 views
1

Je cherche le meilleur moyen de charger des données formatées en VBA. J'ai passé un certain temps à essayer de trouver l'équivalent des fonctions de type fscanf de type C ou Fortran, mais sans succès. Fondamentalement, je veux lire à partir d'un fichier texte des millions de chiffres placés sur plusieurs lignes (100 000) avec 10 numéros chacun (sauf la dernière ligne, éventuellement 1-10 numéros). Les nombres sont séparés par des espaces, mais je ne connais pas à l'avance la largeur de chaque champ (et cette largeur change entre les blocs de données). par exemple.Chargement de données formatées dans VBA à partir d'un fichier texte

397143.1 396743.1 396343.1 395943.1 395543.1 395143.1 394743.1 394343.1 393943.1 393543.1 

    -0.11 -0.10 -0.10 -0.10 -0.10 -0.09 -0.09 -0.09 -0.09 -0.09 

0.171 0.165 0.164 0.162 0.158 0.154 0.151 0.145 0.157 0.209 

Auparavant, je l'ai utilisé la fonction Mid mais dans ce cas, je ne peux pas, parce que je ne sais pas à l'avance la largeur de chaque champ. De plus, il y a trop de lignes à charger dans une feuille Excel. Je peux penser à une manière de force brute dans laquelle je regarde chaque caractère successif et détermine si c'est un espace ou un nombre, mais il semble terriblement maladroit.

Je suis également intéressé par les pointeurs sur la façon d'écrire des données formatées, mais cela semble plus facile - il suffit de formater chaque chaîne et de les concaténer en utilisant &.

Répondre

3

L'extrait suivant lire les numéros délimité par des espaces à partir d'un fichier texte:

Dim someNumber As Double 

Open "YourDataFile.txt" For Input As #1 

Do While Not (EOF(1)) 
    Input #1, someNumber 
    `// do something with someNumber here...` 
Loop 

Close #1 

mise à jour: Voici comment vous pouvez lire une ligne à la fois, avec un nombre variable d'éléments sur chaque ligne :

Dim someNumber As Double 
Dim startPosition As Long 
Dim endPosition As Long 
Dim temp As String 

Open "YourDataFile" For Input As #1 

Do While Not (EOF(1)) 
    startPosition = Seek(1) '// capture the current file position' 
    Line Input #1, temp  '// read an entire line' 
    endPosition = Seek(1) '// determine the end-of-line file position' 
    Seek 1, startPosition '// jump back to the beginning of the line' 

    '// read numbers from the file until the end of the current line' 
    Do While Not (EOF(1)) And (Seek(1) < endPosition) 
     Input #1, someNumber 
     '// do something with someNumber here...' 
    Loop 

Loop 

Close #1 
+0

Super! Je vais utiliser une combinaison de ces deux méthodes. –

+0

Heureux d'être de l'aide :) –

+0

Plus d'un an plus tard et il est toujours utile :) – PowerUser

2

Vous pouvez également utiliser des expressions régulières pour remplacer plusieurs espaces blancs à un espace, puis utiliser la fonction de Split pour chaque ligne comme le code exemple montre ci-dessous. Après que 65000 lignes ont été traitées, une nouvelle feuille sera ajoutée au classeur Excel afin que le fichier source puisse être plus grand que le nombre maximal de lignes dans Excel.

Dim rx As RegExp 

Sub Start() 

    Dim fso As FileSystemObject 
    Dim stream As TextStream 
    Dim originalLine As String 
    Dim formattedLine As String 
    Dim rowNr As Long 
    Dim sht As Worksheet 
    Dim shtCount As Long 

    Const maxRows As Long = 65000 

    Set fso = New FileSystemObject 
    Set stream = fso.OpenTextFile("c:\data.txt", ForReading) 

    rowNr = 1 
    shtCount = 1 

    Set sht = Worksheets.Add 
    sht.Name = shtCount 

    Do While Not stream.AtEndOfStream 
     originalLine = stream.ReadLine 
     formattedLine = ReformatLine(originalLine) 
     If formattedLine <> "" Then 
      WriteValues formattedLine, rowNr, sht 
      rowNr = rowNr + 1 
      If rowNr > maxRows Then 
       rowNr = 1 
       shtCount = shtCount + 1 
       Set sht = Worksheets.Add 
       sht.Name = shtCount 
      End If 
     End If 
    Loop 

End Sub 


Function ReformatLine(line As String) As String 

    Set rx = New RegExp 

    With rx 
     .MultiLine = False 
     .Global = True 
     .IgnoreCase = True 
     .Pattern = "[\s]+" 
     ReformatLine = .Replace(line, " ") 
    End With 

End Function 


Function WriteValues(formattedLine As String, rowNr As Long, sht As Worksheet) 

    Dim colNr As Long 
    colNr = 1 

    stringArray = Split(formattedLine, " ") 
    For Each stringItem In stringArray 
     sht.Cells(rowNr, colNr) = stringItem 
     colNr = colNr + 1 
    Next 

End Function 
+0

Pour cette tâche particulière, je n'ai pas besoin de charger les nombres dans des feuilles Excel réelles, et il serait un peu lourd de traiter des dizaines de feuilles ... Mais, je m'assurerai de prendre note de la méthode que vous suggérez, car je suis sûr que j'aurai besoin de quelque chose de ce genre pour d'autres tâches. Merci! –

+1

Ah Je pensais que vous vouliez capturer les valeurs dans Excel pour le traitement/la cartographie. Que faites-vous avec les valeurs maintenant? – Marc

Questions connexes