Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / прошу помоши / 25 сообщений из 31, страница 1 из 2
18.10.2006, 12:34:30
    #34063128
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Есть полностью рабочий кода. Но работает медленно, но уверенно. Прошу подсказки - как сделать быстрее.

Код: plaintext
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.
Sub Find_to_index(list As String, index As String, val1 As String, N_horz_val1 As Integer, N_vert_val1 As Integer)
Rem зная имя листа, индекс обьекта и содержимое переменной находим обьект в его координатах
Rem возвращаем номер столбца и номер строки, содержащие обьект

Dim iRow As Integer
Dim iClm As Integer
Dim i As Integer

Узнаем номер последней строки листа
iRow = Sheets(list).UsedRange.Row + Sheets(list).UsedRange.Rows.Count -  1 
Узнаем номер последней колонки листа
iClm = Sheets(list).UsedRange.Column + Sheets(list).UsedRange.Columns.Count -  1 

rem Индекс - это имя колонки, содержащееся в первой строке.
rem Ищем совпадение  данных в первой строке с образцом
For i =  1  To iClm+ 1 
    If Sheets(list).Cells( 1 , i) = index Then GoTo Lab1 rem Нашли
Next i
Lab1:

N_horz_val1 = i
    
    If N_horz_val1 = iClm+ 1  Then
        MsgBox "На листе " + list + " не обнаружен индекс " + index
        GoTo Lab3
    End If

rem Зная колонку ищем теперь столбец
For i =  1  To iRow +  1 
    If Sheets(list).Cells(i, N_horz_val1) = val1 Then GoTo Lab2 rem нашли
Next i
Lab2:

N_vert_val1 = i

    If N_vert_val1 = iRow +  1  Then
        MsgBox "Запись " + val1 + " с индексом " + index + " не найдена на листе " + list
        GoTo Lab3
    End If

Lab3:
    

End Sub

Таким образом входящие - имя листа, индекс колонки и значение переменной. Исходящие - координаты ячейки.

Колонки могут меняться местами по этому различаю колонки по индексам, т.е. по содержимому первой строки колонки.


С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
18.10.2006, 12:44:52
    #34063175
talgat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Сначала я бы впихнул всю таблицу в массив нужной размерности, а потом
обрабатывал. Получится порядка в 300 раз быстрее будет выполнятся код.


Рыба ищет-где глубже, человек-где больше рыбы.
...
Рейтинг: 0 / 0
18.10.2006, 12:51:33
    #34063205
vkodor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
используй Find вместо пробега по колонкам и строкам
...
Рейтинг: 0 / 0
18.10.2006, 13:19:57
    #34063336
vbapro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Не обижайся, замечания не только по ускорению:
1. для того чтоб было ясно все-таки, что делает функция, объясни, что "такое индекс объекта", "переменная" и т.д.
2. используй with Sheets(list) ... end with
3. вместо GoTo Lab1 , в частности лучше exit for . также и остальные goto нужно убрать. читать будет легче.
4. действительно, как написал vkodor , используй find (хотя это может случиться и медленнее, но попробовать стоит)
5. зачем iRow = Sheets(list).UsedRange.Row + Sheets(list).UsedRange.Rows.Count - 1 , а потом For i = 1 To iRow + 1 - лишнии операции.
...
Рейтинг: 0 / 0
18.10.2006, 13:44:09
    #34063412
k-nike
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
А еще у вас комментарии про колонки и столбцы перепутаны. Непонятно.

...
Рейтинг: 0 / 0
18.10.2006, 14:11:49
    #34063519
vkodor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
vbapro
4. действительно, как написал vkodor , используй find (хотя это может случиться и медленнее, но попробовать стоит)

практика показывает что через Find быстрее
интересно посмотреть случае когда медленей
...
Рейтинг: 0 / 0
18.10.2006, 14:40:01
    #34063655
vbapro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
vkodor vbapro
4. действительно, как написал vkodor , используй find (хотя это может случиться и медленнее, но попробовать стоит)

практика показывает что через Find быстрее
интересно посмотреть случае когда медленей
писал одно, думал другое :), find быстре, примера обратного у меня нет
...
Рейтинг: 0 / 0
18.10.2006, 18:19:56
    #34064692
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
To vkodor
vkodorиспользуй Find вместо пробега по колонкам и строкам
Я бы с радостью, но что - то у меня не получается. То-ли параметры не так задаю, то-ли что-то еще.
Может есть какой примерчик (я не смог использовать тот, что в хелпе)

