Страницы: 1 2 След.
RSS
Как правильно добавить еще один элемент двумерного массива?
 
Здравствуйте!

Наполняю двумерный массив v() следующим кодом:
Код
        j = 1
        
        Dim v() As Variant
        For Each MyRow In Range("checked").Rows
            x = MyRow.Row
                If j = 1 Then
                    ReDim v(0, 1 To 4)
                Else
                    ReDim Preserve v(UBound(v, 1) + 1, 1 To 4)
                End If
                v(0, 1) = MyRow.Cells(3).Value & MyRow.Cells(4).Value & MyRow.Cells(9).Value & MyRow.Cells(10).Value
                ' MyRow.Cells(24).Value, MyRow.Cells(25).Value, "")
                v(0, 2) = x 'номер строки
                v(0, 3) = MyRow.Cells(30).Value 'КТТ
                v(0, 4) = ""
                j = j + 1
        Next MyRow
Уже на второй итерации(j=2) код заваливается на строке ReDim Preserve v(UBound(v, 1) + 1, 1 To 4)
Как добавить следующий элемент правильно?
Изменено: borro - 30.08.2018 16:39:39
желаю всем счастья
 
Увеличивать можно только последнюю мерность массива
Код
ReDim Preserve v(1 To 4,UBound(v, 2)+1)

А потом циклами транспонируйте.
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim написал:
А потом циклами транспонируйте.
Спасибо. Покажите пожалуйста пример такой транспонировки для данного случая
Изменено: borro - 30.08.2018 16:49:00
желаю всем счастья
 
Nordheim, попробовал по вашему варианту:
Код
        Dim v() As Variant
        For Each MyRow In Range("checked").Rows
            x = MyRow.Row
                If j = 0 Then
                    ReDim v(1 To 4, 0)
                Else
                    ReDim Preserve v(1 To 4, UBound(v, 2) + 1)
                End If
                v(1, j) = MyRow.Cells(3).Value & MyRow.Cells(4).Value & MyRow.Cells(9).Value & MyRow.Cells(10).Value
                v(2, j) = x 'номер строки
                v(3, j) = MyRow.Cells(30).Value 'КТТ
                v(4, j) = ""
                j = j + 1
        Next MyRow
Затем хочу пройтись по всем значениям v(1):
Код
        Dim Kttmax%
        For j = 0 To UBound(v(1))
            ...
        Next j
и получаю ошибку "Subscript out of rangeКак правильно пройтись по ним?
желаю всем счастья
 
Цитата
borro написал:
For j = 0 To UBound(v(1))            ...        Next j
Код
For j = 0 To UBound(v,2)
      ...
Next j
 
Выполнять Redim при каждой итерации цикла - плохая идея. Лучше до цикла определиться с размерами массива.
Изменено: sokol92 - 30.08.2018 20:36:52
Владимир
 
Приложите файл пример небольшой. а то не понятно, что и  как у вас работает.
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Надо было сразу прикладывать файл с неупрощенной действительностью. Сейчас получается, что весь мой предыдущий труд был сделан впустую. А возвращаться к этой задаче я не хочу, да и некогда.
- это ведь читали...
Да и зачем вообще таким способом работать с массивом? Есть несколько других простых способов, но т.к. задача неизвестна, то и способы озвучивать смысла нет...
Изменено: Hugo - 30.08.2018 21:30:16
 
borro, не вникал, но гляньте тут. Я собираю всё в одномерный, а потом по алгоритму в цикле "пилю" на блоки в другие размерности…
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Доброго утра всем
Цитата
Nordheim написал:
Приложите файл пример небольшой. а то не понятно, что и  как у вас работает.
Вот пример полотна, по которому должен формироваться массив v().
Если описать всю задачу, то она такова( возможно это вопрос другой темы, простите модераторы)
Я проверяю заполненность значений этой большой таблицы. Для того чтобы пометить красным какое-то неправильное значение в этой таблице мне предварительно надо всю ее просканировать и получить объект данных, который бы по номеру строки листа(в пределах таблицы), отвечающую за отдельное устройство, говорил, это устройство на "вводе" или нет.
Что значит, что устройство на "вводе":
На предварительном проходе выбрать из таблицы следующие данные(как я выше пытаюсь в массив v()):
1. Номер строки на листе
2. Ключ привязки к топологии сети - это сцепленные значения столбцов 4,5,10,11
3. Коэффициент из столбца 31
4. Пустой столбец для последующей простановки признака ввод/не ввод
5. Пустой столбец для последующей простановки максимального к-та из п.3 среди всех строк с ключом из п.2
Собирать надо строки, которые имеют в столбце 2 значение "Прибору учета", а в столбце 18 "РУ ТП"

