Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.05.2015, 16:34   #1
Denis Ch
Пользователь
 
Регистрация: 07.02.2011
Сообщений: 15
По умолчанию Создание пользовательских функций для удаления дубликатов и сортировки полученных значений в ячейке

Здравствуйте уважаемые форумчане.
Прошу оказать помощь в написании пользовательской(-их) функции(-й) которые бы удаляли дублирующиеся значения в ячейке, а затем отсортировывали их в порядке возрастания(или убывания). Решения по сортировке и удалению дубликатов для диапазонов нашёл, а для ячейки нет.
Два дня с файлом мучаюсь, для удаления дубликатов в массиве значений использовал таблицы google и функцию UNIQUE, а сортировку приходилось делать в ручном режиме. Для написания подобных пользовательских функций опыта не хватает, помогите пожалуйста.
Удаление дубликатов нужно сделать для ячеек в столбце X в прикреплённом примере это ячейки X2 и X5).
Версия excel 2013, пример сохранён именно в ней. Сохранить в .xls, не получается так как у меня там очень большие формулы и большое количество символов в ячейке, которое не поддерживается excel 2003.
Вложения
Тип файла: zip Таблица актов.zip (15.8 Кб, 8 просмотров)
Denis Ch вне форума Ответить с цитированием
Старый 27.05.2015, 17:30   #2
IgorGO
Новичок
СтарожилДжуниор
 
Аватар для IgorGO
 
Регистрация: 05.02.2008
Сообщений: 9,487
По умолчанию

при активном листе выполните этот
Код:
Sub DelSort()
  Dim a, n As Long
  a = Split(Cells(2, 24), ";"):  n = UBound(a) + 1
  Cells(1, 9999).Resize(n) = WorksheetFunction.Transpose(a)
  Cells(1, 9999).Resize(n).RemoveDuplicates Columns:=1, Header:=xlNo
  n = WorksheetFunction.Count(Columns(9999))
  Application.ScreenUpdating = False
  With ActiveSheet.Sort
    .SortFields.Clear
    .SortFields.Add Key:=Cells(1, 9999).Resize(n, 1), SortOn:=xlSortOnValues, _
                    Order:=xlAscending, DataOption:=xlSortNormal
    .SetRange Cells(1, 9999).Resize(n, 1): .Header = xlGuess: .MatchCase = False
    .Orientation = xlTopToBottom: .SortMethod = xlPinYin: .Apply
  End With
  Cells(2, 25) = Join(WorksheetFunction.Transpose(Cells(1, 9999).Resize(n, 1).Value), ";")
  Columns(9999).ClearContents:   Application.ScreenUpdating = True
End Sub
см. в Y2 собрано все лучшее из X2
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете
IgorGO вне форума Ответить с цитированием
Старый 27.05.2015, 17:45   #3
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Например так.
Немного коряво вышло, но работает!
Использовал наработку SAS888
Работает только с числами!
Можно конечно применять сразу в X2 и X5.

P.S.Похоже с названием накосячил - какое там uniqstrings, раз работает только с числами?...
Ну да ладно, исправьте на что хотите...
Вложения
Тип файла: zip Таблица актов H.zip (22.7 Кб, 7 просмотров)
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 27.05.2015 в 17:51.
Hugo121 вне форума Ответить с цитированием
Старый 27.05.2015, 17:58   #4
Denis Ch
Пользователь
 
Регистрация: 07.02.2011
Сообщений: 15
По умолчанию

Цитата:
Сообщение от IgorGO Посмотреть сообщение
при активном листе выполните этот
Код:
Sub DelSort()
  Dim a, n As Long
  a = Split(Cells(2, 24), ";"):  n = UBound(a) + 1
  Cells(1, 9999).Resize(n) = WorksheetFunction.Transpose(a)
  Cells(1, 9999).Resize(n).RemoveDuplicates Columns:=1, Header:=xlNo
  n = WorksheetFunction.Count(Columns(9999))
  Application.ScreenUpdating = False
  With ActiveSheet.Sort
    .SortFields.Clear
    .SortFields.Add Key:=Cells(1, 9999).Resize(n, 1), SortOn:=xlSortOnValues, _
                    Order:=xlAscending, DataOption:=xlSortNormal
    .SetRange Cells(1, 9999).Resize(n, 1): .Header = xlGuess: .MatchCase = False
    .Orientation = xlTopToBottom: .SortMethod = xlPinYin: .Apply
  End With
  Cells(2, 25) = Join(WorksheetFunction.Transpose(Cells(1, 9999).Resize(n, 1).Value), ";")
  Columns(9999).ClearContents:   Application.ScreenUpdating = True
End Sub
см. в Y2 собрано все лучшее из X2
IgorGO, большое спасибо.
Проверил код, для ячейки X2 сработал, отсортировал как надо и удалил лишнее. Чтобы в ячейке Х5 убрать лишнее нужно в коде адрес ячейки менять, я правильно понимаю? А можно сделать так, чтобы для выбранной ячейки выполнялся этот макрос или чтобы выводился запрос какую ячейку оптимизировать и куда вывести результат. Вывод результата в столбец Y вполне устраивает, но неудобно каждый раз в макрос изменения вносить. Вас не затруднит немного код подправить, чтобы удобнее было пользоваться?
Denis Ch вне форума Ответить с цитированием
Старый 27.05.2015, 18:12   #5
IgorGO
Новичок
СтарожилДжуниор
 