To vbapro
vbapro"индекс объекта" - если прочитать коментарии немного дальше, то становится ясно, - индекс это любой текст, находящийся в первой ячейке данной колонки. Поскольку места колонок могут меняться, то нужно (без задания именованых масивов) узнавать где-какая колонка.
vbapro"переменная" - набор букв и цифр, который может принимать любое значение в заданных типом переменной пределах. В данном конкретном случае это то значение, которое содержит объект.
vbapro"Объект"-в данном конкретном случае - ячейка на листе

Итого - задача (написано в самом низу в первом посте) зная лист, значение первой ячейки в столбце и значение, которое находится внутри ячейки узнать абсолютные координаты ячейки, а именно номер столбца и номер строки.

vbaproиспользуй with Sheets(list) ... end with
Хорошо. А дает ли это ускорение или какие-то другие преимущества кроме более структурированного листинга?

По поводу вашего пункта 3 - учту и сделаю

По поводу пункта 4 смотрите выше

По поводу пункта 5, действительно - лишняя операция. Не заметил.

To k-nike
k-nikeА еще у вас комментарии про колонки и столбцы перепутаны. Непонятно.

Вместо
авторrem Зная колонку ищем теперь столбец
Читать
Код: plaintext
rem Зная колонку ищем теперь строку

To All
У меня есть пример, когда осуществляется поиск данных, и потом работа с ними, но примера с поиском данных, а потом получением координат этих данных на листе у меня нет.
...
Рейтинг: 0 / 0
18.10.2006, 18:49:00
    #34064796
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Попробовал следующую конструкцию (по вашим образцам) для поиска текста в первой строке листа и определения его координат.


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
With Sheets(list)
Rem Количество колонок на листе +1
    iClm = .UsedRange.Column + .UsedRange.Columns.Count
End With
    
Rem В области от первой колонки до последней и в первой строке 
With Worksheets(list).Range(Sheets(list).Cells( 1 ,  1 ), Sheets(list).Cells( 1 , iClm -  1 ))
Rem Ищем  содержимое переменной index и узнаем адрес ячейки
    Set C = .Find(index, LookIn:=xlValues)
Rem и узнаем адрес ячейки
    firstAddress = C.Address
End With


Все великолепно. Запускается, но находит "Empty" хотя данные точно есть.
Та процедура, что была описана в начале поста великолепно их находит

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
18.10.2006, 18:55:47
    #34064815
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
To talgat

talgatСначала я бы впихнул всю таблицу в массив нужной размерности, а потом обрабатывал. Получится порядка в 300 раз быстрее будет выполнятся код.

Да-аа. Хочу посмотреть на массив во весь лист Excel, при том что листы всегда разные, и на листе до 600 столбцов и до 5000 строк. (бывают больше, бывают меньше).
И это только для того, чтобы найти координаты ОДНОЙ ячейки на листе ?

Быстрее процедура работать не станет, а вот медленнее точно. При том что на листе могут быть ка цифровые так и текстовые данные.

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
18.10.2006, 19:49:00
    #34064923
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
vbaproНе обижайся, замечания не только по ускорению:
1. для того чтоб было ясно все-таки, что делает функция, объясни, что "такое индекс объекта", "переменная" и т.д.Это не надо объяснять. Надо имена переменным давать осмысленные. Не index, а IndexOfColumn или IndexOfValueInsideColumn. Писать чуть-чуть дольше, разбираться на порядок проще и ошибок меньше.

vbapro2. используй with Sheets(list) ... end with Наоборот, не стоит это использовать. Когда в одном макросе много работаешь с With потом фиг поймешь к какому из объектов относится данная строка, приходится постоянно бегать вверх-вниз по тексту к with чтобы понять от чего мы собственно говоря берем with. А уж если начнешь делать вложеные with - получается такая каша...

vbapro3. вместо GoTo Lab1 , в частности лучше exit for . также и остальные goto нужно убрать. читать будет легче.С этим согласен.

vbapro4. действительно, как написал vkodor , используй find (хотя это может случиться и медленнее, но попробовать стоит)Стоит, стоит. Получится быстрее точно.

vbapro5. зачем iRow = Sheets(list).UsedRange.Row + Sheets(list).UsedRange.Rows.Count - 1 , а потом For i = 1 To iRow + 1 - лишнии операции.Ну циклы там вообще не нужны....


2betepon:
6. Если возвращаешь из процедуры значение через параметр - всегда указывай его явно ByRef.
7. Если нужно чего-то возвращать лучше делать функцию а не процедуру.
8. Использовать MsgBox внутри процедуры не очень хорошо. Если ты попытаешься искать несколько значений в цикле через свою процедуру, то на каждый чих пользователю прийдется нажимать кнопку. Лучше возвращать текст или объект, а потом при нужде либо показывать его на экран сразу через MsgBox или склеить несколько текстов от разных запусков процедуры и показать их все разом.

На, развлекайся:
Код: plaintext
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.
Option Explicit

Function FindValueInColumn(ByVal SheetName As String, ByVal ColumnName As String, ByVal SearchValue As Variant, _
        ByRef FoundRow As Integer, ByRef FoundColumn As Integer) As String
    Dim ws As Worksheet
    Dim rColumn As Range
    
    FoundRow =  0 
    FoundColumn =  0 
    
    On Error GoTo NoSuchSheet
    Set ws = ActiveWorkbook.Worksheets(SheetName)
    
    On Error GoTo ColumnNotFound
    Set rColumn = ws.UsedRange.Rows( 1 ).Find(ColumnName).EntireColumn
    FoundColumn = rColumn.Column
    
    On Error GoTo ValueNotFound
    FoundRow = rColumn.Find(SearchValue).Row

    FindValueInColumn = "Ok"
    Exit Function
    
NoSuchSheet:
    FindValueInColumn = "Active Workbook doesn't have sheet with name " & SheetName
    Exit Function
ColumnNotFound:
    FindValueInColumn = "Can not find column with name " & ColumnName
    Exit Function
ValueNotFound:
    FindValueInColumn = "Can not find value " & SearchValue & " in column " & ColumnName
    Exit Function
End Function

Sub test()
    Dim e As String, x As Integer, y As Integer
    e = FindValueInColumn("Sheet1", "ggg", "asd", y, x)
    If e = "Ok" Then
        MsgBox ("Found value in cell with coordinates: " & y & ":" & x)
    Else
        MsgBox ("Search failed with error: " & e)
    End If
End Sub
...
Рейтинг: 0 / 0
18.10.2006, 22:40:46
    #34065148
vbapro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
если уж пошел разбор фрагмента чуть шире, чем просили :), то в процедуре есть еще подводный камень - индекс строк Integer. нужно всегда для строк делать Long без раздумий: память не экономится, а размера типа может нехватить
...
Рейтинг: 0 / 0
19.10.2006, 09:57:06
    #34065553
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Вроде разобрался - все не так сложно. Но есть вопрос по строке

Код: plaintext
Set rColumn = ws.UsedRange.Rows( 1 ).Find(ColumnName).EntireColumn

Хочу разобраться.
Я так понял что в этой строке создается Range из одной строки с номером 1, в котором производится поиск ColumnName.
А зачем EntireColumn, и что оно такое.

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
19.10.2006, 10:31:09
    #34065654
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Вроде разобрался - как оно работает - решил проверить.

Ваш пример колонку не обнаруживает, хотя точно известно, что она есть.


С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
19.10.2006, 10:37:25
    #34065678
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Нет - все нормально. Разобрался - все работет. Ошибся при подгонке макроса к программе.


С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
19.10.2006, 10:38:56
    #34065682
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Вопрос по

Код: plaintext
Set rColumn = ws.UsedRange.Rows( 1 ).Find(ColumnName).EntireColumn

не отменяю. (хочу научится)

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
19.10.2006, 10:45:52
    #34065708
vkodor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
т. к. rColumn обьявлен как range
EntireColumn - возвращает столбец
т.е. допустим ColumnName найдено в столбце "D" диапозона ws.UsedRange.Rows(1).
следовательно rColumn = ws.Range("D:D")
...
Рейтинг: 0 / 0
19.10.2006, 13:16:31
    #34066383
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Ага. Спасибо. Теперь понял.

Огромное спасибо всем откликнувшимся. Стало работать заметно быстрее.

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
19.10.2006, 18:52:00
    #34067869
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
beteponВроде разобрался - все не так сложно. Но есть вопрос по строке
Код: plaintext
Set rColumn = ws.UsedRange.Rows( 1 ).Find(ColumnName).EntireColumn
Хочу разобраться.
Я так понял что в этой строке создается Range из одной строки с номером 1, в котором производится поиск ColumnName.
А зачем EntireColumn, и что оно такое.
Вопрос "что оно такое" надо смотреть во встроенном хелпе. Там все четко и ясно написано. Запускаешь VBA, нажимаешь F1 и ищешь непонятное слово.