Затем по этой структуре данных v() надо будет пройтись, чтобы для всех строк с ключом из п.2 (сцепленные значения столбцов 4,5,10,11) найти максимальное значение коэффициента из столбца 31(п.3), где-то это запомнить(по всей видимости в тот же объект v() в столбец 5). Если есть хоть один не заполненный коэффициент для данного ключа, то максимальный коэффициент указать как Null(Empty) Затем еще раз пройтись по массиву v()  и проставить в его четвертом столбце признак "ввод", если коэффициент из п.3 = максимальному коэффициенту(столбец.5) для всех строк с ключом из п.2. Если к-т меньше максимального, то "не ввод". Если значение коэффициента неизвестно(Null(Empty)) или неизвестен максимальный коэффициент(Null(Empty)), то проставить "неизвестно"
Изменено: borro - 31.08.2018 10:38:50
желаю всем счастья
 
Вставьте свой макрос в файл пример, нужно понять как он работает. Из описания мало что понял  8-0 . [времени не так уж много вникать в написанное]
Изменено: Nordheim - 31.08.2018 11:03:49
"Все гениальное просто, а все простое гениально!!!"
 
borro, представлять в виде массива данные, количество которых станет ясно только после заполнения массива — плохая, негодная идея. Для данных, которых неизвестно сколько, коллекции существуют.
 
borro, а зачем собирать пустые ячейки?
 
У вас очень много "пройтись по массиву", может есть способ сделать несколько действий за один проход, покажите как есть и на другом листе как нужно,
и покороче что от чего зависит. мне кажется есть проще решение нежели ваш код редактировать.
"Все гениальное просто, а все простое гениально!!!"
 
Сбор нужных данных я бы сделал так:
Код
Option Explicit

Public Type Строка
   Ном As Collection
   Клю  As Collection
   Коэ  As Collection
End Type

Sub Сбор()

   Dim Строки As Строка
   Dim i As Long
   
   With Строки
      Set .Ном = New Collection
      Set .Клю = New Collection
      Set .Коэ = New Collection
      For i = 9 To Cells(Rows.Count, 2).End(xlUp).Row
         If Cells(i, 2).Value = "Прибор учета" And Cells(i, 18).Value = "РУ ТП" Then
            .Ном.Add i
            .Клю.Add Cells(i, 4).Value & Cells(i, 5).Value & Cells(i, 10).Value & Cells(i, 11).Value
            .Коэ.Add Cells(i, 31).Value
         End If
      Next i
   End With

End Sub
Теперь у Вас в переменной Строки, которая является списком строк, которые Вы собираетесь анализировать, в поле Ном — номер строки, в поле Клю — ключ, в поле Коэ — коэффициент.
Изменено: StoTisteg - 31.08.2018 11:24:01
 
Всем спасибо. Если я добавлю еще и свои макросы, это скорее еще труднее станет восприниматься. Просто надо получить объект, который по номеру строки будет говорить, это устройство с максимальным коэффициентом ("ввод") или нет("не ввод") среди всех других с тем же ключом. Много пустых ячеек - это я удалил по причине безопасности
StoTisteg, попробую поработать с вашим вариантом
желаю всем счастья
 
Цитата
borro написал:
устройство с максимальным коэффициентом ("ввод") или нет("не ввод") среди всех других с тем же ключом
Это тоже можно...
Код
Option Explicit

Public Type Строка
   Ном As Collection
   Клю  As Collection
   Коэ  As Collection
End Type

