Как сцепить несколько значений в одну ячейку по критерию? СцепитьЕсли
Все чаще вижу на разных форумах вопросы типа:
Получить такую:
Стандартными функциями это сделать весьма проблематично, т.к. заранее неизвестно сколько будет этих оценок и фамилий.. MIcrosoft работает над усовершенствованием Excel и теперь стало возможным сделать это и стандартными функциями. Правда, с небольшими ограничениями: сделать это могут только пользователи
Аргументы функции:
("; ") - символ(или несколько символов), которым необходимо объединять найденные значения( - диапазон, в котором искать критерийA2:A20 )( - критерий. Значение, на основании которого необходимо сцеплять значения. Значение просматривается в диапазоне значений(A2 ) )A2:A20 ( - из этого диапазона берется значение для сцепления, если значение напротив в диапазонe(B2:B20 ) ) совпадает с искомым значениемA2:A20 A2
Для любителей "старой школы" можно вместо функции
Аргументы точно такие же, как в формуле выше. Правда эта формула вводится в ячейку как формула массива(т.е. одновременным нажатием трех клавиш
А для пользователей Excel 2016 и ниже я написал небольшую функцию пользователя на VBA, которая решает данную проблему. Так же подобную функцию называют "многоразовый ВПР", потому что она по критерию возвращает ВСЕ значения для этого критерия, а не только первое.
'--------------------------------------------------------------------------------------- ' Author : The_Prist(Щербаков Дмитрий) ' Профессиональная разработка приложений для MS Office любой сложности ' Проведение тренингов по MS Excel ' http://www.excel-vba.ru ' Purpose: '--------------------------------------------------------------------------------------- Function СцепитьЕсли(ByRef Диапазон As Range, ByVal Критерий As String, ByRef Диапазон_сцепления As Range, Optional Разделитель As String = " ", Optional БезПовторов As Boolean = False) As String Dim li As Long, sStr As String, avItem, avDateArr(), avRezArr(), lUBnd As Long If Диапазон.Count > 1 Then avDateArr = Intersect(Диапазон, Диапазон.Parent.UsedRange).Value avRezArr = Intersect(Диапазон_сцепления, Диапазон_сцепления.Parent.UsedRange).Value If Диапазон.Rows.Count = 1 Then avDateArr = Application.Transpose(avDateArr) avRezArr = Application.Transpose(avRezArr) End If Else ReDim avDateArr(1, 1): ReDim avRezArr(1, 1) avDateArr(1, 1) = Диапазон.Value avRezArr(1, 1) = Диапазон_сцепления.Value End If lUBnd = UBound(avDateArr, 1) 'Определяем вхождение операторов сравнения в Критерий Dim objRegExp As Object, objMatches As Object Set objRegExp = CreateObject("VBScript.RegExp") objRegExp.Global = False: objRegExp.Pattern = "=|<>|=>|>=|<=|=<|>|<" Set objMatches = objRegExp.Execute(Критерий) 'Если есть вхождения If objMatches.Count > 0 Then Dim sStrMatch As String sStrMatch = objMatches.Item(0) Критерий = Replace(Replace(Критерий, sStrMatch, "", 1, 1), Chr(34), "", 1, 2) If IsNumeric(Критерий) And Критерий <> "" Then Критерий = CDbl(Критерий) End If Select Case sStrMatch Case "=" For li = 1 To lUBnd If avDateArr(li, 1) = Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li Case "<>" For li = 1 To lUBnd If avDateArr(li, 1) <> Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li Case ">=", "=>" For li = 1 To lUBnd If avDateArr(li, 1) >= Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li Case "<=", "=<" For li = 1 To lUBnd If avDateArr(li, 1) <= Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li Case ">" For li = 1 To lUBnd If avDateArr(li, 1) > Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li Case "<" For li = 1 To lUBnd If avDateArr(li, 1) < Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li End Select Else 'Если нет вхождения For li = 1 To lUBnd If avDateArr(li, 1) Like Критерий Then If Trim(avRezArr(li, 1)) <> "" Then _ sStr = sStr & IIf(sStr <> "", Разделитель, "") & avRezArr(li, 1) End If Next li End If If БезПовторов Then Dim oDict As Object, sTmpStr Set oDict = CreateObject("Scripting.Dictionary") sTmpStr = Split(sStr, Разделитель) On Error Resume Next For li = LBound(sTmpStr) To UBound(sTmpStr) oDict.Add sTmpStr(li), sTmpStr(li) Next li sStr = "" sTmpStr = oDict.keys For li = LBound(sTmpStr) To UBound(sTmpStr) sStr = sStr & IIf(sStr <> "", Разделитель, "") & sTmpStr(li) Next li End If СцепитьЕсли = sStr End Function |
Чтобы правильно использовать приведенный код, необходимо сначала ознакомиться со статьей Что такое функция пользователя(UDF)?. Вкратце: скопировать текст кода выше, перейти в редактор VBA(
По принципу работы функция похожа на стандартную СУММЕСЛИ. Указывается диапазон значений(где просматривать значение), критерий и диапазон значений для сцепления. Символ для разделения слов указывать необязательно.
Диапазон
Критерий
Диапазон_сцепления
Разделитель
БезПовторов - если указать 1 или ИСТИНА, то в результате получится строка, в которой нет одинаковых значений. Если указать 0 или ЛОЖЬ, то будут выведены все значения. По умолчанию значение ЛОЖЬ.
Примечание: для работы функции должны быть разрешены макросы
Пример СцепитьЕсли.xls (68,0 KiB, 16 095 скачиваний)
Также см.:
ВПР_МН
Сцепить_МН
СцепитьЕсли
Что такое функция пользователя(UDF)?
ВПР с возвратом всех значений
Статья помогла? Поделись ссылкой с друзьями!

Поиск по меткам
Access apple watch Multex Power Query и Power BI VBA управление кодами Бесплатные надстройки Дата и время Записки ИП Надстройки Печать Политика Конфиденциальности Почта Программы Работа с приложениями Разработка приложений Росстат Тренинги и вебинары Финансовые Форматирование Функции Excel акции MulTEx ссылки статистикаКомментарии, не имеющие отношения к комментируемой статье, могут быть удалены без уведомления и объяснения причин. Если есть вопрос по личной проблеме - добро пожаловать на Форум
С П А С И Б О!!!
я уж думал сам запариться над макросом....но вот наткнулся на эту реализацию.
5+
а можно ли оставить только крайние числа, сделать так 1-6, вместо 1, 2, 3, 4, 5, 6?
С помощью конкретно этой функции - нет. А вообще - можно все. Дописываете код или пишите свой, который будет выполнять конкретно Вашу задачу.
КАК ВАС БЛАГОДАРИТЬ?
АПЛОДИРУЕМ СТОЯ!!!!!!!!!!
Огромное спасибо за формулу!
А может подскажите, как правильно написать код, чтобы было 2 диапазона условия?
т.е. диапазон1; Критерий1; диапазон2; Критерий2;
как в СуммЕслиМН. оеально это сделать? спасибо!
Надежда, только правкой кода.
Автор, реальный тебе РЕСПЕКТ!!!!!
Бью поклоны за избавление от ручного сцепления 3,5 тысяч значений!
СПАСИБО!!!!!!!
Отличная функция, но работает если данные на одном листе. Не получилось ни с разных файлов сравнивать (тупо вылетает Excel по ошибке), ни с разных листов....
Макс, а функция и не сравнивает. Она берет данные для просмотри и сцепления с одного листа. Критерии при этом могут быть откуда угодно. Что у Вас там вылетает не знаю.
Если ячеек более 37000 то функция не срабатывает, это факт. Причем если критерии находятся в другом файле, то Excel вываливается по ошибке. Вместо того что придираться к словам обратили бы внимание на свои ошибки. Удачи Вам.
Макс, как скажете. Не буду придираться. Но сравнивать и сцеплять понятия разные - кто знает как Вы поняли функцию и для чего применить пытаетесь. Может Вы хотите навязать ей то, чего она не умеет. Поэтому я уточнил, но нисколько не придирался. Не надо по себе людей судить.
И вот другой факт: у меня функция РАБОТАЕТ. И не только у меня, судя по комментариям. Без Вашего примера сказать почему не работает у Вас нереально. Может у Вас книги в разных процессах открыты. А может еще что.
Плюс, если у Вас так много значений - есть вероятность, что результирующая строка содержит больше символов, чем допускается для записи в ячейку. И функция просто завершается с ошибкой, т.к. не может занести данные. Ничего с этим не сделать, т.к. это ограничения самого Excel.
И еще момент: нехватка свободной памяти для обработки таких объемных данных. VBA просто не может поместить их в массивы.
P.S. Про "обратили бы внимание на свои ошибки". А Вам не кажется, что я ничем Вам не обязан, чтобы что-то для Вас лично исправлять? Функция не работает только у Вас. Причины я описал выше. Хотите с ними разобраться - выкладывайте файл со своими данными на файлообменник, а ссылку на него сюда. Не забудьте прописать там функцию. Я скачаю, посмотрю. И тогда будет видно, где и чья ошибка.