Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/91: Рейтинг темы: голосов - 91, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
1

Поиск и пометка повторяющихся значений

20.09.2006, 21:36. Показов 17070. Ответов 31
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго дня, Господа !
Помогите мне, пожалуйста, определится с правильным подходом для реализации следующей задачи:
Есть столбец с данными в ячейках, например:
Столбец 1 Столбец 2
Иванов
Петров
Сидоров
Дармостук
Петров
Иванов
Необходимо при запуске макроса в столбце правее проставить метку напротив тех значений, которые повторяются, т. е.:
Столбец 1 Столбец 2
Иванов
Петров
Сидоров
Дармостук
Петров 1
Иванов 1
Другими словами, как только значение встречается второй раз, напротив него ставится метка.
Предвидя некоторые варианты ответов, скажу, что сортировка а потом применение формулы типа "=if(A1=A2,1,"")", как и применение сводной таблицы или других непрограммных методов, не подходит. Это необходимо реализовать программно.
Так вот, принимая во внимание все вышесказанное, я думаю реализовать это следующим способом:
1. Выделяю необходимую область
2. Создаю динамический массив
3. В цикле перебираю каждую ячейку, сравнивая ее содержимое со значениями в массиве. Если содержимое ячейки уже есть в массиве, то ставится метка, если нет, то заносится в массив.
Буду рад выслушать Ваши мысли, советы и комментарии по этому поводу
Александр
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.09.2006, 21:36
Ответы с готовыми решениями:

Сравнение повторяющихся значений
Добрый день, помогите решить задачу. Есть таблица с двумя столбцами, в перовом id, во втором...

Удаление повторяющихся значений из комбобокса
Добрый день. Как в VBA удалить из комбобокса данные которые повторяются, оставив только по одному...

Подсчет повторяющихся значений в ячейке
Всем здрасьте. Помогите, пожалуйста, реализовать макрос последовательного (с конца) подсчета нолей...

Изменение значений у повторяющихся элементов
Доброй ночи. Начну с того, что в VBA и программировании в целом я неофит, так что, пожалуйста, не...

31
1 / 1 / 0
Регистрация: 19.07.2011
Сообщений: 285
20.09.2006, 22:43 2
Я помогу Вам, но прежде хотел узнатьзачем это Вам т.е. цель просто интересно. Завтра я Вам отправлю файлик на форум
0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
20.09.2006, 23:03  [ТС] 3
Ser Artur,
Да я и сам написать могу, хотя и файлик посмотреть будет интересно
Я просто спрашивал про концепцию. Правильный ли я подход выбрал и нет ли у этого подхода подводных камней...
А нужно это для целей аудита, так как я аудитор. Ну вот, представте, что есть база основных средств строк так на 55,000 и у каждого ОС есть ID (хотя обычно ID нет). Так вот, на практике в 95% случаев:
1. Или среди ID есть повторяющиеся значения
2. Или этот самый ID необходимо создавать самому (поскольку его нет), объединяя несколько параметров, примером "Название&Сумма&Дата_Введения_в_эксплуатацию" и т. д.
Так вот, для дальнейших <STRONG>корректных</STRONG> манипуляций необходимо отловить одинаковые значения.
Надеюсь, мой ответ удовлетворил Ваше любопытство
0
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
21.09.2006, 01:42 4
мне кажется такой подход имел бы смысл в случае когда заранее количество дублирующихся элементов больше чем количество уникальных...



а в Вашем случае с каждым ходом массив все больше и больше увиличивается а соответственно и скорость выполнения операции постепенно падает - если учесть что количество строк может доходить до 55 тысяч - получается очень мрачная ситуация даже на сильной машине уже после первых 5 тысяч строк - и дальше - хуже



если бы такая задача стояла передо мной я бы:

1. создал столбец идентификационных номеров ->

2. перевел бы их в текстовый формат ->

3. используя автофильтр отсортировал бы весь масив по этому полю ->

