Гость
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Почему возникает ошибка при пеердаче пареметра A:A / 25 сообщений из 27, страница 1 из 2
04.09.2015, 09:40
    #39043099
Почему возникает ошибка при пеердаче пареметра A:A
День добрый!
Есть функция, которая ищет данные в массиве. Если передавать массив с заданным диапазоном (имею ввиду такой диапазон "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
04.09.2015, 10:09
    #39043127
Казанский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Почемучка-220,
я бы сказал, что эта функция может работать нормально только при удачном стечении обстоятельств :)
И чем Вас не устраивает обычная функция листа ВПР с тем же первым аргументом "*"&txt&"*" ?
...
Рейтинг: 0 / 0
04.09.2015, 10:09
    #39043128
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
вероятно потому, что переменная i имеет тип Integer
...
Рейтинг: 0 / 0
04.09.2015, 10:50
    #39043163
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Shocker.Proвероятно потому, что переменная i имеет тип Integerразве
Код: vbnet
1.
vartype(i)

будет vbInteger ?
...
Рейтинг: 0 / 0
04.09.2015, 11:01
    #39043177
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
hclubmk, откуда ж я знаю, я не вижу ее объявления.
А автор считает, что по фразе "то функция не работает" мы все дружно догадались, какая у него возникает ошибка.
...
Рейтинг: 0 / 0
04.09.2015, 11:13
    #39043191
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
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
04.09.2015, 11:27
    #39043212
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
hclubmkНе лучше ли для перебора использовать конструкциюлучше вообще не пользоваться перебором для такого огромного диапазона, Find будет работать гораздо быстрее
...
Рейтинг: 0 / 0
04.09.2015, 12:15
    #39043273
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Хороший вариант. Но я бы вообще отвязался от работы с Range, и работал бы с массивом (если уж речь зашла о больших диапазонах с данными)
...
Рейтинг: 0 / 0
04.09.2015, 12:55
    #39043330
kos20
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
hclubmk,

Хороший, вариант. Обязательно попробую. Ошибки как таковой нет, просто висннт компьютер и все...
...
Рейтинг: 0 / 0
04.09.2015, 13:04
    #39043344
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
kos20просто висннт компьютер и все..просто подождите подольше, он не виснет, он перебирает, а это очень долго
...
Рейтинг: 0 / 0
04.09.2015, 13:39
    #39043404
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
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
04.09.2015, 13:57
    #39043430
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
И сколько памяти сожрет массив в несколько миллионов строк? ))
...
Рейтинг: 0 / 0
04.09.2015, 14:36
    #39043485
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Shocker.ProИ сколько памяти сожрет массив в несколько миллионов строк? ))исходя из размерности типа Variant. Если работать с цифровыми значениями - тогда несколько десятков мегабайт, если со строками - тут уж от длин строк зависит.
Если речь идет об экономичном расходовании/выделении памяти - никто не против - жертвуйте процессорным (и своим кстати тоже) временем: каждому своё.
...
Рейтинг: 0 / 0
04.09.2015, 15:16
    #39043540
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
В любом случае, я думаю, что вряд ли будут заполнены все доступные несколько миллионов ячеек, так что устраивать подобный цикл (по ячейкам или по массиву) - непродуктивный расход времени, поэтому Find кажется тут наиболее оптимальным вариантом. Ну или, как вариант, соотноситься с UsedRange (собственно, несложно добавить Intersect) или останавливаться после некоторого количества пустых значений.
...
Рейтинг: 0 / 0
04.09.2015, 15:17
    #39043541
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Shocker.ProIntersect...точнее Union (или как его там)
...
Рейтинг: 0 / 0
04.09.2015, 16:56
    #39043656
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Ну уж не знаю.
Код: 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
04.09.2015, 18:00
    #39043709
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
У тебя область заполнения и область обработки совпадают.
Я же немножко о другом. Обрати внимание:Почемучка-220Но если пытаюсь передать "A:C"то есть автор пытается просматривать в цикле полностью столбец. При этом реально заполнено может быть ну пусть несколько тысяч строк. И вот тут уже fooFind тут дает фору на порядок

И еще момент - ты пытаешься искать среди чисел. Когда я заполнил ячейки текстом (а, полагаю, у автора именно текст), метод fooFind стал работать в два раза быстрее ))
...
Рейтинг: 0 / 0
05.09.2015, 10:21
    #39043877
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Немного изменил: заполняем каждую 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
05.09.2015, 12:48
    #39043936
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
hclubmkи этот результат (проигрыш find) повторяется, как ни заполняй и исследуй диапазон. По карайней мере - у меня.ты создаешь UsedRange с миллионом строк и почти весь его обрабатываешь. Есть строк десять тысяч - то Find будет работать на порядок быстрее, если тысяча - на два порядка.

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

hclubmkдля меня это остается загадкой.почему? Find-у не приходится делать лишнее преобразование числа в текст для каждой ячейки
...
Рейтинг: 0 / 0
05.09.2015, 13:33
    #39043957
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
10000 строк
Immediate39,0625msec in fooFind
19,53125msec in likeInArray1000 строкImmediate7,8125msec in fooFind
3,90625msec in likeInArrayЗагадка кроется в том, что по твоим утверждениям, вызов методов объектной модели ExcelApplication происходит быстрее, чем работа напрямую с массивом.
...
Рейтинг: 0 / 0
18.09.2015, 10:02
    #39054723
The_Prist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
Вообще даже в начальном варианте функции очень напрашивается 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
18.09.2015, 13:47
    #39055072
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
The_PristThe_Pristhclubmkвызов методов объектной модели ExcelApplication происходит быстрее вырвано из контекста, и теперь выглядит как неверно истолкованное. Без отрыва же от контекста - смысловая нагрузка лежит на том, что стоило бы усомниться в быстродействии методов, предложенных оппонентом, который настаивает на том, что ты процитировал.
О памяти и о размерности массивов обсуждалось выше.
...
Рейтинг: 0 / 0
19.09.2015, 11:19
    #39055864
The_Prist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
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
19.09.2015, 14:46
    #39055973
hclubmk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
The_Pristиз какого же контекста я вырвал?Сравни:hclubmkвызов методов объектной модели ExcelApplication происходит быстрееhclubmk по твоим утверждениям , вызов методов объектной модели ExcelApplication происходит быстрееЧувствуешь разницу? Если нет, значит нет.
The_PristВообще даже в начальном варианте функции очень напрашивается Exit For после этой строки: Исходя из этого Exit For ты ставишь под сомнение ход предыдущих решений. Согласен, Exit For напрашивается с вероятность ~50%, но где об этом сказано у ТС, что ему нужно найти первое соответствие? Тут можно сказать, что ТС хотел найти последнее значение, и возразить: если бы последнее, то почему тогда не пошел по пути обратного цикла Step -1? И т.д и т.п.
В общем, всё в стиле: небезызвестный персонажОстальное додумаете сами.
Я исходил из тех условий задачи, которые озвучил прописал ТС, ничего не додумывая.
...
Рейтинг: 0 / 0
19.09.2015, 16:22
    #39056022
The_Prist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему возникает ошибка при пеердаче пареметра A:A
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
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Почему возникает ошибка при пеердаче пареметра A:A / 25 сообщений из 27, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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