Страницы: 1
RSS
Номер строки массива при переборе метода For Each
 
Добрый день Уважаемые Эксперты.

Позвольте у Вас уточнить как быть в следующем случае?
Перебираю массива Методов For Each  и хочу узнать по адрес и номер строки Массива по условию. Делаю я это следующим способом:
Код
Sub Test_Massib_1()
Dim myRow As Long
Dim a()

a = Range("S8:Y14")
Count = 0

For Each Element1 In a
   If Element1 = 4 Then
      'If Element1 = 4 Then myRow = Element1.Row
            
      'C = Element1.Address
      'Stop
      
      Count = Count + 1
      myRow = Element1.Row
      MsgBox myRow 
   End If
Next

MsgBox Count
End Sub
На строке:
Код
myRow = Element1.Row
процедура уходит на 424 ошибку.
Позвольте у Вас уточнить в чем кроется ошибка? Каким образом определить номер строки в массиве по условию.
Это возможно, если делать перебор методом For Each?

Прошу помочь разобраться.

Благодарю Вас.
 
Код
Sub Test_Massib_1()
  Dim a as Range, count&
  Set a = Range("S8:Y14"):  Count = 0
  For Each Element1 In a
    If Element1 = 4 Then
      Count = Count + 1
      MsgBox "Sheet ROW = " & Element1.Row & "  range ROW = " & 1 + Element1.Row - a.Row
    End If
  Next
  MsgBox Count
End Sub
Изменено: Ігор Гончаренко - 03.03.2019 14:00:23
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ответ Ігор Гончаренко, не совсем ответ на вопрос.  Если работать именно с массивом, а не с диапазоном, то так
Код
Sub Test_Massib_1()
Dim myRow As Long
Dim a()
Dim i As Long
a = Range("S8:Y14")
R0 = Range("S8:Y14").Row
C0 = Range("S8:Y14").Column
Count = 0
For Each Element1 In a
i = i + 1
   If Element1 = 4 Then
      Count = Count + 1
      myRow = ((i - 1) Mod UBound(a)) + R0
      myColumn = Int((i - 1) / UBound(a, 2)) + C0
      MsgBox myRow
   End If
Next
MsgBox Count
End Sub

Не стал оформлять  и выводить номер столбца, разберетесь.
По вопросам из тем форума, личку не читаю.
 
Уважаемые Ігор Гончаренко и БМВ  
Спасибо Вам за ответы.
 
или так (с массивом)
Код
Sub Test2()
  Dim a, E, count&, n&
  a = Range("S8:Y14")
  For Each E In a
    If E = 4 Then count = count + 1: MsgBox "R" & n Mod UBound(a) + 1 & "C" & n \ UBound(a) + 1
    n = n + 1
  Next
  MsgBox count
End Sub
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
IgorBoot написал:
...
a = Range("S8:Y14")
...
For Each Element1 In a
   ...
   myRow = Element1.Row
   
   Element1.Address
   ...
Next
IgorBoot, вы перепутали работу с массивом с работой с диапазонам ячеек.
В массиве данных (переменна) вы не можете ссылаться на свойство 'Row' ('Address' тоже) элемента массива, такого нет тут.

Ps:
Если вы ничего не меняете силой/принудительно, то 'For...Each':
1. в массиве подсчитывает элементы по строкам в столбце
2. в диапазоне ячеек подсчитывает элементы по столбцам в строке
(смотрите Debug.Print в макросах)
Изменено: ocet p - 03.03.2019 16:30:23 (ошибка в макросе)
 
Цитата
ocet p написал:
в массиве подсчитывает элементы по строкам в столбце
А у массива есть строка и столбец? А у трех мерного , а у N мерного  массива? :-)
По вопросам из тем форума, личку не читаю.
 
БМВ, Вы очень аналитический программист ... : ) ... скажу так ... с "математической" точки зрения, "массив" является матрицей, матрица имеет их: строк и столбцов.
Из чисто практического ... как бы не смотреть на это ... в пивной коробке всегда есть строки и столбцы ... : ) ... я знаю, потому что я видел это много раз ... : ) ...
 
ocet p, я просто не программист. :-)  
Цитата
ocet p написал:
с "математической" точки зрения, "массив" является матрицей
- это не верно, так как двумерный массив - это частный случай многомерного. А там есть просто один из индексов 1,2, …. N. Вот в этом порядке и меняются, и нет там строк, столбцов, рядов, …..
По вопросам из тем форума, личку не читаю.
 

Как в этом "практическом" случае видно, этот массив двумерный, и это матрица со строками и столбцами, как лист эксельа (со своими строками и столбцами) откуда она взялась. Когда она будет многомерной (больше чем 2х2), тогда мы поговорим о том, или этот "стакан наполовину полный или наполовину пустой" ... : ) ...

... это спор о номенклатуре, а не о содержании ... дело в том, чтобы "хорошо было", а "хорошо будет" тогда, когда это будет срабатывать ... или чё там ... : ) ...

 
Цитата
IgorBoot написал:
Это возможно, если делать перебор методом For Each?
правильнее в таком случае For Next. И проблем меньше и сразу понимаете где чего. For Each хорош только тогда, когда не нужно определять индекс элемента.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Дмитрий(The_Prist) Щербаков написал:
правильнее в таком случае For Next
Дмитрий, так это ж  целых 2 цикла  :-)
По вопросам из тем форума, личку не читаю.
 
по классике:
сначала создаем себе трудности For Each
а потом геройски их преодолеваем (особенно удобно, если преодолевать не самому, а кто-нибудь покажет как решается)
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Спасибо Всем за ответы.
Дисскусия привела довольно неожиданный поворот.
2 цикла так 2 цикла.
Код
Sub Test_Massib()

Dim a(), b1(), b2(), b3()

a = Range("S8:Y14")

Count = 0

For i = 1 To 7

  For j = 1 To 7
  
     If a(i, j) = 4 Then
     
       MsgBox i
       MsgBox j
     
     End If
  
  Next j

Next i

End Sub
Прошу прощения за первоначальный вопрос. Изначально я был уверен, что есть условно простой метод, который позволяет найти координату в массиве по условию.
Благодарю Всех за дисскусию.
Изменено: IgorBoot - 03.03.2019 22:16:37
 
Код
Sub aaa()
Dim aa as Range, x&, y&
Set aa=[A1:C100]
For y=1 to aa.Rows.Count
  For x=1 to aa.Columns.Count
    aa(y,x).Interior.Color=vbBlue
    MsgBox "Мы сейчас здесь - " & aa(y,x).AddressLocal(0,0)
  Next
Next
End Sub
 
... и ещё маленький обман ... : ) ...
Код
Sub Test_Massib_3()
    Const adrs$ = "S8:Y14"
    Dim a(), elmnt, adr$, chasy!
    
    a = Range(adrs).Value
    ActiveSheet.Shapes.AddTextbox(1, 350, 130, 80, 20).Name = "txt"
    For Each elmnt In a
        adr = Range(adrs).Cells(elmnt).Address(0, 0)
        ActiveSheet.Shapes.Item("txt").TextFrame.Characters.Text = elmnt & " => " & adr
        Range(adr).Select
        chasy = Timer: While Timer - chasy < 0.5: DoEvents: Wend
    Next
    ActiveSheet.Shapes.Item("txt").Delete
End Sub
 
ocet p, затем вы такие маленькие файлы ещё и в архив?
 
1. привычка приобретенная (выученная) на низкой пропускной способности (медленном соединении)
2. некоторые жаловались, что некоторые "несжатые" файлы, скачанные из интернета, не хотят открыватся
3. на сервере поместится больше файлов
 
ocet p, у меня тоже некоторые дурные привычки выработались, еще с тех пор, как бэйсик на Z-spectrum 64 k изучал...
Все три пункта сегодня в 99,9% неактуальны. ИМХО.
 
Off
п.1 - порой архив может только увеличить размер итогового файла, за счет несжимаемого содержимого, и добавления служебной информации
п.2 - бывает, когда защита срабатывает
п.3 - в данном случае только трата времени, при том  и своего и чужого. Размер практически не изменился, а чтоб открыть файл надо чуть больше времени.
По вопросам из тем форума, личку не читаю.
 
Цитата
Дмитрий(The_Prist) Щербаков: For Each хорош только тогда, когда не нужно определять индекс элемента
приветствую!
Не соглашусь, т.к. For Each быстрее и на массивах 10к+ это уже заметно. Для данного случая, безусловно, он на фиг не нужен, поскольку логика совсем другая и "костыли" со счётчиками хоть и сработают, но явно будут медленнее. А для вот таких циклов, я часто использую именно связку For Each + счётчик:
Получить индексы элементов
Изменено: Jack Famous - 04.03.2019 10:17:43
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Маленькая заметка по поводу For Each.
Давненько обнаружили (и была тема по этому поводу) - у оператора какая-то своя логика перебора. Т.е. не строго по горизонтали или вертикали.
Была задача по заливке ячеек диапазона несколькими цветами. Вот там цикл с For Each и накосячил.  
Это нужно учитывать, если перебор связан с "местоположением" элемента
 
Цитата
vikttur: не строго по горизонтали или вертикали
не заметил (или не так понял)… Логика: Столбец-Строки столбца-Следующий столбец
Изменено: Jack Famous - 04.03.2019 10:37:53
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Тему, к сожалению, не нашел. Но нашел файл  - май 2012 года (где-то в этом месяце и тема должна быть). Тогда цикл в коде пришлось заменить на два (по строкам и столбцам), т.к. ячейки закрашивались неправильно. От старого кода осталась только закомментированная строка с объявлением массива и переменных.

Тогда сошлись на том, что логика перебора  For Each отличается от обычной. Связано ли это со старой версией (писалось в Excel-2003) - не знаю, больше не проверял.
 
Цитата
vikttur: Цикл в коде пришлось заменить на два (по строкам и столбцам)
самое очевидное и правильное решение  :D
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
vikttur, Виктор, прости, но вааще пример не в кассу ибо там как бы и в массив заглядывать не имело смысла.
 Ну а код наверно был бы сейчас таким
Код
    With Worksheets("задачка")
        .Cells(72, 19).Value = 0 ' обнуление счетчика
        For Each Mycell In .Range("d73:x106").SpecialCells(xlCellTypeConstants)
             .Cells(72, 19).Value = .Cells(72, 19).Value + 1
             Select Case True
                 Case IsDate(Mycell.Value) ' если дата
                     Mycell.Interior.Color = RGB(255, 100, 30)
                 Case TypeName(Mycell.Value) = "Double" ' если число
                     Mycell.Interior.Color = RGB(125, 255, 70)
                 Case Else ' другие данные
                     Mycell.Interior.Color = RGB(50, 200, 255)
                 End Select
        Next
    End With
По вопросам из тем форума, личку не читаю.
 
Да я не помню, зачем был массив. Начала работы с VBA. А код изменен, как было поначалу... разве вспомнишь?
Была задача, реализовано с помощью For Each. Выяснилось, что местами заливка не соответствовала. Обсудили на форуме. Убрал For Each.  Заработало.

И если твой код отрабатывает правильно... Как догадка - исправлено в новых версиях?
 
OFF
Цитата
vikttur написал: Да я не помню, зачем был массив.
ну разве что для определения пустышек, а на следующем шаге все равно переходить к листу и смотреть не формула ли это. Хотя я б наверно сейчас условным форматированием все это делал.
По вопросам из тем форума, личку не читаю.
 
Цитата
Михаил Витальевич С. написал:
некоторые дурные привычки ... сегодня в 99,9% неактуальны. ИМХО
Цитата
БМВ написал:
Off
Так как и вам, мне позволено иметь свое мнение, так и себе думаю, что тройное уменьшение размера файла (с 33кБ до 10кБ) это не какое-то "некоторые дурные", или чё бы вы там хотели, или не хотели сказать об этих привычках, это соблюдение правил сетевого этикета и правил этого форума, например пункт 2.3. Но нет ничего, чтобы продлить эти соображения, это совершенно не связано с этой темой.
Всех приветствую и желаю вам хорошего настроения.
Страницы: 1
Наверх