загрузка отформатированных данных в VBA из текстового файла - PullRequest
1 голос
/ 25 июня 2009

Я ищу лучший способ загрузки отформатированных данных в VBA. Я потратил довольно много времени, пытаясь найти эквивалент C-подобных или Fortran-подобных функций типа fscanf, но безуспешно.

В основном я хочу прочитать из текстового файла миллионы чисел, размещенных во многих (100 000) строках по 10 чисел в каждой (кроме последней строки, возможно, 1-10 чисел). Числа разделены пробелами, но я заранее не знаю ширину каждого поля (и эта ширина изменяется между блоками данных). например,

  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 

Ранее я использовал функцию Mid, но в этом случае я не могу, потому что я заранее не знаю ширину каждого поля. Также в листе Excel слишком много строк для загрузки. Я могу думать о грубой силе, с помощью которой я смотрю на каждого последующего персонажа и определяю, является ли это пробел или число, но это кажется ужасно неуклюжим.

Мне также интересны указатели о том, как записывать отформатированные данные, но это кажется более простым - просто отформатируйте каждую строку и объедините их, используя &.

Ответы [ 2 ]

4 голосов
/ 25 июня 2009

Следующий фрагмент будет считывать числа с пробелами из текстового файла:

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

обновление: Вот как можно читать по одной строке за раз, с переменным количеством элементов в каждой строке:

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
2 голосов
/ 25 июня 2009

Вы также можете использовать регулярные выражения для замены нескольких пробелов на один пробел, а затем использовать функцию Split для каждой строки, как показано в примере кода ниже.

После обработки 65000 строк новый лист будет добавлен в книгу Excel, поэтому исходный файл может быть больше максимального числа строк в 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
...