Страницы: 1
RSS
Преобразовать строку в массив (VBA)
 
Всем доброго дня!
Прошу уважаемых форумчан помочь советом по следующей ситуации.

[VBA]: обрабатывается построчно текстовый файл большого размера (100+ Мб).
Каждая считанная строка имеет следующий вид (пример):
Код
{{"Василий","Инженер",55000,35},{"Михаил","Юрист",65000,42},{"Светлана","офис-менеджер",35000,27}}

Согласно синтаксису VB (не VBA), подобная запись информации (с использованием вложенных литералов `{` и `}` ) соответствует записи двумерного массива.
Цитата
' https://msdn.microsoft.com/ru-ru/library/wak0wfyt.aspx
...
Dim grid = {{1, 2}, {3, 4}}
...
А синтаксис описания массивов в VBA, к сожалению, иной и фигурные скобки не воспринимаются.

Требуется: присвоить содержимое вышеуказанной строки переменной, являющей двумерным массивом для последующей обработки строк и столбцов. К примеру - суммированию в цикле зарплат сотрудников, чей возраст менее 40 лет.

Проблема: описание массивов в VBA не воспринимает фигурные скобки. Можно было бы через RegExp привести строку к виду
Код
Array(Array("Василий","Инженер",55000,35),Array("Михаил","Юрист",65000,42),Array("Светлана","Офис-менеджер",35000,27))
и применить (бы) evaluate, но Evaluate в VBA обрабатывает только арифметические выражения...

Я пытался воспользоваться другим редактором:
Код
Dim d As New MSScriptControl.ScriptControl
d.Language = "VBScript"...
но он так же отличается от VB и не воспринимает синтаксис массива с применением фигурных скобок.

Уважаемые коллеги, подскажите, какие есть идеи или варианты на Ваш взгляд, кроме простого перебора строки и заполнения в цикле двумерного массива для приведения его к виду
Цитата
Василий      Инженер         55000    35
Михаил       Юрист           65000    42
Светлана     Офис-менеджер   35000    27
Скорость работы решения важна, поскольку файл - большого размера.

Заранее благодарю Вас за участие в обсуждении!
Изменено: Alex.Karev - 18.08.2016 10:39:52
 
Я думаю незачем собирать двумерный массив - перебираем в цикле строки, каждую сплитим в одномерный массив, затем в цикле его в другой массив, сразу проверяем критерий - если запись нужна, то тут же её и обрабатываем.

Код
Sub tt()

Dim s$, arr1, arr2, el

s = "{{""Василий"",""Инженер"",55000,35},{""Михаил"",""Юрист"",65000,42},{""Светлана"",""офис-менеджер"",35000,27}}"
s = Replace(s, "},{", "|")
s = Replace(s, "{", "")
arr1 = Split(s, "|")
For Each el In arr1
arr2 = Split(el, ",")
If arr2(3) < 40 Then MsgBox arr2(0)
Next

End Sub
 
Мой вариант.
Код
Function JArray(S, Age_, Summ) As Double
    bRes = False
    Set RegExp = CreateObject("VBScript.RegExp")
    RegExp.Global = True
    RegExp.Pattern = "\{""(.+?)"",""(.+?)"",(.+?),(\d+)\}"
    bRes = RegExp.test(S)
    If bRes Then
        Set oMatches = RegExp.Execute(S)
        For n = 0 To oMatches.Count - 1
            Age = Val(oMatches(n).SubMatches(3))
            If Age_ > Age Then Summ = Summ + CDbl(oMatches(n).SubMatches(2))
        Next
    End If
   JArray = Summ
End Function

 
Ну в моём варианте я думаю как приладить суммирование понятно.
И кстати если нужны только суммы - то убивать "{" лишнее, т.е. строка
s = Replace(s, "{", "")
не нужна.
 
Hugo,
так немного проще, имхо
Код
Sub tt()
 
Dim s$, arr1, arr2, el
 
s = "{{""Василий"",""Инженер"",55000,35},{""Михаил"",""Юрист"",65000,42},{""Светлана"",""офис-менеджер"",35000,27}}"
s = Mid$(s, 3, Len(s) - 4)
arr1 = Split(s, "},{")
For Each el In arr1
    arr2 = Split(el, ",")
    If arr2(3) < 40 Then MsgBox arr2(0)
Next
 
End Sub
F1 творит чудеса
 
Ну да, так проще, согласен. Замены не нужны, так будет чуть быстрее.
Можно и переменную arr1 не использовать.
Изменено: Hugo - 18.08.2016 12:41:05
 
Цитата
Alex.Karev написал #1:
и применить (бы) evaluate
Цитата
Alex.Karev написал:
но Evaluate в VBA обрабатывает только арифметические выражения
Доказательство ложности утверждения:
Код
Sub Test1()
    Dim S As String, Arr
    S = [B4]
    Arr = Evaluate(Replace(Mid(S, 2, Len(S) - 2), "},{", ";"))
    [B6].Resize(UBound(Arr, 1), UBound(Arr, 2)) = Arr
End Sub
 
Цитата
С.М. написал: Arr = Evaluate(Replace(Mid(S, 2, Len(S) - 2), "},{", ";"))
вот это круто!
F1 творит чудеса
 
Hugo, Doober, Максим Зеленский, спасибо Вам за хорошие варианты решений! Решение Максима претендовало на окончательное... пока не появился С.М.

Это действительно круто. С.М.,  Вы предложили наикрутейшее решение!
Цитата
...
Arr = Evaluate(Replace(Mid(S, 2, Len(S) - 2), "},{", ";"))

Достойное пополнение в Золотую коллекцию фичей VBA! Ничего подобного нет в сети, включая MSDN.

Огромное Вам спасибо!
Изменено: Alex.Karev - 18.08.2016 22:50:30
 
Круто. Но вот что будет в итоге быстрее? Перебирать массив в цикле всё равно нужно...
Страницы: 1
Наверх