Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.79/112: Рейтинг темы: голосов - 112, средняя оценка - 4.79
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48

Ошибка Run time error ‘-2147417848 (80010108)’

18.07.2013, 21:58. Показов 25162. Ответов 102
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.

Долгое время работал с макросом в Эксель 2010, ищущем дубли на листе:
1. в пустую ячейку столбца С, следующую за последней заполненной, вставляется слово, по которому идёт поиск дублей (или несколько слов вставляются последовательно в соответствующее кол-во ячеек столбца С, если нужно найти дубли сразу нескольких слов);
2. выделяется ячейка, содержащая это слово (или верхнее из слов, если их несколько), запускается макрос поиска дублей по всем ячейкам столбца С;
3. макрос пробегает все ячейки столбца С и находит дубли;
4. вырезает строку/строки с ячейками от A до Z, где в столбце С был найден дубль поискового слова/слов;
5. вставляет найденные строки в пустые строки в конце файла (т.е. в строки, следующие за строками, содержащими слова, по которым ведётся поиск дублей);


Visual Basic
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
Sub FindDub()
Range("Y:Y").Clear
Application.ScreenUpdating = False
StartCell = ActiveCell.Row
lastcell = Cells(Rows.Count, 3).End(xlUp).Row
Delta = 1
ColDub = 25
For a = 1 To StartCell - 1
  If Cells(a, 3).Value <> "" And Cells(a, ColDub).Value <> 1 Then
    For b = StartCell To lastcell
      If b <> a Then
         If UCase(Cells(a, 3).Value) = UCase(Cells(b, 3).Value) Then
          Range("A" & a & ":" & "Z" & a).Select
          Selection.Cut
          Range("A" & (lastcell + Delta) & ":" & "Z" & (lastcell + Delta)).Select
          ActiveSheet.Paste
          Delta = Delta + 1
          Cells(b, ColDub).Value = 1
         End If
      End If
    Next
  End If
  Next
    LastRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count
    For r = LastRow To 1 Step -1
    If Application.CountA(Rows(r)) = 0 Then Rows(r).Delete
    Next r
Application.ScreenUpdating = True
End Sub
Неделю назад, когда число строк перевалило за 60000, стала вылетать ошибка:
Run time error ‘-2147417848 (80010108)’:
Method ‘Paste’ of object ‘_Worksheet’ failed

После нажатия Debug выделяется строка
ActiveSheet.Paste

При этом таки находится дубль 1-ой строки, но удалить никакую строку после этого невозможно - эксель просто не реагирует на попытку удаления строк и макрос поиска дублей больше не работает, а вот все остальные - работают. После перезагрузки экселя можно удалять строки, но при поиске дублей, ситуация повторяется.

Огромная просьба: помогите пожалуйста оптимизировать макрос, чтобы данная ошибка не возникала. Сколько сам не бился, не удалось исправить.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.07.2013, 21:58
Ответы с готовыми решениями:

Ошибка VBA: Run time error ‘-2147417848 (80010108)’: Method ‘Paste’ of object ‘_Worksheet’ failed
Пожалуйста, помогите! При записи макроса для копирования столбцов с одного листа на другой VBA выдал код: ...

Периодическая Run-time error '-2147417848(80010108)'
Замучил периодически повторяющийся глюк в довольно объемном проекте (в стадии разработки) - в совершенно обычной многократно отлаженной и...

Ошибка Run-time error '13'
При заполнении таблицы на 3-4 строке выскакивает вот это; 'общая стоимость Dim a As Currency a =...

102
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,961
Записей в блоге: 4
19.07.2013, 13:21
Студворк — интернет-сервис помощи студентам
попробуйте. может что упустила

Code
1
2
3
4
dim a as long
dim b as long
dim r as long
dim delta as long
0
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
19.07.2013, 13:40  [ТС]
shanemac51, бесполезно я и сам пытался что только можно с данным макросом сделать...
Но здесь, видимо, нужно макрос полностью переписать под другой метод поиска...
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,961
Записей в блоге: 4
19.07.2013, 14:19
данные типа integer 65000 зап
long ------------2 000 000 000
-------
это важно
может циклы по разному выполняются