4. далее, например, в колонке справа от автофильтра вписал бы формулу "=b2=b1" и скопировал бы до конца массива (для упращения дальнейшей обработки можно использовать более сложную конструкцию - например "=ЕСЛИ(I2=I1;"ахтунг";"")"->

5. полученый столбец скопирывал бы и вставил как значения - чтобы не напрягать систему ненужным пересчетом при фильтрации..



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






0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
21.09.2006, 14:55  [ТС] 5
To игорий,
В своем первом посте я уже говорил, что действия, использующие автофильтр, сортировку, формулы типа "=ЕСЛИ(I2=I1;"ахтунг";"")" и тому подобное, в принципе неприемлемы. И тому есть несколько причин, на которых я не буду останавливаться.
Самая главная из них - массив данных необходимо обрабатывать "как есть". Никаких сортировок, изменения порядка строк в массиве и т. д. И это условие необходимо жестко выполнять. Вот такая вот заморочка.
Жду любых комментариев, предложений, одобрений и неодобрений
С уважением,
Александр
0
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
21.09.2006, 15:32 6
<FONT color=#0072c2>дико извиняюсь... совершенно не заметил про то что основной док трогать нельзя...
<FONT color=#0072c2>но тем не менее - если нам нельзя сортировать средствами экселя то что имеем, то я бы предложил 2 пути:
<FONT color=#0072c2>1. добавляем к исходному массиву столбец в котором указываем порядковый номер или номер строки в которой он находится - далее выполняем описанный вами же способ на основе логических формул - далее возвращаем массив к исходному виду используя созданное нами поле с порядковым номером
<FONT color=#0072c2>2. копируем столбец уникальных идентификационных номеров в отдельную книгу или лист, совершаем с ним теже спамые манипуляции и возвращаем количество используя =впр()
такой вариант подойдет?

( имхо - ну не оч преспособлен VBA для обработки больших массивов)
0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
21.09.2006, 16:35  [ТС] 7
To игорий,
К сожалению, первый способ не подходит, поскольку не выполняется условие "как есть". Ну, представте себе массив, размерами 55,000 х 100 (при чем 50 столбцов - это формулы). Тут сортировку запускаешь, и можно идти домой.
Второй тоже не подходит, поскольку после данных манипуляций у меня будут выделены все записи которые повторяются. Посмотрите на мой пример в первом посте. Единичка стоит напротив второй записи, которая повторилась. Другими словами, после функции =впр() эта же единичка будет стоять и напротив первых записей:
Столбец 1 Столбец 2
Иванов 1
Петров 1
Сидоров
Дармостук
Петров 1
Иванов 1
что тоже неприемлемо. Это что же, если вариантов повторяющихся значений 4,000 - 5,000 мне вручную удалять признак (единицу) в первых строках? Это работы дня на три

С уважением,
Александр
0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
21.09.2006, 16:37  [ТС] 8
Вообще-то я создал этот топик для того, чтобы узнать другие способы решения этой задачи на ВБА от наших Гуру, не прибегая к циклам и массивам (если это, конечно, возможно). И я прекрасно осознаю всю тяжесть использования этих инструментов при обработке таких массивов данных. После запуска такого макроса можно спокойно идти на обед. Но поверьте, использование альтернативных методов, при условии обработки "как есть", не менее трудоемки.
С уважением,
Александр
0
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
21.09.2006, 17:38 9
не хочу вдаваться в полемику... но все же скажу что пометить начиная со второго значения - очень легко...
з.ы. а если нет желания слушать мысли простых смертных - надо было так прямо и написать в первом топике
0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
21.09.2006, 18:26  [ТС] 10
игорий,
Вот только без обид Твои мысли я с удовольствием выслушиваю.
Насчет твоего последнего поста:
не хочу вдаваться в полемику... но все же скажу что пометить начиная со второго значения - очень легко...
С этого места поподробнее

С уважением,
Александр
0
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
21.09.2006, 19:02 11
я думаю - это будет максимально подробно (см. аттач)
жду комментариев
0
5 / 5 / 3
Регистрация: 17.10.2007
Сообщений: 1,119
21.09.2006, 19:03 12
Emer,
Поищите в этом форуме мои примеры с Find и FindNext. И совсем альтернативный вариант: через DAO или ADO. Экспортируй данные в ACCESS и через свой UPDATE/SELECT одним запросом получай, что надо, а затем - назад импортируй. Для скорости - назначь индекс в таблице на поле, где ищутся дупликаты.
VladConn
0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
21.09.2006, 19:27  [ТС] 13
To игорий,
Совершенно согласен. Это вариант. Я как-то выпустил из вида, что формула типа "=IF(K3=K2,1,"")" ставит метку во второй продублированной позиции. Спасибо.
То VladConn,
Спасибо. Сейчас гляну.
0
0 / 0 / 0
Регистрация: 25.05.2011
Сообщений: 27
21.09.2006, 22:24  [ТС] 14
То игорий,
Вот вариант макроса, который выполняет поставленную задачу. 2,000 строк проверяет за секунды. Единственная проблема состоит в том, что необходимо захватывать при выделении сверху на 1 ячейку больше. С этим я попозже разбирусь. Твой вариант тоже взят на вооружение . Извини, если что не так сказал.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Sub SelectDoubledData()
Dim q As Integer
Dim z As Integer
Dim c As Range
Dim r As Range
    With Selection
        For Each c In Selection
         If Len(c.Value) > 0 Then
          q = 0
          Set c = .Find(c.Value, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=True)
                Do
                    If c.Row > q Then q = c.Row
                    Set c = .FindNext(c)
                    z = c.Row
                    If z > q Then Cells(c.Row, c.Column + 1).Value = 1
                Loop While c.Row > q
          End If
        Next c
    End With
End Sub
Так же спасибо VladConn за подсказку, на что обратить внимание
С уважением,
Александр
0
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
22.09.2006, 00:59 15
на то они и гуру
с 200 тыс строк действительно справляется сравнительно быстро - но вот при количестве строк близком к заявленным 55,000... в общем у меня не хватило терпения дождаться
0
rank1
22.09.2006, 02:33 16
Это же классическая задача из учебника по Perl - для этого лучше всего использовать Scripting.dictionary
rank1
22.09.2006, 02:44 17
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Sub getTheSame()
 On Error GoTo errh:
 Dim h As New Scripting.dictionary
 Dim rg As Range
 Set rg = Columns(2).Cells.SpecialCells(xlCellTypeConstants)
 For Each c In rg.Cells
  DoEvents
  h(c.Value) = h(c.Value) + 1
  If h(c.Value) > 1 Then
   c.Offset(0, 1).Value = "Exists"
  End If
 Next c
 Set h = Nothing
 
 If 0 Then
errh:
  Set h = Nothing
  MsgBox Err.Description
 End If
End Sub
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
22.09.2006, 12:09 18
супер! а можно код с коментариями... а то отлично работает но я не очень понимаю как...
0
rank1
22.09.2006, 16:59 19
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
Sub getTheSame()
    On Error GoTo errh: 'Устанавливаем хендлер ошибок
    Dim h As New Scripting.dictionary 'Создаем хеш - множество пар "ключ" -> значение
    Dim rg As Range 
    Set rg = Columns(2).Cells.SpecialCells(xlCellTypeConstants) 'Берем только константы из колонки 2
    For Each c In rg.Cells 'Перебираем все ячейки из множества 
        DoEvents 'Даем Экселю возможность отрисоваться
        ActiveWindow.Caption = c.Address 'Можно еще адрес ячейки показывать - чтоб был виден прогресс
        h(c.Value) = h(c.Value) + 1 ' Если ключ не существовал, хеш его автоматически добавит, иначе увеличит к-во повторений ключа
        If h(c.Value) > 1 Then 'Если ключ встречался более 1 раза
            c.Offset(0, 1).Value = "Exists" 'Ставим в соседней ячейке Exists
        End If
    Next c
    Set h = Nothing 'Освобождаем память из под хеша
    MsgBox "Done", vbInformation' Ну и для наглядности плакат об окончании
    '=============================
    If 0 Then 'Сюда попадем только в случае ошибки
errh:       'В обычных условиях if 0 никогда не сработает
        Set h = Nothing 'Если возникла ошибка - освобождаем память из под хеша
        MsgBox Err.Description 'Выводим сообщение об ошибке
    End If
    '==============================
End Sub
2 / 2 / 0
Регистрация: 16.04.2012
Сообщений: 24
22.09.2006, 17:09 20
спасибо огромное
0
22.09.2006, 17:09
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.09.2006, 17:09
Помогаю со студенческими работами здесь

Выбор повторяющихся значений из массива
&lt;TABLE style=&quot;WIDTH: 121pt; BORDER-COLLAPSE: collapse&quot; cellSpacing=0 cellPadding=0 width=161...

Удаление повторяющихся (дубликаты) значений. VBA
Добрый день Уважаемые форумчане, Хочу спросить у вас помощи, возможно ли каким-либо образом...

Некорректное суммирование повторяющихся значений. (scripting.dictionary)
Привет друзья! Много интересного и нужного почерпнул с Вашего форума, и видимо пришло время задать...

Объединить таблицы в exel для повторяющихся значений
Добрый день. Нужна помощь. Есть файл exel, где в столбце повторяются значения. Под этим значением...


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

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