Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
1

Удаление дубликатов строк из диапазона, состоящего из 18-ти колонок

05.12.2020, 16:06. Показов 2520. Ответов 16

Author24 — интернет-сервис помощи студентам
Доброго времени суток всем!
Имеется книга Excel с одним листом
На данном листе находится таблица, состоящая из 18-ти колонок и нескольких тысяч строк (в файле оставлю только малую часть, чтобы показать, о чем я говорю).
В файле имеется огромное множество дубликатов, нужно их удалить.
Имеется два варианта, оба из которых не работают. Задумка такая:
1-й вариант: перебираю в цикле i каждый из столбцов по очереди двигаясь вниз, пока не дойду до конца строчек и в итоге удаляю. Скажу сразу, что этот вариант построен на немного измененном моем коде, поэтому, хотя и я прочитал про UBound - я всё равно не ощущаю себя уверенно в этом коде. Тут используется два цикла, потому что я подумал, что так будет правильней сравнивать строку i и строку i+1.
2-й вариант: Решил сделать два цикла - i и Z, и чтоб они шли параллельно друг другу, также перебирали каждый столбец, но уже не i и i+1 (это мне кажется плохая задумка, потому что тут он вроде как перебирает только две соседние строки).
Я думаю как-нибудь зациклить эти 18 условий для каждого столбца, чтоб был цикл и переменная от 2 до 19 (для каждого столбца) или вообще переделать их в сравнение не ячеек Cells, а в сравнение строчек Rows.
1-й вариант:
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
Sub MMM()
'ZZZ = Timer
Application.ScreenUpdating = False
LR = Cells(Rows.Count, 2).End(xlUp).Row
 
Set RNG1 = Range(Cells(1, 2), Cells(LR, 19))
ARR1 = RNG1.Value
 
For i = 2 To LR
   For j = i + 1 To LR
        If ARR1(i, 2) = ARR1(j, 2) Then
                 If ARR1(i, 3) = ARR1(j, 3) Then
                    If ARR1(i, 4) = ARR1(j, 4) Then
                        If ARR1(i, 5) = ARR1(j, 5) Then
                            If ARR1(i, 6) = ARR1(j, 6) Then
                                If ARR1(i, 7) = ARR1(j, 7) Then
                                    If ARR1(i, 8) = ARR1(j, 8) Then
                                        If ARR1(i, 9) = ARR1(j, 9) Then
                                            If ARR1(i, 10) = ARR1(j, 10) Then
                                                If ARR1(i, 11) = ARR1(j, 11) Then
                                                    If ARR1(i, 12) = ARR1(j, 12) Then
                                                        If ARR1(i, 13) = ARR1(j, 13) Then
                                                            If ARR1(i, 14) = ARR1(j, 14) Then
                                                                If ARR1(i, 15) = ARR1(j, 15) Then
                                                                    If ARR1(i, 16) = ARR1(j, 16) Then
                                                                        If ARR1(i, 17) = ARR1(j, 17) Then
                                                                            If ARR1(i, 18) = ARR1(j, 18) Then
                                                                                If ARR1(i, 19) = ARR1(j, 19) Then
    For X = 2 To UBound(ARR1, 2)
    If ARR1(1, X) = ARR1(j, 2) Then ARR1(i, X).Delete
    Next X
    End If
                                                                                End If
                                                                            End If
                                                                        End If
                                                                    End If
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
Next j
Next i
RNG1.Value = ARR1
'MsgBox "Complete   " & Chr(13) & CStr(Timer - ZZZ) & "sec"
End Sub
2-й вариант:
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
 Public Sub Inp()