Code
1
2
3
4
sub mm()
dim a as long dim b as long dim r as long dim delta as long
'''' обработка
end sub
1
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
19.07.2013, 15:59  [ТС]
shanemac51, да проверял я это дело. Увы, тут дело похоже уже в самом алгоритме. Слишком он таким способом перебора перегружен.
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
19.07.2013, 16:42
To oxe. Здравствуйте. Раз вчера вошел - обязательно посмотрю тоже, но как только вырву время. Но вопрос. В Вашем примере "слово 12" встречается три раза и все в столбце С. Где его нужно искать? Только по С, или по всему листу в всех ячейках UsedRange? И только это слово Вам интересует, или все слова-критерии в ст. С? Я, например, вчера так понял, что в ст.С Вы собираете только критерии поиска.
0
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
19.07.2013, 17:40  [ТС]
Igor_Tr, Добрый день

Мой пример находится в посте #17. Там "Слово 12" только в 2-х местах - первое в строке, которую поиск дублей должен найти, второе - в ячейке, которую нужно выделить для запуска поиска дублей.

Алгоритм в самом первом посте прописан: "...запускается макрос поиска дублей по всем ячейкам столбца С".

В столбце С располагаются слова-идентификаторы, к которым фактически привязана инфа в остальных ячейках этой же строки (в колонках A-B, D-Z).
Соответственно, в пустую ячейку (ячейки) столбца С (следующих за заполненными) помещаются слова-идентификаторы (по 1 в ячейку последовательно друг за другом), по которым я хочу найти дубли во всём вышеидущем столбце С.

Добавляю более понятный пример:
Выбери ячейку со словом-идентификатором "Слово 12" в 18-ой строке
Нажми поиск дублей
Он будет искать дубли по столбцу С строкам 4-17 к словам идентификаторам "Слово 12" и следующим за ним "Слово 4857295" и "Слово 04"
В строках, содержащих поисковые ячейки "Слово 12" и "Слово 04", по которым найдёт дубли - в столбце Y поставит "1". В строке с "Слово 4857295" ничего не появится т.к. дубля нету.
Смысл в том, чтобы выкинуть строки вместе со всей инфой в столбцах A-Z в конец файла путём нахождения этих строк по однозначным словам-идентификаторам, содержащимся в столбце С.
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
19.07.2013, 18:07
Попробуйте, посмотрим, как ругаться будет. Он попросит - Вы ему просто мышкой укажите ячейку с Вашим критерием (где слово12).
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Sub asdfsdf()
   Dim j&, mstr$, mRNG As Range, cC As Range
j = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count
mstr = Application.InputBox(" Select cell with your word", , , , , , , 8).Value
   With ActiveSheet
      .Range("a3").AutoFilter Field:=3, Criteria1:=mstr
      Set mRNG = Range(Cells(2, 1), Cells(j, 1)).SpecialCells(xlCellTypeVisible)
      .Range("a3").AutoFilter
         For Each cC In mRNG
            cC.Rows.EntireRow.Copy .Cells(Rows.Count, "a").End(xlUp).Offset(1, 0)
         Next cC
   End With
End Sub
0
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
19.07.2013, 18:22  [ТС]
эммм... попробовал. Найти то он нашёл, но только по 1 слову, при этом вписав найденную строку заместо него. Следующие за ним слова проигнорировал.
Да и строку скопировал а не перенёс т.е. сделав 2 дубля одной строки

В исходном файле с 60 000 строк эксель просто завис после запуска


З.Ы. сегодня вынужден уехать на дачу, буду завтра ближе к вечеру
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
19.07.2013, 18:53
Следующие за ним слова проигнорировал
Какие именно? Я совсем запутался. Он копирует, и вставляет в конце листа в свободную строку с форматированием и т.д. Не могу понять... Нужно найденую строку еще и удалить? А форматирование не надо? Если не надо - еще проще.
А слова? Он должен искать все слова, которые ниже слово12? Или выше? Может, для наглядности, пусть он их закидывает внизу через строку? Тогда найдите похожую на эту в коде:
cC.Rows.EntireRow.Copy Cells(Rows.Count, "a").End(xlUp).Offset(1, 0)
и замените на cC.Rows.EntireRow.Copy Cells(Rows.Count, "a").End(xlUp).Offset(2, 0)

Добавлено через 20 минут
Присмотрелся к Вашему коду. Если судить по этому If UCase(Cells(a, 3).Value) = UCase(Cells(b, 3).Value) Then, тогда я понимаю так:
Основной критерий - "слово12" в ст.С.
Найти дубли где в строке по ст.С есть "слово12" и при этом значение ячейки в найденом ряду в ст.А = значению ячейки в найденом ряду ст.B. Теперь я так понял? Если да, то кол-во дублей считать?
0
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
19.07.2013, 20:25  [ТС]
Igor_Tr, нет
Вы макрос, тот что я в примере давал, запускали? По-моему, это самый простой способ понять, что должен делать макрос, увидев что он выдаст.

Выбери ячейку со словом-идентификатором "Слово 12" в 18-ой строке
Нажми поиск дублей
Он будет искать дубли по столбцу С строкам 4-17 к словам идентификаторам "Слово 12" и следующим за ним "Слово 4857295" и "Слово 04" - только по столбцу С! Значение других столбцов при этом значения не имеет!
В строках, содержащих поисковые ячейки "Слово 12" и "Слово 04", по которым найдёт дубли - в столбце Y поставит "1". В строке с "Слово 4857295" ничего не появится т.к. дубля нету.
Смысл в том, чтобы выкинуть строки (т.е. переместить оттуда где они в середине файла валяются в конец файла для дальней работы с ними, именно переместить - плодить повторы не нужно ) вместе со всей инфой в столбцах A-Z в конец файла путём нахождения этих строк по однозначным словам-идентификаторам, содержащимся в столбце С.


Если да, то кол-во дублей считать? - не надо
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
19.07.2013, 22:10
Я понял. Находим все дубли. Все дубли удаляются с тела основной таблицы, но одна копия сохраняется ниже списка критериев, который (список) прописывается после последней записи таблицы в ст.С. Так? И копии мы определяем только по критериям в ст.С.

Добавлено через 1 час 27 минут
Пробуйте. В понедельник еще Dragokas обещал посмотреть. А может еще кто-то. Не пойдет - еще что-нибудь смонтируем. Было бы что поломать! Хотел сестре очень отомстить. Не помню за что. Купил племяннику барабан. Думал - месть удалась. Ага! На второй день она спросила у малого: " А что там в середине так красиво гремит?" И моя ужасная месть закончилась.
Visual Basic
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 asdfsdf()
   Dim i&, j&, k&, mRNG As Range, cC As Range, marr(), arrRow()
   Application.ScreenUpdating = False
   j = Cells(Rows.Count, "a").End(xlUp).Row
   marr = Range(Cells(j + 1, "c"), Cells(Rows.Count, "c").End(xlUp)).Value
      With ActiveSheet
         For i = LBound(marr, 1) To UBound(marr, 1)
            .Range("a3").AutoFilter Field:=3, Criteria1:=marr(i, 1)
            Set mRNG = Range(Cells(2, 1), Cells(j, 1)).SpecialCells(xlCellTypeVisible)
            ReDim arrRow(1 To mRNG.Cells.Count):   k = 1
               For Each cC In mRNG
                  arrRow(k) = cC.Row: k = k + 1
               Next 'cC
            .Range("a3").AutoFilter
            mRNG.Cells(1).Rows.EntireRow.Copy .Cells(Rows.Count, "c").End(xlUp).Offset(1, -2)
               For k = UBound(arrRow) To LBound(arrRow) Step -1
                  Rows(arrRow(k)).Delete:  j = j - 1
               Next 'k
         Next 'i
         Erase arrRow: Set mRNG = Nothing
         For i = UBound(marr, 1) To 1 Step -1
            .Rows(j + UBound(marr, 1)).ClearContents: j = j - 1
         Next 'i
      End With
      Application.ScreenUpdating = True
      Erase marr:   MsgBox Space(10) & "D O N E!"
End Sub
Добавлено через 5 минут
!!! Забыл !!! Пишете внизу все свои критерии (1, 5,...., сколько надо) и просто запускаете код. Он соберет их в массив и сделает все сам.
1
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18035 / 7738 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
20.07.2013, 00:03
Igor_Tr, автофильтр... браво, класс
А строки 16-18, чтобы снова не зависло все? =)))
Так должно быть быстрее (но выживет ли - вот в чем вопрос):
Visual Basic
1
mRNG.EntireRow.Delete
2
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
20.07.2013, 11:57
To Dragokas. Еще не уверен, но уже жалею про автофильтр. Накопировал немного больше 30 000 строк для теста. Из-за моей глупости код остановился на середине (автофильтр в работе, строки собраны). Я его вручную развернул - вот он разворачивался больше 10 сек. точно. Правда, я в эти игры играю на слабеньком ноуте ( вот, свои плюсы слабости). Думаю теперь, может через коллекцию переписать? За подсказку - спасибо. Там еще есть ошибка - создание массива. Если много критериев - нормально, а один - ругается. Пособираю все, завтра поправлю.

Добавлено через 10 часов 10 минут
To Oxe. Немного коду "сделал прическу", учтено замечание от Dragokas, убрал свои промашки. И еще. Теперь критерии в С не обязательно писать подряд. Код стал более вежливый. Если еще и работать будет.... А то я что-то стал с опаской смотреть на AutoFilter (по скорости). Пробуйте, там увидим. И может еще кто-то что-то подскажет. Видите, а Вы хотели через личку! Сейчас бы мы шептались с Вами. С умным видом.
Visual Basic
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
Sub v2_my60000()
Dim i&, j&, mrng As Range, marr(), sttime!
    sttime = Timer
    Application.ScreenUpdating = False
      j = Cells(Rows.Count, "a").End(xlUp).Row
      If j + 1 <> Cells(Rows.Count, "c").End(xlUp).Row Then
         For i = Cells(Rows.Count, "c").End(xlUp).Row To j Step -1
            If Application.CountA(Rows(i)) = 0 Then Rows(i).Delete
         Next 'i
         marr = Range(Cells(j + 1, "c"), Cells(Rows.Count, "c").End(xlUp)).Value
            Else
               ReDim marr(1 To 1, 1 To 1): marr(1, 1) = Cells(j + 1, "c").Value
      End If
   With ActiveSheet
      If .Cells.AutoFilterMode Then .Cells.AutoFilter
      For i = LBound(marr, 1) To UBound(marr, 1)
            .Range("a3").AutoFilter Field:=3, Criteria1:=marr(i, 1)
            Set mrng = Range(.Cells(2, 1), .Cells(j, 1)).SpecialCells(xlCellTypeVisible)
            Select Case mrng.Cells.Count
                Case Is < 2: MsgBox "Not found dublicate for " & marr(i)
                Case Is > 1
                    .Range("a3").AutoFilter
                    mrng.Cells(1).Rows.EntireRow.Copy .Cells(Rows.Count, "c").End(xlUp).Offset(1, -2)
                    j = j - mrng.Cells.Count
                    mrng.EntireRow.Delete
            End Select
        Next 'i
        Set mrng = Nothing
        For i = UBound(marr, 1) To 1 Step -1
            .Rows(j + UBound(marr, 1)).ClearContents: j = j - 1
        Next 'i
    End With
    Application.ScreenUpdating = True
    MsgBox ("Time:   " & Format(Timer - sttime, "#,##0.00"))
    Erase marr: MsgBox (Space(10) & "D O N E!")
End Sub
1
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
20.07.2013, 21:15  [ТС]
Я понял. Находим все дубли. Все дубли удаляются с тела основной таблицы, но одна копия сохраняется ниже списка критериев, который (список) прописывается после последней записи таблицы в ст.С. Так? И копии мы определяем только по критериям в ст.С.

Да, абсолютно верно! Разве что уточнение:
Все дубли удаляются с тела основной таблицы, но одна копия каждого сохраняется...
в теории к каждому критерию должен находиться только 1 дубль... но, как говорится, никто не застрахован

"И моя ужасная месть закончилась."
спасибо за подсказку! Возможно в будущем пригодится

Насчёт входных строк: можно их не удалять, а в столбце Y помечать "1" к тем, по которым дубли нашлись?
Удаление входных строк не всегда удобно - например, при поиске сразу по сотне критериев, сложно будет отыскивать начало выпавших дублей... разве что помечать его как-то?
И что при этом произойдёт с критериями, по которым дубли не найдутся? Мне нужно чтобы эти критерии обязательно остались. Как раз к этим критериям и будет новая инфа писаться. Сообщение, что дубли по ним не нашлись, не обязательно

Т.е. если к критерию дубль нашёлся, то работа идёт с той инфой что дубль содержит, а если не нашёлся - к нему новая инфа будет записана.
Получается, что либо удалять только те критерии, к которым найдутся дубли, и оставлять остальные для дальнейшей работы с ними, при этом помечая верхний из выпавших дублей (какой-нибудь легко или самостоятельно снимающейся отметкой - а то при сотне поисков по 1 дублю заколебаешся их снимать ), либо просто помечать те критерии, к которым найдутся дубли "1" в строке Y и в дальнейшем их в ручную удалять. Мне кажется проще реализовать 2-ой вариант, но буду рад любому ))

"Если много критериев - нормально, а один - ругается"
Чаще всего с 1-м и работаю

Igor_Tr, Dragokas, shanemac51, Спасибо огромное за помощь! К сожалению, мои познания в VB пока не достаточны, чтобы самому нечто подобное написать


З.Ы. К сожалению оттестировать могу только в рабочее время по будням В понедельник буду пробовать!
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
21.07.2013, 15:18
Жена считает, что если в суботу меня не загрузит, я наверное на другой конец света убегу.
Короче, ничего мне там не нравится. Немного изменил. Теперь так. Он проверяеть дубли, только взяв за ОСНОВУ критерии. Кроме совпадения по нему, он еще хочет полное совпадение по всему ряду критерия (это все из-за того, что, подозреваю, не совсем правильно понимаю и задачу, и цели). В первой части удаляет все дубли. Потом Ваши критерии берет как запрос поиска и выдает, все что найдет. Пробуйте. Если все-таки Вам нужно дубли только и только! по критерию - найдете в коде это выражение:
mrng.RemoveDuplicates (marr), xlNo
и замените этим:
mRNG.RemoveDuplicates Columns:=3, Header:=xlNo
3 - это номер столбца (С), в которых Ваши критерии. Должен бегать веселее. Все. Может кто-то еще что-то придумает. Но если чесно - я бы подобное для себя делал как-то по другому. Сам Ваш принцып мне совсем не нравится. Ну а если будет работать - хотелось бы знать время. Я в свой ноут 60 тыс. Ваших строк запихнуть не смог.
Visual Basic
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
Sub delDUBLICATE_60000()
   Dim mrng As Range, i&, j&, n&, k&, marr(), sttime!
   Application.ScreenUpdating = False
   sttime = Timer
   With ActiveSheet
      If .AutoFilterMode = True Then .AutoFilterMode = False
      n = .UsedRange.Column - 1 + .UsedRange.Columns.Count
      Set mrng = Range(.Cells(3, 1), .Cells(.UsedRange.Row - 1 + .UsedRange.Rows.Count, n))
      ReDim marr(0 To n - 1):    j = 0
         For i = 1 To n:      marr(j) = i:   j = j + 1:   Next 'i
      mrng.RemoveDuplicates (marr), xlNo
'--End--Part1----------------------------------------------------
      j = Cells(Rows.Count, "a").End(xlUp).Row
         If j + 1 <> Cells(Rows.Count, "c").End(xlUp).Row Then
            For i = Cells(Rows.Count, "c").End(xlUp).Row To j Step -1
               If Application.CountA(Rows(i)) = 0 Then Rows(i).Delete
            Next 'i
            marr = Range(Cells(j + 1, "c"), Cells(Rows.Count, "c").End(xlUp)).Value
               Else
                  ReDim marr(1 To 1, 1 To 1): marr(1, 1) = Cells(j + 1, "c").Value
         End If
         j = .Cells(.Rows.Count, "c").End(xlUp).Row:   k = j - UBound(marr, 1)
         For i = LBound(marr, 1) To UBound(marr, 1)
            .Range(Cells(2, 1), Cells(k, n)).AutoFilter Field:=3, Criteria1:=marr(i, 1)
            On Error Resume Next: Err.Number = 0
            Set mrng = Range(.Cells(3, 1), .Cells(k, n)).SpecialCells(xlCellTypeVisible)
               Select Case Err.Number
                  Case Is <> 0: MsgBox "Not found criteria   " & marr(i, 1): .AutoFilterMode = False
                  Case Is = 0
                     mrng.Rows.Copy .Cells(j + 1, 1): .AutoFilterMode = False
                     j = .Cells(.Rows.Count, "c").End(xlUp).Row
               End Select
         Next 'i
   End With
   Application.ScreenUpdating = True: ActiveWindow.ScrollRow = j
   Erase marr:  Set mrng = Nothing: MsgBox "My TIME:" & Space(3) & Format(Timer - sttime, "#0.00000")
End Sub
Еще. Теперь уже на кол-во критериев не ругается. Загоняйте - сколько хотите.

Добавлено через 17 часов 12 минут
To Oxe. Все выкидывайте в мусор!!! Правильно я грешил на AutoFilter. Немного подправил, и сделал ч/з словарь, в который вкладывал коллекцию нужных диапазонов. Скорость увеличилась в 8 (!!!) раз. При этом 3/4 времени уходит на удаление дубликатов (если учесть, что я Ваш маленький пример увеличил до 25 000 строк - это и не удивительно ) . Вот теперь мне уже начинает код нравиться. И еще - если Вы не укажете критерии, код просто удалит дубликаты и остановится. Можете использовать и для этого.
Visual Basic
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
Sub vDICT_delDUBLICATE_60000()
   Dim mrng As Range, i&, j&, n&, k&, marr(), stTime!, cC As Range
   Dim dict As Object, elt, colEL, inELT
   Application.ScreenUpdating = False
   stTime = Timer
'   --Remove--All--DUBLICATE--------------------
   If ActiveSheet.AutoFilterMode Then ActiveSheet.AutoFilterMode = False
   With ActiveSheet
      n = .UsedRange.Column - 1 + .UsedRange.Columns.Count
      Set mrng = Range(.Cells(3, 1), .Cells(.UsedRange.Row - 1 + .UsedRange.Rows.Count, n))
      ReDim marr(0 To n - 1):    j = 0
         For i = 1 To n:      marr(j) = i:   j = j + 1:   Next 'i
      mrng.RemoveDuplicates (marr), xlNo
      j = .Cells(Rows.Count, "c").End(xlUp).Row
         With Range(.Cells(j + 1, 1), .Cells(Rows.Count, Columns.Count))
            .ClearComments: .Interior.ColorIndex = xlNone
         End With
'==End==REMOVE==============================
      k = .Cells(Rows.Count, "a").End(xlUp).Row
         If j - k > 1 Then
            For i = j To k + 1 Step -1
               If Application.CountA(.Rows(i)) = 0 Then .Rows(i).Delete: j = j - 1
            Next 'i
         End If
      Select Case j - k
         Case Is = 0: MsgBox "My TIME:" & Space(3) & _
                  Format(Timer - stTime, "#0.00000") & Chr(13) & Chr(13) & _
                        "THE   CRITERIAS   ARE   NOT SPECIFIED."
            ActiveWindow.ScrollRow = j:    Exit Sub
         Case Is = 1:  ReDim marr(1 To 1, 1 To 1): marr(1, 1) = LCase(Application.Trim(.Cells(j, "c").Value))
         Case Is > 1
            marr = Range(.Cells(j, "c"), .Cells(k + 1, "c")).Value
      End Select
      Set dict = CreateObject("scripting.dictionary")
      dict.comparemode = 1
         For i = LBound(marr, 1) To UBound(marr, 1)
            If Not dict.exists(marr(i, 1)) Then dict.Add marr(i, 1), New Collection
         Next 'i
         Erase marr
         For Each cC In Range("c3:c" & k)
            If dict.exists(LCase(Application.Trim(cC.Value))) Then
               With dict.Item(LCase(Application.Trim(cC.Value)))
                  .Add Range(.Cells(cC.Row, 1), .Cells(cC.Row, n))
               End With
            End If
         Next 'cC
         For Each elt In dict.keys
            Set colEL = dict.Item(elt)
               For Each inELT In colEL
                  inELT.Copy .Cells(.Rows.Count, "c").End(xlUp).Offset(1, -2)
               Next
         Next
   End With
   Set mrng = Nothing:  Application.ScreenUpdating = True:  ActiveWindow.ScrollRow = j
   set dict=Nothing:  MsgBox "My TIME:" & Space(3) & Format(Timer - stTime, "#0.00000")
End Sub
Добавлено через 11 минут
2
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
21.07.2013, 20:35  [ТС]
Igor_Tr, огромное спасибо завтра буду тестировать!

Не очень понял "И еще - если Вы не укажете критерии, код просто удалит дубликаты и остановится. Можете использовать и для этого." Дубликаты чего код удалит, если критерии не указать, ведь дубликаты как раз по критериям и ищутся... или я уже запутался в терминологии?
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
21.07.2013, 21:22
Ну вот так. У Вас есть таблица. В ней, по каким-то причинам, несколько раз записана одна и та же строка (в любых разных местах. Вы указываете критерии в самом низу таблицы, где -то (не имеет значения), но после последней записи, и в ст. С (имеет значение). Так вот, если Вы там ничего не укажете - код просто проверит все строки таблицы и если найдет полное совпадение - оставит только одну. Другими словами, этот код, при указанных условиях, можна использовать для удаления лишних (полностью повторяющихся) записах. А так - сделайте копию Вашего листа и на нем тестируйте.

Добавлено через 31 минуту
Придумал, как обяснить. Я не русский, поэтому мне тяжело иногда и понять, и обяснить. Другими словами, если у Вас в ст. С есть несколько "Слово N", и при этом в некоторых строках, которые соответствуют этим "Слово N", хотя бы в одной ячейке, будет какое-нибудь-отличие, код не тронет. Отличия не будет - код лишние (дубли) удалит, оставит только одну такую. Это если не указать критерии. Если указать - то же самое, но еще и внизу покажет, что он удалял (а зачем???). В последнем случае - у Вас на листе будет две идентичные строки. Одна (оригинал) где-то в таблице, другая - внизу, в "отчете". Вот и я не понимаю всю эту Вашу архитектуру. Зачем это все надо.... Удалить дубликаты - это одно. Найти и куда-то вставить все строки по Вашим критериям - это другое. А то, что мы делаем здесть - одно удивление.
0
0 / 0 / 0
Регистрация: 18.07.2013
Сообщений: 48
21.07.2013, 23:04  [ТС]
Igor_Tr, мда... кажется мы запутались Однозначно запутались видимо совсем не умею объяснять... Вы макрос мой запускали, видели что он делает?

"Придумал, как обяснить. Я не русский, поэтому мне тяжело иногда и понять, и обяснить. Другими словами, если у Вас в ст. С есть несколько "Слово N", и при этом в некоторых строках, которые соответствуют этим "Слово N", хотя бы в одной ячейке, будет какое-нибудь-отличие, код не тронет. Отличия не будет - код лишние (дубли) удалит, оставит только одну такую. Это если не указать критерии."
Полезно, да но в экселе и так есть встроенная функция, которая делает тоже самое Удаление дублей называется. Эта функция мне совершенно не нужна, тем более если она занимает много времени

Собственно, в приведённом мной примере, в том макросе, что есть сейчас, видно что я хочу получить - именно перенести найденные по критерию строки в низ файла.
Т.е. мне нужно обновить инфу в некой строке (имеется в виду инфа в столбцах A-B, D-Z, инфа в столбце С неизменна и однозначно определяет нужную строку). Я вставляю критерий (то что содержится в столбце С) и запускаю поиск дублей по этому критерию. Цель - получить имеющуюся строку в конец файла и обновить в ней инфу (одна из ячеек строки - дата обновления инфы - именно поэтому строка нужна внизу). Мне совершенно не нужно чтобы где-то осталась валяться строка со старой инфой.

"Если указать - то же самое, но еще и внизу покажет, что он удалял (а зачем???)."
Ни за чем. Это не нужно.

"Найти и куда-то вставить все строки по Вашим критериям - это другое"
Вот именно это мне и надо!

И вопрос: что произойдёт с критериями, по которым мы ищем дубли? С теми, по которым найдёт, и с теми, по которым не найдёт? В настоящий момент с теми, по которым найдёт - в столбце Y ставится "1", с теми, по которым не найдёт - просто остаются в конце файла и к ним инфа пишется как к новым уникальным критериям.

Так что Вы сильно перемудрили извиняюсь, если это я так запутал своими объяснениями...
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
22.07.2013, 00:09
В этой книге три листа. Я немного изменил. Посмотрите внимательно. На листе ...Before там есть дубли. Для одного из дублей "слово 12" в ячейке А изменил содержание (выделено шрифтом). Если нажать маленькую кнопочку "Do it!" - результат будет как на листе ...After. Прежде, чем нажимать - внимательно просто посмотрите на эти листы. Все дубли будут удалены, а слово 12 в основной таблице будет 2 раза (не совпадения по ст.А). Так понятно?
Вложения
Тип файла: rar New_TASK.rar (66.8 Кб, 9 просмотров)
0
4377 / 661 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
22.07.2013, 00:48
Друзья пришли. Иду на пиво - пишу на предупреждение. Если не нужно обращать внимание на ст. А (и/или b,d,g,..) - замените в коде блок (я его специально отделил), ориентируйтесь на ' --Remove--All--DUBLICATE-------------------- (это начало блока) и на '==End==REMOVE================== (это конец блока) этим блоком:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
'   --Remove--All--DUBLICATE--------------------
   With ActiveSheet
      n = .UsedRange.Column - 1 + .UsedRange.Columns.Count
      Set mRng = Range(.Cells(3, 1), .Cells(.Cells(Rows.Count, "a").End(xlUp).Row, n))
      ReDim mARR(0 To n - 1):   For i = 1 To n:     mARR(i - 1) = i:   Next 'i
      mRng.RemoveDuplicates (3), xlNo
      j = .Cells(Rows.Count, "c").End(xlUp).Row
         With Range(.Cells(j + 1, 1), .Cells(Rows.Count, Columns.Count))
            .ClearComments:   .Interior.ColorIndex = xlNone
         End With
'==End==REMOVE==============================
Тогда код не будет принимать в внимание ст. А (и/или b,d,g,..). Запустите - и увидите, что в основной таблице останется только одно "слово 12". Поганяйте, присмотритесь.

Добавлено через 11 минут
Ага! Там еще и еденица! Найдите этот блок:
Visual Basic
1
2
3
4
5
6
For Each cC In .Range("c3:c" & k)
   If dict.exists(LCase(Application.Trim(cC.Value))) Then
         With dict.Item(LCase(Application.Trim(cC.Value)))
               .Add Range(Cells(cC.Row, 1), Cells(cC.Row, n))
         End With 'dict.Item()
   End If
и в нем, между End With 'dict.Item() и End If вставьте это: .Cells(cC.Row, "y").Value = 1. И все. А что Вы будете делать дальше с этой единицей? Удачи. Завтра вернусь. Сюда, в смысле, в форум.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.07.2013, 00:48

Ошибка Run-time error 76
Добрый день! У меня есть вот такой код для копирования файлов с одной папки в другую. Sub CopyReports() Dim aPath(), aErr() ...

Ошибка run time error
Здравствуйте. Помогите пожалуйста, при запуске макроса выдает ошибку &quot;Run-time error '-2147467259 (80004005)': Automation error ...

Ошибка run time error 9
Помогите начинающему ,делаю курсовую,при выполнении выходит ошибка run time error 9 vba вот код макроса Sub prodaga_igr() Dim cena(5,...

Ошибка: Run-time error '5'
Доброго времени суток! Совсем недавно занялась изучением VBA и столкнулась с проблемой. Имеется программа: Function krug(x As Double)...

Ошибка run-time error 1004
Sub pract() korp = Val(InputBox(&quot;Введите номер столбца, где находятся адреса: &quot;, &quot;Столбец&quot;, 5)) Columns(korp + 1).Select ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
Запись в регистр сведений независимо от заполненности табличной части
Maks 25.08.2026
Реализация из решения ниже выполнена на нетиповом документе с несколькими табличными частями, разработанного в КА2. Задача: Обеспечить запись документа в регистр сведений независимо от. . .
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru