powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Почему возникает ошибка при пеердаче пареметра A:A
25 сообщений из 27, страница 1 из 2
Почему возникает ошибка при пеердаче пареметра A:A
    #39043099
День добрый!
Есть функция, которая ищет данные в массиве. Если передавать массив с заданным диапазоном (имею ввиду такой диапазон "A1:C10", то функция работает нормально. Но если пытаюсь передать "A:C". то функция не работает. Как исправить, подскажите, пожалуйста
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Function GetLike(List As Range, ColumnCount As Integer, Optional Curr As String) As Double   v = List.Value
dd = 0
txt = Curr
For i = LBound(v) To UBound(v)
    For j = LBound(v, 2) To UBound(v, 2)
        'Debug.Print v(i, j)

         If CStr(v(i, j)) Like "*" & txt & "*" Then
            arr = Split(v(i, j), txt, , vbTextCompare)               If UBound(arr) > 0 Then
           dd = v(i, j + ColumnCount)
        End If
        End If
    Next j
Next i
GetLike = dd
End Function
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043127
Казанский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Почемучка-220,
я бы сказал, что эта функция может работать нормально только при удачном стечении обстоятельств :)
И чем Вас не устраивает обычная функция листа ВПР с тем же первым аргументом "*"&txt&"*" ?
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043128
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вероятно потому, что переменная i имеет тип Integer
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043163
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Proвероятно потому, что переменная i имеет тип Integerразве
Код: vbnet
1.
vartype(i)

будет vbInteger ?
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043177
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmk, откуда ж я знаю, я не вижу ее объявления.
А автор считает, что по фразе "то функция не работает" мы все дружно догадались, какая у него возникает ошибка.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043191
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,
MSDN LBound Function
Returns a Long containing the smallest available subscript for the indicated dimension of an array.
Почемучка-220,
Не лучше ли для перебора использовать конструкцию
Код: vbnet
1.
For Each myRange In List

?
ну и соответственно, исходя из того, что
Код: vbnet
1.
i = myRange.Column: j = myRange.Row

продолжать свои вычисления
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043212
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmkНе лучше ли для перебора использовать конструкциюлучше вообще не пользоваться перебором для такого огромного диапазона, Find будет работать гораздо быстрее
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043273
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хороший вариант. Но я бы вообще отвязался от работы с Range, и работал бы с массивом (если уж речь зашла о больших диапазонах с данными)
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043330
kos20
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmk,

Хороший, вариант. Обязательно попробую. Ошибки как таковой нет, просто висннт компьютер и все...
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043344
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kos20просто висннт компьютер и все..просто подождите подольше, он не виснет, он перебирает, а это очень долго
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043404
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kos20,
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Function GetLike(List As Range, ColumnCount As Integer, Optional Curr As String) As Double
Dim arr() As Variant
...
    arr = List
    For i = LBound(arr) To UBound(arr)
        For j = LBound(arr, 2) To UBound(arr, 2)
        ...
        Next
    Next
End Function
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043430
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И сколько памяти сожрет массив в несколько миллионов строк? ))
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043485
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProИ сколько памяти сожрет массив в несколько миллионов строк? ))исходя из размерности типа Variant. Если работать с цифровыми значениями - тогда несколько десятков мегабайт, если со строками - тут уж от длин строк зависит.
Если речь идет об экономичном расходовании/выделении памяти - никто не против - жертвуйте процессорным (и своим кстати тоже) временем: каждому своё.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043540
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В любом случае, я думаю, что вряд ли будут заполнены все доступные несколько миллионов ячеек, так что устраивать подобный цикл (по ячейкам или по массиву) - непродуктивный расход времени, поэтому Find кажется тут наиболее оптимальным вариантом. Ну или, как вариант, соотноситься с UsedRange (собственно, несложно добавить Intersect) или останавливаться после некоторого количества пустых значений.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043541
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProIntersect...точнее Union (или как его там)
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043656
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну уж не знаю.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
Sub CompareMethods()
Dim arr(1 To 1000000, 1 To 2) As Variant
Dim i As Long, j As Long
Dim r As Range

' заполнить массив
Randomize
For i = LBound(arr) To UBound(arr)
    For j = LBound(arr, 2) To UBound(arr, 2)
        'If (i + j) Mod 10 = 0 Then ' 1й вариант заполнения
        'If (i + j) Mod 2 = 0 Then ' 2й вариант заполнения
        ' 3й вариант - это отсутствие условия заполнения (заполняем всё)
            arr(i, j) = Rnd()
        'End If
    Next
Next

' массив отобразить на лист
Set r = Range("A1").Resize(UBound(arr), UBound(arr, 2))
r = arr

' поиск методом find
FooFind r

' поиск ч/з массив и like
LikeInArray r
End Sub

' процедура, использующая find
' болван здесь: https://msdn.microsoft.com/en-us/library/office/ff196143.aspx
Sub FooFind(r As Range)
Dim t As Single
Dim c As Range
Dim firstAddress As String
t = Timer

Set c = r.Find("123")
If Not c Is Nothing Then
    firstAddress = c.Address
    Do
        Set c = r.FindNext(c)
        ' ничего не делаем, просто ищем по условию
    Loop While Not c Is Nothing And c.Address <> firstAddress
End If
Debug.Print (Timer - t) * 1000 & "msec in fooFind"
End Sub

Sub LikeInArray(r As Range)
Dim t As Single
Dim i As Long, j As Long
Dim arr() As Variant

' начало замера до загрузки массива - всё по честному
t = Timer

arr = r
For i = LBound(arr) To UBound(arr)
    For j = LBound(arr, 2) To UBound(arr, 2)
        If Not IsEmpty(arr(i, j)) Then
            If arr(i, j) Like "*123*" Then
               ' ничего не делаем, но условие поиска должно быть выполнено
            End If
        End If
    Next
Next

Debug.Print (Timer - t) * 1000 & "msec in likeInArray"
End Sub

у меня find проиграл во всех случаях заполнения таблицы.
Единственный недостаток, который в общем-то никто и не отрицает - это большой объем расходуемой памяти (но об этом было выше).
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043709
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя область заполнения и область обработки совпадают.
Я же немножко о другом. Обрати внимание:Почемучка-220Но если пытаюсь передать "A:C"то есть автор пытается просматривать в цикле полностью столбец. При этом реально заполнено может быть ну пусть несколько тысяч строк. И вот тут уже fooFind тут дает фору на порядок

И еще момент - ты пытаешься искать среди чисел. Когда я заполнил ячейки текстом (а, полагаю, у автора именно текст), метод fooFind стал работать в два раза быстрее ))
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043877
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного изменил: заполняем каждую 10-ю ячейку; заполняем текстом; ищем в диапазоне "A:C"
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
Sub CompareMethods()
Dim arr(1 To 1000000, 1 To 2) As Variant
Dim i As Long, j As Long
Dim r As Range

' заполнить массив
Randomize
For i = LBound(arr) To UBound(arr)
    For j = LBound(arr, 2) To UBound(arr, 2)
        If (i + j) Mod 10 = 0 Then ' 1й вариант заполнения
        'If (i + j) Mod 2 = 0 Then ' 2й вариант заполнения
        ' 3й вариант - это отсутствие условия заполнения (заполняем всё)
            arr(i, j) = "text" & Rnd()
        End If
    Next
Next

' массив отобразить на лист
Set r = Range("A1").Resize(UBound(arr), UBound(arr, 2))
r = arr

' поиск методом find
FooFind Range("A:C") 'r

' поиск ч/з массив и like
LikeInArray Range("A:C") 'r
End Sub

в процедурах FooFind и LikeInArray в качестве подстроки для поиска использовал "t0,123"
результат: Immediate1003,906msec in fooFind
753,9063msec in likeInArrayи этот результат (проигрыш find) повторяется, как ни заполняй и исследуй диапазон. По карайней мере - у меня.Shocker.ProКогда я заполнил ячейки текстом (а, полагаю, у автора именно текст), метод fooFind стал работать в два раза быстрее )) для меня это остается загадкой.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043936
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmkи этот результат (проигрыш find) повторяется, как ни заполняй и исследуй диапазон. По карайней мере - у меня.ты создаешь UsedRange с миллионом строк и почти весь его обрабатываешь. Есть строк десять тысяч - то Find будет работать на порядок быстрее, если тысяча - на два порядка.

Но Find добивается такой скорости за счет внутреннего анализа UsedRange, я полагаю. Так что оптимальным будет твой алгоритм с массивом, который предварительно усекает диапазон до UsedRange.

hclubmkдля меня это остается загадкой.почему? Find-у не приходится делать лишнее преобразование числа в текст для каждой ячейки
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39043957
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
10000 строк
Immediate39,0625msec in fooFind
19,53125msec in likeInArray1000 строкImmediate7,8125msec in fooFind
3,90625msec in likeInArrayЗагадка кроется в том, что по твоим утверждениям, вызов методов объектной модели ExcelApplication происходит быстрее, чем работа напрямую с массивом.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39054723
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще даже в начальном варианте функции очень напрашивается Exit For после этой строки:
dd = v(i, j + ColumnCount)
hclubmkвызов методов объектной модели ExcelApplication происходит быстрее
не совсем верно. Вызов будет медленнее, чем обращение с массивом. Но вот сам поиск значения через Find на таких массивах будет быстрее. Тем более, что здесь надо искать только одно значение и завершать цикл.
Плюс Shocker.Pro правильно упомянул про память. Дело в том, что не все ПК(особенно 32-разрядные) могут выделить достаточно памяти под большой массив вроде A:C. Что вызовет ошибку Out of memory и как следствие выход из функции с ошибкой #ЗНАЧ!

Если же массив определяется заданной размерностью или хотя бы так:
Код: vbnet
1.
2.
3.
4.
dim rr as range
set rr = intersect(List.Parent.UsedRange,List)
if rr is nothing then exit function
v = rr.Value


и при этом надо вернуть более одного совпадения - то массивы несомненно выигрывают. Особенно, если учесть тот факт, что FindNext не работает при вызове из функций листа :-)
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39055072
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
The_PristThe_Pristhclubmkвызов методов объектной модели ExcelApplication происходит быстрее вырвано из контекста, и теперь выглядит как неверно истолкованное. Без отрыва же от контекста - смысловая нагрузка лежит на том, что стоило бы усомниться в быстродействии методов, предложенных оппонентом, который настаивает на том, что ты процитировал.
О памяти и о размерности массивов обсуждалось выше.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39055864
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmk,

из какого же контекста я вырвал? Вот весь текст того сообщения:
hclubmkЗагадка кроется в том, что по твоим утверждениям, вызов методов объектной модели ExcelApplication происходит быстрее, чем работа напрямую с массивом .
И чего я здесь вырвал не так? Или я этой цитатой кого-то в чем-то обвинял? Нет. Я вырвал ровно ту фразу, которую хотел процитировать, без обращения к кому-то конкретно.

Что до этой фразы и контекста. Само твое толкование мыслей Shocker.Pro не очень верное(могу ошибаться). Вызов модели Excel из VBA никак не может быть быстрее обращения к массиву, это не секрет. Суть-то в ином: обращение идет ОДИН РАЗ для вызова метода, т.к. найти надо только одно значение. Перебор же массива смешанных данных может значительно проиграть в скорости, даже с форой в виде времени, затраченного на вызов из объектной модели Excel. И Shocker.Pro говорил про то, что перебор миллиона строк будет медленнее, чем Find, если заполненных строк всего 200. Перебираешь-то ты весь массив, даже если большая часть там пуста.
Плюс неверно приведен текст fooFind, т.к. туда зачем-то цикл воткнут Do While, что не отвечает изначальным условиям поиска только первого найденного. Процедура должна выглядеть так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub FooFind(r As Range)
Dim t As Single
Dim c As Range
Dim firstAddress As String
t = Timer

Set c = r.Find("123")
If Not c Is Nothing Then firstAddress = c.Value
Debug.Print (Timer - t) * 1000 & "msec in fooFind"
End Sub


А общий текст процедур с поиском по тексту такой:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
Option Explicit

Sub CompareMethods()
Dim arr(1 To 1000000, 1 To 2) As Variant
Dim i As Long, j As Long
Dim r As Range

' заполнить массив
Randomize
For i = LBound(arr) To 300
    For j = LBound(arr, 2) To UBound(arr, 2)
        'If (i + j) Mod 10 = 0 Then ' 1й вариант заполнения
        'If (i + j) Mod 2 = 0 Then ' 2й вариант заполнения
        ' 3й вариант - это отсутствие условия заполнения (заполняем всё)
            arr(i, j) = "absolutly random text" & Rnd()
        'End If
    Next
Next

' массив отобразить на лист
Set r = Range("A1").Resize(UBound(arr), UBound(arr, 2))
r = arr

' поиск методом find
FooFind r

' поиск ч/з массив и like
LikeInArray r
End Sub

' процедура, использующая find
' болван здесь: https://msdn.microsoft.com/en-us/library/office/ff196143.aspx
Sub FooFind(r As Range)
Dim t As Single
Dim c As Range
Dim firstAddress As String
t = Timer

Set c = r.Find("123")
If Not c Is Nothing Then firstAddress = c.Value
Debug.Print (Timer - t) * 1000 & "msec in fooFind"
End Sub

Sub LikeInArray(r As Range)
Dim t As Single
Dim i As Long, j As Long
Dim arr() As Variant

' начало замера до загрузки массива - всё по честному
t = Timer

arr = r
For i = LBound(arr) To UBound(arr)
    For j = LBound(arr, 2) To UBound(arr, 2)
        If Not IsEmpty(arr(i, j)) Then
            If arr(i, j) Like "*123*" Then
               ' ничего не делаем, но условие поиска должно быть выполнено
            End If
        End If
    Next
Next

Debug.Print (Timer - t) * 1000 & "msec in likeInArray"
End Sub


В таком виде можете убедиться сами в том, что для поиска первого(одного) совпадения Find вполне себе выигрывает.
Подчеркну: для поиска первого совпадения . Для поиска всех в любом случае будет лучше подходить перебор массива(но на больших массивах у ПК может просто не хватить памяти для обработки сразу всего массива).
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39055973
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
The_Pristиз какого же контекста я вырвал?Сравни:hclubmkвызов методов объектной модели ExcelApplication происходит быстрееhclubmk по твоим утверждениям , вызов методов объектной модели ExcelApplication происходит быстрееЧувствуешь разницу? Если нет, значит нет.
The_PristВообще даже в начальном варианте функции очень напрашивается Exit For после этой строки: Исходя из этого Exit For ты ставишь под сомнение ход предыдущих решений. Согласен, Exit For напрашивается с вероятность ~50%, но где об этом сказано у ТС, что ему нужно найти первое соответствие? Тут можно сказать, что ТС хотел найти последнее значение, и возразить: если бы последнее, то почему тогда не пошел по пути обратного цикла Step -1? И т.д и т.п.
В общем, всё в стиле: небезызвестный персонажОстальное додумаете сами.
Я исходил из тех условий задачи, которые озвучил прописал ТС, ничего не додумывая.
...
Рейтинг: 0 / 0
Почему возникает ошибка при пеердаче пареметра A:A
    #39056022
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmkЧувствуешь разницу?Почувствую, когда ты наконец прочитаешь то, что написано, а не то, что ты пытаешься додумать.
Я ни к кому в своем сообщении не обращался. Или тебя задело, что я не оставил в цитате твои домыслы об утверждениях Shocker.Pro, тем самым посчитав, что я тебе приписываю фразу "вызов методов объектной модели ExcelApplication происходит быстрее"? Таких мыслей не было, я читал переписку и видел кто что пишет. Я хотел подчеркнуть именно то предложение, которое планировал обсудить. Я написал, что никто не оспаривал тот факт, что обращение к объектной модели медленнее обращения к массиву. Shocker.Pro тебе другое вроде как хотел донести - глянь на мой код в последнем сообщении - я попытался наглядно там показать.
Предлагаю обсуждать это, а не друг за друга выдумывать домыслы и утверждения :-)

hclubmkИсходя из этого Exit For ты ставишь под сомнение ход предыдущих решенийЯ в отличие от тебя ничего не ставлю. Я лишь написал, что там напрашивается выход из цикла при нахождении совпадения, исходя из текста процедуры. И никаких утверждений о необходимости не делал. Я это автору темы написал, а не чтобы какие-то там сомнения создавать.
hclubmkЯ исходил из тех условий задачи
Я из них же. Но т.к. в любом случае возвращается одно значение - то Find можно вызывать один раз:
Код: vbnet
1.
.Find(Range("A1"), , , xlPart, , xlPrevious) 'для последнего совпадения в массиве


или
Код: vbnet
1.
.Find(Range("A1"), , , xlPart, , xlNext) 'для первого


и тогда скорость значительно увеличится. И это будет более правильное сравнение Find и массивов для поиска и возврата одного значения. А про все значения я еще в первом сообщении написал.
...
Рейтинг: 0 / 0
25 сообщений из 27, страница 1 из 2
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Почему возникает ошибка при пеердаче пареметра A:A
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]