На днях возникла необходимость создать многомерный (более двух вложений) массив для использования в программе на JavaScrip. Одно из обязательных условий, что массив должен быть объявлен непосредственно в коде функции. Значений он (массив) будет содержать порядка 2000 — 3000. В общем, перспектива набивание «забора» из квадратных скобок и запятых в несколько тысяч штук приводила в уныние.
К моему счастью, данные для массива уже были заготовлены в определенном формате, который позволял экспортировать их в текстовый файл или табличный редактор MS Excel. Так возникла идея автоматизации этого рутинного процесса.
Да, существует большое количество конвертеров, позволяющих генерировать массивы из CSV данных. Но применимы они только для создания двумерных массивов (Или я не нашел таких. Буду благодарен за подсказку). Мне же необходим массив с вложенностью до трех уровней. В итоге я принялся за реализацию своего конвертера с применением VBA макросов в MS Excel. Мне показалось, что MS Excel может использоваться как удобный инструмент для формирования многомерных массивов. Гораздо удобнее подготовить данные в табличном виде с возможностью автоматизированного заполнения диапазонов.
Первые три колонки A, B, C — это индексы массива, обозначающие уровни вложенности. Колонка D — значения для массива. Результат выводится в ячейку F1.
Код VBA функции
Sub create_array() Set ws1 = ThisWorkbook.Sheets("Лист1") lines_amount = 2025 Dim i As Integer, max1 As Integer, max2 As Integer, max3 As Integer, j As Integer, k As Integer, y As Integer, index As Integer max1 = 0 For i = 2 To lines_amount - 1 If max1 < CInt(ws1.Cells(i, 1).Value) Then max1 = CInt(ws1.Cells(i, 1).Value) End If Next i ws1.Cells(1, 6).Value = "[" For i = 1 To max1 max2 = 0 For index = 2 To lines_amount - 1 If max2 < CInt(ws1.Cells(index, 2).Value) And CInt(ws1.Cells(index, 1).Value) = i Then max2 = CInt(ws1.Cells(index, 2).Value) End If Next index ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "[" For j = 1 To max2 max3 = 0 For index = 2 To lines_amount - 1 If max3 < CInt(ws1.Cells(index,3).Value) And CInt(ws1.Cells(index,1).Value)=i And CInt(ws1.Cells(index,2).Value)=j Then max3 = CInt(ws1.Cells(index, 3).Value) End If Next index ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "[" For k = 1 To max3 For y = 2 To lines_amount - 1 If CInt(ws1.Cells(y,1).Value)=i And CInt(ws1.Cells(y,2).Value)=j And CInt(ws1.Cells(y,3).Value)=k Then ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & ws1.Cells(y, 4).Value ws1.Rows(y).Delete Exit For End If Next y If k <> max3 Then ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "," End If Next k If j <> max2 Then ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "]," Else ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "]" End If Next j If i <> max1 Then ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "]," Else ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "]" End If Next i ws1.Cells(1, 6).Value = ws1.Cells(1, 6).Value & "]" End Sub
Через переменную lines_amount = 2025 задается количество строк для обработки. Первой строкой является заголовок, поэтому диапазон данных начинается со второй строки index = 2.
В моем случае индексы шли не по порядку, поэтому функция просматривает весь диапазон несколько раз. В случае ручного формирования таблицы с данными, думаю, код можно упростить. Из за нескольких итераций просмотра всего диапазона с данными, выполнение функции может занимать большое количество времени. В связи с чем в функцию добавлен код для удаления строки из таблицы, которая уже занесена в массив. Поэтому настоятельно рекомендую копировать лист с данными перед выполнением функции.
Код VBA функции ни в коем случае не претендует на роль идеального инструмента. Нужно рассматривать его как прототип, демонстрирующий возможность использования таблиц MS Excel для подготовки массивов.
Пример книги Excel (необходимо выполнить макрос Вид -> Макросы -> create_array)
https://cloud.mail.ru/public/7mpU/s1mNTmuzh
ссылка на оригинал статьи http://habrahabr.ru/post/271377/
Добавить комментарий