Аватар для IgorGO
 
Регистрация: 05.02.2008
Сообщений: 9,487
По умолчанию

в начале:
Код:
 a = Split(Selection, ";"):  n = UBound(a) + 1
в конце
Код:
Selection.Offset(0, 1) = Join(WorksheetFunction.Transpose(Cells(1, 9999).Resize(n, 1).Value), ";")
результат будет правее исходной ячейки
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете
IgorGO вне форума Ответить с цитированием
Старый 27.05.2015, 18:20   #6
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

А мой вариант может сразу в исходной, и динамически, и без кнопки...
И ничего на листе не затрёт...
Зря что ли писал?
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 27.05.2015, 18:26   #7
Denis Ch
Пользователь
 
Регистрация: 07.02.2011
Сообщений: 15
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
Например так.
Немного коряво вышло, но работает!
Использовал наработку SAS888
Работает только с числами!
Можно конечно применять сразу в X2 и X5.

P.S.Похоже с названием накосячил - какое там uniqstrings, раз работает только с числами?...
Ну да ладно, исправьте на что хотите...
Огромное вам спасибо Hugo121,
Формула работает. Плохо, что массивы констант типа {1;2;5;10;56;87;2}, не обрабатывает и работает только с числовыми значениями. Можно ли доработать функцию, чтоб она более универсальной и "всеядной" стала?
P.s. IgorGO, Hugo121 большое спасибо что так быстро откликнулись и помогли с решением задачи.Проверьте ваши "места сбора благодарностей" указанные в подписях

Последний раз редактировалось Denis Ch; 27.05.2015 в 18:32. Причина: Исправил ник Hugo121
Denis Ch вне форума Ответить с цитированием
Старый 27.05.2015, 18:34   #8
IgorGO
Новичок
СтарожилДжуниор
 
Аватар для IgorGO
 
Регистрация: 05.02.2008
Сообщений: 9,487
По умолчанию

спасибо!

зафиксирован факт пополнения кошелька.
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете
IgorGO вне форума Ответить с цитированием
Старый 27.05.2015, 19:01   #9
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Спасибо, пополнение прибыло.
Доработать можно, но в примере всегда предусмотрены числа - поэтому использовал решение для чисел.
Можно взять любой готовый код сортировки массива и использовать - будет для любых значений.
А вот про массив не понял - покажите пример в файле, подумаю.

P.S. Вот для чисел и строк. Ещё можно для дат доработать...
Код:
Option Explicit

Function uniqel(s$, razd$) As String
    Dim col As New Collection, el, i&, j&, k&
    Dim x&, y&

    If InStr(s, razd) Then
        On Error Resume Next
        For Each el In Split(s, razd)
            el = Trim(el)
            col.Add el, el
        Next
        On Error GoTo 0

        ReDim a(1 To col.Count)
        For Each el In col
            i = i + 1
            If IsNumeric(el) Then a(i) = --el Else a(i) = el
        Next

        SortArray a

        uniqel = Join(a, razd)
    End If
End Function

Private Sub SortArray(ByRef a As Variant)
    Dim i As Long, j As Long
    Dim t As Variant

    'standard bubble sort loops
    For i = LBound(a) To UBound(a) - 1
        For j = i + 1 To UBound(a)
            If a(i) > a(j) Then    'change to < for descending order
                t = a(i)
                a(i) = a(j)
                a(j) = t
            End If
        Next j
    Next i
End Sub
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 27.05.2015 в 19:11.
Hugo121 вне форума Ответить с цитированием
Старый 27.05.2015, 19:18   #10
Denis Ch
Пользователь
 
Регистрация: 07.02.2011
Сообщений: 15
По умолчанию

Hugo121,
когда я писал про массив то имел ввиду возможность использовать запись следующего вида =uniqel({1;2;5;6;8;9;2};";"), т.е. чтобы можно было использовать как ссылку на ячейку так и использовать массив констант. Я планировал использовать эту формулу в составе других формул, а там у меня иногда массивы констант проскакивают. Сейчас она ругается на запись в виде {1;2;5;6;8;9;2}, вместо ссылки на ячейку.
Denis Ch вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Составить схему алгоритма и программу для вычисления значений функций Y и F для заданных значений Иван Олегович Паскаль, Turbo Pascal, PascalABC.NET 11 04.12.2013 08:49
Создание пользовательских функций Riona Общие вопросы C/C++ 1 12.04.2012 11:13
Создание пользовательских функций для обработки числовой информации. Larisa7 Помощь студентам 1 16.12.2011 18:40
Словесный алгоритм нахождения в матрице для каждой строки числа элементов, кратных 5 и наибольшее из полученных значений (Паскаль) BloodyBlade Помощь студентам 0 05.12.2011 23:28
Создание пользовательских функций Lain. Помощь студентам 0 23.12.2010 23:23