Public Type Итог
   Ключ As Collection
   Макс As Collection
End Type

Sub Сбор()

   Dim Строки As Строка
   Dim i As Long
   
   With Строки
      Set .Ном = New Collection
      Set .Клю = New Collection
      Set .Коэ = New Collection
      For i = 9 To Cells(Rows.Count, 2).End(xlUp).Row
         If Cells(i, 2).Value = "Прибор учета" And Cells(i, 18).Value = "РУ ТП" Then
            .Ном.Add i
            .Клю.Add Cells(i, 4).Value & Cells(i, 5).Value & Cells(i, 10).Value & Cells(i, 11).Value
            .Коэ.Add Cells(i, 31).Value
         End If
      Next i
   End With

End Sub

Function Итоги(ByRef Строки As Строка) As Итог

   Dim i As Long, Mxm As Long, Str As Long
   Dim Elem As Variant
   Dim sh As Worksheet
   
   Set sh = ActiveSheet
   With Итоги
      Set .Ключ = New Collection
      Set .Макс = New Collection
      Application.DisplayAlerts = False
      Application.ScreenUpdating = False
      Worksheets.Add after:=Worksheets(Sheets.Count)
      Cells(1, 1).Value = "Ключ"
      For Each Elem In Строки.Клю
         Cells(Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).Value = Elem
      Next Elem
      Range(Cells(1, 1), Cells(Строки.Клю.Count + 1, 1)).RemoveDuplicates Columns:=1, Header:=xlYes
      For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
         .Ключ.Add Cells(i, 1).Value
      Next i
      Worksheets(Sheets.Count).Delete
      Application.DisplayAlerts = True
      Application.ScreenUpdating = True
      sh.Activate
      For Each Elem In .Ключ
         Mxm = 0
         Str = 0
         For i = 1 To Строки.Клю.Count
            If Строки.Клю(i) = Elem And Строки.Коэ > Mxm Then Str = Строки.Ном(i)
         Next i
         .Макс.Add Str
      Next Elem

End Function
Функция Итоги получает список строк от макроса Сбор и возвращает список ключей и соответствующих им строк с максимальным коэффициентом.
Изменено: StoTisteg - 31.08.2018 16:49:10
 
StoTisteg, спасибо! Буду изучать
желаю всем счастья
 
StoTisteg, попробовал на тестовом файле. Возникает ошибка, что какой-то аргумент не указан(Argument is not optional). При этом подсвечивается код Строки.Коэ в конце вашей функции

Можете пояснить, в чем причина?
желаю всем счастья
 
Цитата
borro: в чем причина?
матчасть. Как я понимаю, не опциональный - значит обязательный. То есть его нужно обязательно указать/передать.
Изменено: Jack Famous - 31.08.2018 15:24:27
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
может так.
Код
Function Итоги(ByRef Строки As Строка) As Итог
 
   Dim i As Long, Mxm As Long, Str As Long
   Dim Elem As Variant
   Dim sh As Worksheet
    
   Set sh = ActiveSheet
   With Итоги
      Set .Ключ = New Collection
      Set .Макс = New Collection
      Application.DisplayAlerts = False
      Application.ScreenUpdating = False
      Worksheets.Add after:=Worksheets(Sheets.Count)
      Cells(1, 1).Value = "Ключ"
      For Each Elem In Строки.Клю
         Cells(Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).Value = Elem
      Next Elem
      Range(Cells(1, 1), Cells(Строки.Клю.Count + 1, 1)).RemoveDuplicates Columns:=1, Header:=xlYes
      For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
         .Ключ.Add Cells(i, 1).Value
      Next i
      Worksheets(Sheets.Count).Delete
      Application.DisplayAlerts = True
      Application.ScreenUpdating = True
      sh.Activate
      For Each Elem In .Ключ
         Mxm = 0
         Str = 0
         For i = 1 To Строки.Клю.Count
            If Строки.Клю(i) = Elem And Строки.Коэ(i) > Mxm Then Str = Строки.Ном(i) ' добавил индекс в Строки.Коэ(i)
         Next i
         .Макс.Add Str
      Next Elem
