Как преобразовать строку с запятой в двухмерный массив - PullRequest
2 голосов
/ 19 апреля 2019

У меня есть файл csv, разделенный запятыми с разделителем Lf, и я хочу преобразовать его в двумерный массив для дальнейшей обработки.Я успешно прочитал файл в строку и изменил терминатор строки с Lf на Cr, так как я понимаю, что vba не распознает Lf как терминатор.Я хочу взять эту строку и создать двумерный массив, в котором я также могу определить количество строк и столбцов, поскольку исходный файл csv может иметь произвольный размер.Файл csv также может быть большого размера (> 300 МБ и> 1М элементов)

Я не смог выяснить, как определить количество столбцов, даже если в нем есть терминатор CRстрока для каждой строки данных.Приведенный ниже код показывает, как я создал строку, разделенную запятой в качестве разделителя Cr

Open fName For Binary As #1

     Buf$ = String$(LOF(1), 0)
     Get 1, , Buf$
     Buf$ = Replace$(Buf$, vbLf, vbCr) ' Replace LF with CR

Close #1

Я хотел бы создать метод или функцию, которая создаст двумерный массив и рассчитает количество строк истолбцы

Ответы [ 2 ]

1 голос
/ 19 апреля 2019

Я бы попытался это сделать:

  1. Сначала разбейте данные на строки, используя vbNewLine .
  2. Затем зациклите ваш массив split и разбейте каждую итерацию, используя разделитель запятых. Оставив вас с зубчатым массивом (массивом, содержащим массивы).
  3. Наконец, теперь у вас есть размеры для двух dim-массивов ReDim и зациклите их, чтобы добавить все ваши данные.

В целях абстракции я разделил эту задачу на три отдельные функции.


Основная функция для вызова

Я сделал разделитель необязательным, чтобы он не ограничивался только запятыми.

Это не относится к экранированным символам, вам придется добавить это, если это необходимо.

Private Function TextFileToArray(ByVal FilePath As String, Optional ByVal Delimiter As String = ",") As Variant

    'READ THE CONTENTS FROM TEXTFILE
    Dim FileContent As String
    FileContent = ReadTextFile(FilePath)

    'SEPERATE THE ROWS USING vbNewLine
    Dim SplitData As Variant
    SplitData = Split(FileContent, vbNewLine)

    'CREATE A JAGGED ARRAY BY SPLITTING EACH STRING
    Dim JaggedArray As Variant
    ReDim JaggedArray(LBound(SplitData, 1) To UBound(SplitData, 1))

    Dim Index As Long
    For Index = LBound(SplitData, 1) To UBound(SplitData, 1)
        JaggedArray(Index) = Split(SplitData(Index), Delimiter)
    Next Index

    'CONVERT JAGGED ARRAY INTO A TWO DIM ARRAY
    TextFileToArray = JaggedArrayToTwoDimArray(JaggedArray)

End Function

Прочитать содержимое текстового файла

Это можно записать в основной функции, но обычно лучше попытаться разделить ваш код на более мелкие блоки.

Public Function ReadTextFile(ByVal FilePath As String) As String

    Dim Fso As Object
    Set Fso = CreateObject("Scripting.FileSystemObject")

    Dim Ts As Object
    Set Ts = Fso.OpenTextFile(FilePath, 1, False)

    ReadTextFile = Ts.ReadAll

End Function

Преобразование Jagged Array в 2d Array

Я сохранил границы в переменных, чтобы упростить отладку и чтение.

Private Function JaggedArrayToTwoDimArray(ByVal SourceArray As Variant) As Variant

    'CAPTURE BOUNDS
    Dim LB1 As Long
    LB1 = LBound(SourceArray, 1)

    Dim UB1 As Long
    UB1 = UBound(SourceArray, 1)

    Dim LB2 As Long
    LB2 = LBound(SourceArray(LB1), 1)

    Dim UB2
    UB2 = UBound(SourceArray(UB1), 1)

    'SET BOUNDS OF RETURN ARRAY
    Dim ReturnArray As Variant
    ReDim ReturnArray(LB1 To UB1, LB2 To UB2)

    'POPULATE TWO DIM ARRAY FROM JAGGED ARRAY
    Dim RowIndex As Long
    For RowIndex = LB1 To UB1

        Dim ColIndex As Long
        For ColIndex = LB2 To UB2
            ReturnArray(RowIndex, ColIndex) = SourceArray(RowIndex)(ColIndex)
        Next ColIndex

    Next RowIndex

    JaggedArrayToTwoDimArray = ReturnArray

End Function

Пожалуйста, не стесняйтесь добавлять обработку ошибок и любые изменения, которые могут потребоваться.

1 голос
/ 19 апреля 2019

Первое, что приходит на ум, - это использование InStr (), которое отображает расположение символа в строке.Определите размеры вашего массива заранее (последняя строка вашего набора данных);Я буду использовать i в качестве итератора цикла в кратких примерах)

sep = InStr(Cells(i,1).Value,"BS") 'swap BS for whatever you want to separate on

Затем использовать отдельный (sep) для любого массива

arr(i,1) = left(Cells(i,1).value,sep-1)
arr(i,2) = right(Cells(i,1).value,len(cells(i,1))-sep+2) '2 characters in sep "b" and "s" so adding that back

Изменение, которое я бы предложилваш код должен использовать какой-либо символ или строку вместо возврата каретки, чтобы его можно было легко отделить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...