|
|
|
новичок
      
участник
Last Login: 22.05.2007 12:07
Сообщ.: 9,
Visits: 405
|
|
Доброго времени суток. Помогите пожалуйста решить вопрос.
Есть 3 листа:
На Листе1 сроки с текстом
Смирнова Анна Алексеевна, …
... , Смирнова Анна Ивановна
Иванов Алесей Алексеевич
… , Смирнов Иван Алексеевич, …
На Листе2 строка
Смирнов
есть макрос, который при совпадении имен, с Лист1 переносит найденные строки на Лист3.
Sub проверка()
Application.ScreenUpdating = False
Workbooks("Книга1.xls").Activate
Dim i, z, poisk, y
i = 1
y = 0
start:
i = i + 1
Sheets("Лист2").Select
z = Range("A" & i)
If z = Empty Then
Application.ScreenUpdating = True
Sheets("Лист2").Select
MsgBox "Нашли и перенесли - " & y
End
Else
End If
Sheets("Лист1").Select
Cells(1, 1).Select
povtor:
With Sheets("Лист1").Columns(1)
'Переменная (poisk)
Set poisk = Cells.Find(What:=z, After:=ActiveCell, _
LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
End With
If poisk Is Nothing Then
GoTo start
'Else
End If
poisk.Select
ActiveCell.EntireRow.Select
Selection.Copy
Sheets("Лист3").Select
Rows("2:2").Select
Selection.Insert Shift:=xlDown
Sheets("Лист1").Select
Selection.Delete
y = y + 1
GoTo povtor
'GoTo start
End Sub
Но вся проблема в том, что он переносит и по части слова, а нужно точное совпадение имени или фамилии. (например если искать Смирнов, то выдернет так же и Смирнова, в принципе так же как и с Иван)
Как можно ограничить поиск, и сделать его более точным?
|
|
|
|
|
Supreme Being
      
участник
Last Login: 14.12.2007 16:53
Сообщ.: 100,
Visits: 1 707
|
|
| Если у вас фамилии написаны в отдельном столбце, то попробуйте в инструкции Cells.Find замени LookAt:=xlPart на LookAt:=xlWhole P.S. xlPart искать с частью ячейки, xlWhole - искать ячейку целиком Если же у вас в одной ячейке и имя и фамилия и отчество, то попробуйте добавлять к фамилии, которую вы ищите пробел, т.е. Смирнов+пробел, тогда поиск не будет находить Смирнова, а будет находить только Смирнов. Для этого вам надо перед строкой Sells.Find добавить строку z = z & " " P.S.S. Когда выкладываете код программы, пожалуйста, берите свой код в тэги [.code] ... Ваш код... [./code] Только без точек, которые я указал внутри тэгов (это чтобы вы увидели эти тэги)
|
|
|
|
|
новичок
      
участник
Last Login: 22.05.2007 12:07
Сообщ.: 9,
Visits: 405
|
|
весь текст в одной ячейке.
ставить пробел можно, но фамилии и имена так же могут заканчиваться точкой или запятой. к тому же поиск может проходить и по другим словам не только по именам, а части слова могут встречаться в середине одного большого слова.
как можно сделать повторную проверку например: если в найденом с одной или с другой стороны буква, то значение ложно?
а в Exele есть значения как Word - любой знак, любая цифра и т.д.?
|
|
|
|
|
Supreme Being
      
участник
Last Login: 14.12.2007 16:53
Сообщ.: 100,
Visits: 1 707
|
|
| У вас переменная Poisk получает значенией всей ячейки (например, Смирнова Анна Ивановна) поэтому проверять стоит ли буква перед или после ФИО, по-моему, неправильно. По-моему, будет более правильно искать слово с добавлением пробелов 1) если ищем по фамилии, то добавляем z = z & " " (конечный пробел) 2) если ищем по имени, то добавляем z = " " & z & " " (и начальный и конеч. пробелы) 3) если ищем по отчеству, то добавляем z = " " & z (начальный пробел) Я тут немного оптимизировал ваш код, посмотрите на изменения 1) Желательно всегда объявлять переменные с указанием типа, т.е. не просто Dim i (это тоже самое, что и Dim i as Variant, т.е. зря будет выделено много памяти), а Dim i as Long (или Dim i& (& - это Long), т.к. вы знаете что i будет целым числом (т.е. номер ряда 1, 2, 3, 4 и т.д.). Переменная z всегда будет текстом, поэтому Dim z as String (или Dim z$), таким образом вместо Dim i, z, poisk, y правильнее написать
Dim i As Long, z As String, Poisk As Variant, y As Long 2) Чтобы работать с объектами в Excel - их не обязательно выделять, т.е. не надо всегда использовать метод Select - это замедляет работу макросов. Т.е. вместо кодаSheets("Лист2").Select z = Range("A" & i)можно записать z = Sheets("Лист2").Range("A" & i) 3) Когда используете конструкцию If ... Else ... End if не обязательно всегда писать Else, если у вас нет этого условия. Таким образом, если у вас нет Else и вам надо выполнить одно дейстие (т.е. GoTo start), то всю конструкцию можно записать в одну строку без End if, т.е. вместо 4-х строк кода If poisk Is Nothing Then GoTo start Else End If можно просто написать однуIf poisk Is Nothing Then GoTo start
4) Копирование информации с одного листа на другой также можно оптимизировать, чтобы было без выделения каких либо листов (первого, а потом третьего и так по кругу), т.е. вместо 7-ми строчек кода poisk.Select ActiveCell.EntireRow.Select Selection.Copy Sheets("Лист3").Select Rows("2:2").Select Selection.Insert Shift:=xlDown Sheets("Лист1").Select
можно написать одной Poisk.Copy Destination:=Sheets("Лист3").Cells(iRaz + 1, 1)Таким образом мы получаем Sub Проверка() Dim i As Long, z As String, Poisk As Variant, y As Long, iRaz As Long 'Dim i&, z$, Poisk As Variant, y&, iRaz& 'тоже самое, но короче 'Application.ScreenUpdating = False 'Workbooks("Книга1.xls").Activate iRaz = 1 i = 1 y = 0 Start: i = i + 1 z = Sheets("Лист2").Range("A" & i) If z = Empty Then Application.ScreenUpdating = True Sheets("Лист2").Select MsgBox "Нашли и перенесли - " & y End End If Povtor: With Sheets("Лист1").Columns(1) 'z = " " & z 'добавляем пробел перед словом 'z = z & " " 'добавляем пробел в конце слова 'z = " " & z & " " 'добавляем пробелы в начало и в конец слова Set Poisk = .Find(What:=z, LookIn:=xlValues) End With If Poisk Is Nothing Then GoTo Start iRaz = iRaz + 1 Poisk.Copy Destination:=Sheets("Лист3").Cells(iRaz + 1, 1) Poisk.EntireRow.Delete y = y + 1 GoTo Povtor 'GoTo start End Sub P.S. уверен, что другие участники форума ещё что-нибудь своё предложать вам. P.S.S. При поиске значения знак вопроса "?" и будет любой один знак, звёздочка "*" - много знаков )
|
|
|
|
|
новичок
      