А вообще, пойми одну простую вещь - любой Range это множество. И как любое множество, ты можешь разбить на маленькие множества, так и любой Range, ты можешь разбить на маленькие Range. При этом адресация ячеек внутри Range всегда соответсвет самому Range от которого берется, а не листу!
В данном случае:
UsedRange дает тебе область на листе в которой есть данные.
UsedRange.Rows(1) даст тебе первую строку области в которой есть данные. Причем это не полная строка! Если у тебя UsedRange имеет адрес относительно листа C3:F10, то UsedRange.Rows(1) даст область с адресом относительно листа C3:F3.
UsedRange.Rows(1).Find(ColumnName) - даст одну (первую) ячейку в области первая строка, занятого диапазона.
EntireColumn - (как и братский метод EntireRow) в отличие от методов Rows, Columns, Cells и Range возвращают область относительно листа а не Range от которого берутся. Поэтому UsedRange.Rows(1).Find(ColumnName).EntireColumn даст полную колонку листа.

В принципе, чтобы не заставлять эксель искать в пустых ячейках до и после реально заполненых. Можно после:
Set rColumn = ws.UsedRange.Rows(1).Find(ColumnName).EntireColumn
добавить еще одну строку
Set rColumn = Intersect(ws.UsedRange, rColumn)
Тогда rColumn вместо области D:D станет описывать область D3:D10 и поиск значения ускорится еще чуть-чуть. Заодно, если ищешь пустую ячейку, то получишь пустую ячейку внутри таблицы с данными, а не первую ячейку колонки.
...
Рейтинг: 0 / 0
20.10.2006, 10:24:44
    #34068689
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
А как в Find можно управлять направлением поиска.
Например мне надо узнать значение первой не пустой ячейки слева от текущей. т.е.
Есть лист. На нем много строк и много столбцов.
В первой ячейке каждого столбца находится дата.
задача следующая -
1. определить все даты, которые входят в промежуток -30 дней от текущей (это я сделал)
2. За дату перебрать все строки в этой колонке до конца листа. Если встретилась не пустая ячейка, тогда в этой строке ищем первое число левее текущего. Если нашли - вычитаем его из текущего. Полученную разницу суммируем с разницей по предидущей строке (если она была)
Таким образом к концу листа накапливаем сумму всех разниц.

Проблема в следующем
1. Строк много - хотелось бы игнорировать пустые строки (в данный моммент действую полным перебором)
2. быстрее находить первое число левее текущего, либо приходить к выводу, что его нет (т.е. оно равно 0)

Первую задачу я почти решил методом Find - по аналогии с предидущей.
А вот как заставить find искать в обратную сторону (справа на лево) и не конкретное значение, а первое не пустое (игнорируя при этом значения нулевые, если таковые встретятся.)


С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
20.10.2006, 10:58:36
    #34068820
vkodor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Код: plaintext
1.
2.
Cells.Find(What:="ïàïà", After:=Range("E23"), LookIn:=xlFormulas, LookAt _
        :=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
        False).Activate

After:=Range("E23") - отвечает за начало поиска

SearchOrder:=, SearchDirection:=

SearchOrder:=xlByRows, SearchDirection:=xlNext - двигаться в право потом вниз
SearchOrder:=xlByColumns, SearchDirection:=xlNext двигаться в вниз потом право
SearchOrder:=xlByRows, SearchDirection:=xlPrevious двигаться в влево потом вверх
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious двигаться в вверх потом влево



а еще есть функция End
для нахождения первой пустой ячейки очень хорошо подходит
...
Рейтинг: 0 / 0
20.10.2006, 12:23:06
    #34069294
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
А как найти первую не пустую ? Not End?

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
20.10.2006, 12:46:22
    #34069418
vkodor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Поиск последней ячейки в Excel
...
Рейтинг: 0 / 0
20.10.2006, 15:33:52
    #34070307
betepon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
Все. Сам разобрался. Там было просто.

А поиск последней ячейки мне не нужен. Но за ссылку спасибо. Воспользуюсь.

Допишу и покажу, что получилось.

С уважением BETEPON
---------------------------
Ну вот собственно и ВСЕ.
Подпись:Смерть
...
Рейтинг: 0 / 0
20.10.2006, 15:54:43
    #34070401
vkodor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
прошу помоши
beteponДопишу и покажу, что получилось.

С уважением BETEPON


жду с нетерпением
...
Рейтинг: 0 / 0
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / прошу помоши / 25 сообщений из 31, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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