End With ' добавил окончание блока  
End Function
Изменено: Nordheim - 31.08.2018 15:38:54
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, спасибо, да, похоже на то
желаю всем счастья
 
Цитата
borro написал:
Можете пояснить, в чем причина?
Индекс забыл, пардон:
Код
If Строки.Клю(i) = Elem And Строки.Коэ(i) > Mxm Then Str = Строки.Ном(i)
Изменено: StoTisteg - 31.08.2018 16:08:33
 
спасибо. и еще обновить Mxm :)
желаю всем счастья
 
Блин. Вот что значит кодить прямо в форум :)
Код
Option Explicit

Public Type Строка
   Ном As Collection
   Клю  As Collection
   Коэ  As Collection
End Type

Public Type Итог
   Ключ As Collection
   Макс As Collection
End Type

Sub Сбор()

   Dim Строки As Строка
   Dim i As Long
   
   With Строки
      Set .Ном = New Collection
      Set .Клю = New Collection
      Set .Коэ = New Collection
      For i = 9 To Cells(Rows.Count, 2).End(xlUp).Row
         If Cells(i, 2).Value = "Прибор учета" And Cells(i, 18).Value = "РУ ТП" Then
            .Ном.Add i
            .Клю.Add Cells(i, 4).Value & Cells(i, 5).Value & Cells(i, 10).Value & Cells(i, 11).Value
            .Коэ.Add Cells(i, 31).Value
         End If
      Next i
   End With

End Sub

Function Итоги(ByRef Строки As Строка) As Итог

   Dim i As Long, Mxm As Long, Str As Long
   Dim Elem As Variant
   Dim sh As Worksheet
   
   Set sh = ActiveSheet
   With Итоги
      Set .Ключ = New Collection
      Set .Макс = New Collection
      Application.DisplayAlerts = False
      Application.ScreenUpdating = False
      Worksheets.Add after:=Worksheets(Sheets.Count)
      Cells(1, 1).Value = "Ключ"
      For Each Elem In Строки.Клю
         Cells(Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).Value = Elem
      Next Elem
      Range(Cells(1, 1), Cells(Строки.Клю.Count + 1, 1)).RemoveDuplicates Columns:=1, Header:=xlYes
      For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
         .Ключ.Add Cells(i, 1).Value
      Next i
      Worksheets(Sheets.Count).Delete
      Application.DisplayAlerts = True
      Application.ScreenUpdating = True
      For Each Elem In .Ключ
         Mxm = 0
         Str = 0
         For i = 1 To Строки.Клю.Count
            If Строки.Клю(i) = Elem And Строки.Коэ(i) > Mxm Then
               Str = Строки.Ном(i)
               Mxm = Строки.Коэ(i)
            End If
         Next i
         .Макс.Add Str
      Next Elem
   End With

End Function
Изменено: StoTisteg - 31.08.2018 16:47:57
 
StoTisteg, а как теперь из результата функции Итоги по ключу получить номер строки - организовывать цикл, который сначала узнает порядковый номер ключа, а потом в следующем цикле на узнанном порядковом номере узнает номер строки?

Выход нашел через создание словаря из результата функции Итоги
Изменено: borro - 31.08.2018 17:40:26
желаю всем счастья
 
Здравствуйте, borro!

Посмотрел постановку задачи в #10. На мой взгляд, оптимальный путь (по скорости и наглядности) следующий:
1. Проставить в столбце A (или ином) номера строк
2. Отсортировать таблицу по возрастанию полей 4,5,10,11 и убыванию поля 31
3. За один прогон определить признак "на вводе" (без массивов и коллекций)
4. Вернуть первоначальную сортировку, если необходимо (для этого был нужен первый пункт)

Успехов!
Владимир
 
в Вашем вопросе как бы есть ответ на него
Цитата
borro написал:
Как правильно добавить еще один элемент
добавьте его правильно! вот и все
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Всем спасибо за советы и знания. Все получилось
желаю всем счастья
 
sokol92, не будет там сортировать, там объединённые ячейки...
Страницы: 1 2 След.
Наверх