участник
Last Login: 22.05.2007 12:07
Сообщ.: 9,
Visits: 405
|
|
супер. спасибо огромное за модернизацию. сам бы не сделал.
множество Еlse - был расчет на оветвление. например масив на разовый перенос и удаление, так как на 15-20 тысячах строк макрос просто умирает, чем дольше работает - тем дольше перенос происходит (можно на ночь включать и идти домой спать).
а что касается пробелов, как вариант удобно, есть только 1 но. заполняют ячейки кто как гаразд. запись может быть красивой как в примере, а может быть "Смирнов, звонил и просил оста...." - в таком случае такие ячейки будет пропускать. а если прийдется искать по номеру телефона - тут вообще будут пересечения городских и мобильных номеров.
P.S. а так же спасибо за инструктаж. в макросе основные действия через обычную запись макроса, потом просто склеивалось, от того и большой вышел.
|
|
|
|
|
Supreme Being
      
участник
Last Login: 14.12.2007 16:53
Сообщ.: 100,
Visits: 1 707
|
|
| Да, сложная ситуация, даже не знаю, что вам и подсказать, надеюсь другие участники вам что-нить подскажут
|
|
|
|
|
Supreme Being
      
участник
Last Login: 26.10.2007 9:10
Сообщ.: 166,
Visits: 1 538
|
|
| Вечная проблема - разобрать то, что введено второпях и часто "левой ногой". Я бы посоветовал вводить ФИО в отдельную ячейку и обязательно не прямым вводом в ячейку, а через список. Список, естественно, должен быть с возможностью пополнения. Желаю успехов.
|
|
|
|