Sub zzz()
LR = Cells(Rows.Count, 2).End(xlUp).Row
'MsgBox (LR)
For i = 2 To LR 
    For Z = 2 To LR
        If InStr(1, Cells(i, 2), Cells(Z, 2), 1) > 0 Then 
            If InStr(1, Cells(i, 3), Cells(Z, 3), 1) > 0 Then 
                If InStr(1, Cells(i, 4), Cells(Z, 4), 1) > 0 Then
                    If InStr(1, Cells(i, 5), Cells(Z, 5), 1) > 0 Then
                        If InStr(1, Cells(i, 6), Cells(Z, 6), 1) > 0 Then
                            If InStr(1, Cells(i, 7), Cells(Z, 7), 1) > 0 Then
                                If InStr(1, Cells(i, 8), Cells(Z, 8), 1) > 0 Then
                                    If InStr(1, Cells(i, 9), Cells(Z, 9), 1) > 0 Then
                                        If InStr(1, Cells(i, 10), Cells(Z, 10), 1) > 0 Then
                                            If InStr(1, Cells(i, 11), Cells(Z, 11), 1) > 0 Then
                                                If InStr(1, Cells(i, 12), Cells(Z, 12), 1) > 0 Then
                                                    If InStr(1, Cells(i, 13), Cells(Z, 13), 1) > 0 Then
                                                        If InStr(1, Cells(i, 14), Cells(Z, 14), 1) > 0 Then
                                                            If InStr(1, Cells(i, 15), Cells(Z, 15), 1) > 0 Then
                                                                If InStr(1, Cells(i, 16), Cells(Z, 16), 1) > 0 Then
                                                                    If InStr(1, Cells(i, 17), Cells(Z, 17), 1) > 0 Then
                                                                        If InStr(1, Cells(i, 18), Cells(Z, 18), 1) > 0 Then
                                                                            If InStr(1, Cells(i, 19), Cells(Z, 19), 1) > 0 Then
                                                                            Rows(i).Delete
                                                                            End If
                                                                        End If
                                                                    End If
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    Next
Next
End Sub
Вложения
Тип файла: zip Книга1.xlsm.zip (24.0 Кб, 9 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.12.2020, 16:06
Ответы с готовыми решениями:

Удаление дубликатов по всем колонкам и по каждой отдельно с возможностью выбора диапазона
Доброго времени суток. Помогите плз написать макрос с возможностью удаления дубликатов по всем...

Удаление дубликатов строк
Ребята, подскажите алгоритм - удаление дубликатов строк через: AssignFile Reset Rewrite writeln...

Удаление дубликатов строк
Доброго всем времени суток! Есть таблица, в которой присутствуют дубликаты строк; пОля, вроде id, в...

Разные варианты описания диапазона колонок и строк в Excel?
У меня был прекрасно работающий макрос, в котором диапазоны строк и колонок записывались через...

16
2724 / 1701 / 776
Регистрация: 23.03.2015
Сообщений: 5,388
05.12.2020, 16:20 2
serviktor,
Напишите конкретное задание.

Добавлено через 25 секунд
Что вы хотите?
0
ᴁ®
Эксперт MS Access
3648 / 2004 / 427
Регистрация: 13.12.2016
Сообщений: 6,899
Записей в блоге: 5
05.12.2020, 17:02 3
serviktor, а для 19-ти колонок не потребуется?
0
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
05.12.2020, 18:55  [ТС] 4
Цитата Сообщение от Narimanych Посмотреть сообщение
Напишите конкретное задание
Удалить дубликаты, если имеется некоторое количество одинаковых строк (с диапазоном со второго по 19-й столбец, то оставить только одну такую строку, а ее копии удалить, и так со всеми строчками.
0
3218 / 967 / 223
Регистрация: 29.05.2010
Сообщений: 2,086
05.12.2020, 18:59 5
Как вариант на словарях:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Sub CopyUnicumNColumns()
    Dim t$, i&, k&
    a = ActiveSheet.UsedRange
    k = UBound(a)
    With CreateObject("Scripting.Dictionary")
        For i = 1 To k
            b = Application.Index(a, i, , 1)
            t = Join(b, "|")
            If Not .exists(t) Then .Item(t) = b
        Next
        Erase a
        Sheets.Add
        i = 1
        For Each x In .keys
            Cells(i, 1).Resize(1, k) = .Item(x)
            i = i + 1
        Next
    End With
End Sub
1
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
05.12.2020, 19:11  [ТС] 6
Цитата Сообщение от АЕ Посмотреть сообщение
а для 19-ти колонок не потребуется?
Не потребуется, есть у меня одна идея, но не знаю как реализовать. В строке 1 находится шапка, то есть именно по ней можно определить то, сколько столбцов заполнено. Думаю, можно использовать метод наподобие Cells(Rows.Count, 2).End(xlUp).Row, только чтоб не количество заполненных строк считал, а количество столбцов, и занести это в переменную. Но этот вариант не обязательно реализовывать, да и у меня не получается его реализовать, это просто как идея, поэтому можно явно указать 18 колонок.

Добавлено через 4 минуты
Цитата Сообщение от toiai Посмотреть сообщение
Как вариант на словарях:
Выдает ошибку на строчке
Visual Basic
1
 With CreateObject("Scripting.Dictionary")
Пишет: ActiveX component can't create object
0
3218 / 967 / 223
Регистрация: 29.05.2010
Сообщений: 2,086
05.12.2020, 19:18 7
Вот файл
Вложения
Тип файла: rar копирование уникальных по n-колонок.rar (16.7 Кб, 8 просмотров)
1
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
05.12.2020, 19:22  [ТС] 8
Цитата Сообщение от toiai Посмотреть сообщение
Вот файл
Такая же ошибка
0
3218 / 967 / 223
Регистрация: 29.05.2010
Сообщений: 2,086
05.12.2020, 19:23 9
Какой офис?
0
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
05.12.2020, 19:24  [ТС] 10
Цитата Сообщение от toiai Посмотреть сообщение
Какой офис?
2019, а разве это может влиять?
0
3218 / 967 / 223
Регистрация: 29.05.2010
Сообщений: 2,086
05.12.2020, 19:39 11
У меня 2010 и все работает, посмотри References:
Миниатюры
Удаление дубликатов строк из диапазона, состоящего из 18-ти колонок  
1
2724 / 1701 / 776
Регистрация: 23.03.2015
Сообщений: 5,388
05.12.2020, 19:39 12
Лучший ответ Сообщение было отмечено serviktor как решение

Решение

serviktor,
Еще вариант ( в принципе такой же как и наверху , только в массивах)...
отработка на 100000 строк меньше 2 секунд
Кликните здесь для просмотра всего текста

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
Sub MMM()
T1 = Timer
LR = Range("B:S").Find("*", , xlValues, xlWhole, , xlPrevious).Row
Set RNG1 = Range(Cells(1, 2), Cells(LR, 19))
ARR1 = RNG1.Value
ReDim ARR2(1 To UBound(ARR1))
 
    For i = 1 To UBound(ARR1)
         s = ""
            For j = 1 To UBound(ARR1, 2)
              s = s & ARR1(i, j) & ";"
            Next
         ARR2(i) = Mid(s, 1, Len(s) - 1)
    Next
    With CreateObject("Scripting.Dictionary")
            For i = 1 To UBound(ARR2)
              LL = .Item(ARR2(i))
            Next
     ReDim ARR3(1 To .Count, 1 To 18)
            For i = 1 To .Count
                   ARR4 = Split(.Keys()(i - 1), ";")
                    For j = 1 To 18
                      ARR3(i, j) = ARR4(j - 1)
                    Next
            Next
    End With
Sheets.Add After:=Worksheets(Worksheets.Count)
Cells(2, 1).Resize(UBound(ARR3), 18).Value = ARR3
 
MsgBox "Job Complete   " & Chr(13) _
& "Time spent : " & CStr(Timer - T1) & "  sec" & Chr(13) _
& LR - 1 & "  lines in total" & Chr(13) _
& UBound(ARR3) - 1 & " Original lines found"
End Sub


Файл приложен,нажатие кнопки МММ
Миниатюры
Удаление дубликатов строк из диапазона, состоящего из 18-ти колонок  
Вложения
Тип файла: rar NB.rar (2.61 Мб, 15 просмотров)
1
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
05.12.2020, 19:48  [ТС] 13
Цитата Сообщение от toiai Посмотреть сообщение
посмотри References
Отличается только тем, что у меня не 15.0, а 16.0, а так всё аналогично, галочки стоят
0
Часто онлайн
864 / 579 / 263
Регистрация: 09.01.2017
Сообщений: 1,951
05.12.2020, 19:50 14
Цитата Сообщение от serviktor Посмотреть сообщение
Выдает ошибку на строчке
Visual BasicВыделить код
1
 With CreateObject("Scripting.Dictionary")

У ТС Мак и думаю дело в этом
0
3218 / 967 / 223
Регистрация: 29.05.2010
Сообщений: 2,086
05.12.2020, 19:51 15
Лучший ответ Сообщение было отмечено serviktor как решение

Решение

Проверил в 2013 -работает.
Подправил ошибку по количеству стообцов
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Sub CopyUnicumNColumns()
    Dim t$, i&, k&
    a = ActiveSheet.UsedRange
    k = UBound(a, 2)
    With CreateObject("Scripting.Dictionary")
        For i = 1 To UBound(a)
            b = Application.Index(a, i, , 1)
            t = Join(b, "|")
            If Not .exists(t) Then .Item(t) = b
        Next
        Erase a
        Sheets.Add
        i = 1
        For Each x In .keys
            Cells(i, 1).Resize(1, k) = .Item(x)
            i = i + 1
        Next
    End With
End Sub
1
5 / 4 / 1
Регистрация: 03.04.2018
Сообщений: 113
05.12.2020, 20:16  [ТС] 16
toiai, Narimanych, большое спасибо за помощь, возможно ошибка была из-за версии офиса, или из-за Mac оси, на винде офис всё удачно выполнил. Теперь знаю, в каком направлении двигаться и что подтянуть, чтобы решать подобные задачи)
0
2724 / 1701 / 776
Регистрация: 23.03.2015
Сообщений: 5,388
05.12.2020, 20:17 17
serviktor,
Велкоме
0
05.12.2020, 20:17
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.12.2020, 20:17
Помогаю со студенческими работами здесь

Удаление дубликатов строк из таблицы
Собственно существует ли какая нибудь команда или универсальный запрос, который подойдет к любой...

Удаление строк - полных дубликатов
Приветствую. Есть такая табличка product_id category_id position 1 1 ...

Word Удаление смежных дубликатов строк
Добрый день! Помогите с кодом, плиз! В Word есть табличка в 1 столбец. Нужно удалить дубликаты...

Удаление строк и колонок из матрицы
Добрый день, помогите пожалуйста решить эту задачу. Дан двумерный массив. Удалить из него: а)...

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

Удаление дубликатов + ассинхронное удаление из другой таблицы
Есть две таблицы tbl_content : id, title tbl_pics : id, picname 1. Нужно удалить дубликаты...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru