Часто бывает ситуация, когда необходимо из трех разных столбцов сцепить данные в одну строку с разделителем. Допустим в А1 Фамилия, в В1 - Имя, в С1 - Отчество, а надо получить все вместе Фамилия Имя Отчество. Как обычно в Excel объединяют значения нескольких ячеек в одну? Правильно, при помощи функции СЦЕПИТЬ или при помощи амперсанда:
=
Это достаточно эффективно, если необходимо сцепить значения из трех-пяти ячеек. А если ячеек 50? Или того больше? Не очень удобно объединять их все описанными выше способами. А других встроенных функций в Excel для подобных операций не существует. С момента написания статьи Microsoft порадовал нас новыми функциями и теперь в составе функций есть функция
Так же этот аргумент удобен, если неизвестен заранее размер диапазона сцепления. Можно указать ячейки чуть с запасом(
Правда и здесь не все так радужно:
Поэтому я написал функцию пользователя, которая сцепляет данные из указанных ячеек в одну строку и использовать её можно в любой версии офиса. Чем отличается от стандартной функции СЦЕПИТЬ()? Тем, что в качестве ячеек для сцепки указывается не каждая из ячеек по очереди, а сразу весь диапазон с возможностью указания разделителя между значениями каждой ячейки. Так же, в функции сразу заложен алгоритм пропуска пустых ячеек и возможность сцеплять исключительно уникальные значения - т.е. в результате будут сцепляться только те ячейки, значения которых ранее еще не были добавлены в сцепку.
Option Explicit '--------------------------------------------------------------------------------------- ' Procedure : СцепитьМного ' http://www.excel-vba.ru ' Purpose : Функция сцепляет все указанные ячейки в одну с указанным разделителем. ' Аргументы функции: ' Диапазон — диапазон ячеек, значения которых необходимо объединить в строку. ' Разделитель — необязательный аргумент. ' Один или несколько символов, которые будут вставлены между каждым словом. ' По умолчанию пробел. ' БезПовторов — необязательный аргумент. ' Если указан как ИСТИНА или 1 — в результирующей строке будут значения без дубликатов. ' Для английской локализации данный параметр указывается как TRUE и FALSE соответственно. '--------------------------------------------------------------------------------------- Function СцепитьМного(Диапазон As Range, Optional Разделитель As String = " ", Optional БезПовторов As Boolean = False) Dim avData, lr As Long, lc As Long, sRes As String Dim oDict As Object, sTmpStr Set oDict = CreateObject("Scripting.Dictionary") oDict.comparemode = 1 avData = Диапазон.Value If Not IsArray(avData) Then СцепитьМного = avData Exit Function End If For lc = 1 To UBound(avData, 2) For lr = 1 To UBound(avData, 1) If Len(avData(lr, lc)) Then sRes = sRes & Разделитель & avData(lr, lc) If БезПовторов Then If Not oDict.exists(avData(lr, lc)) Then oDict.Add avData(lr, lc), 0& End If End If End If Next lr Next lc If Len(sRes) Then sRes = Mid(sRes, Len(Разделитель) + 1) End If If БезПовторов Then sRes = "" sTmpStr = oDict.keys For lr = LBound(sTmpStr) To UBound(sTmpStr) sRes = sRes & IIf(sRes <> "", Разделитель, "") & sTmpStr(lr) Next lr End If СцепитьМного = sRes End Function |
Чтобы правильно использовать приведенный код, необходимо сначала ознакомиться со статьей Что такое функция пользователя(UDF)?. Вкратце: скопировать текст кода выше, перейти в редактор VBA(
Синтаксис функции:
Диапазон - диапазон ячеек, значения которых необходимо объединить в строку.
Разделитель - необязательный аргумент. Один или несколько символов, которые будут вставлены между каждым словом. По умолчанию пробел.
БезПовторов - необязательный аргумент. Если указан как ИСТИНА или 1 - в результирующей строке будут значения без дубликатов. Например, из значений Сидоров, Петров, Сидоров, Иванов в результат попадут только Сидоров, Петров, Иванов. Если ЛОЖЬ или 0 - будут выведены все значения. Для английской локализации данный параметр указывается как TRUE и FALSE соответственно.
Скачать пример
СцепитьМного.xls (52,5 КиБ, 13 302 скачиваний)
Если необходимо объединять значения ячеек из "рваных"(несмежных) диапазонов(выделенных через Ctrl), то код нужно немного изменить:
Option Explicit '--------------------------------------------------------------------------------------- ' Procedure : СцепитьМного ' http://www.excel-vba.ru ' Purpose : Функция сцепляет все указанные ячейки в одну с указанным разделителем. Допускается указание несмежных диапазонов ' Аргументы функции: ' Диапазон — диапазон ячеек, значения которых необходимо объединить в строку. ' Разделитель — необязательный аргумент. ' Один или несколько символов, которые будут вставлены между каждым словом. ' По умолчанию пробел. ' БезПовторов — необязательный аргумент. ' Если указан как ИСТИНА или 1 — в результирующей строке будут значения без дубликатов. ' Для английской локализации данный параметр указывается как TRUE и FALSE соответственно. '--------------------------------------------------------------------------------------- Function СцепитьМного(диапазон As Range, Optional разделитель As String = " ", Optional БезПовторов As Boolean = False) Dim avData, lr As Long, lc As Long, sRes As String Dim ra As Range For Each ra In диапазон.Areas avData = ra.Value If Not IsArray(avData) Then ReDim avData(1 To 1, 1 To 1) avData(1, 1) = ra.Value End If For lc = 1 To UBound(avData, 2) For lr = 1 To UBound(avData, 1) If Len(avData(lr, lc)) Then sRes = sRes & разделитель & avData(lr, lc) End If Next lr Next lc Next If Len(sRes) Then sRes = Mid(sRes, Len(разделитель) + 1) End If If БезПовторов Then Dim oDict As Object, sTmpStr Set oDict = CreateObject("Scripting.Dictionary") sTmpStr = Split(sRes, разделитель) On Error Resume Next For lr = LBound(sTmpStr) To UBound(sTmpStr) oDict.Add sTmpStr(lr), sTmpStr(lr) Next lr sRes = "" sTmpStr = oDict.Keys For lr = LBound(sTmpStr) To UBound(sTmpStr) sRes = sRes & IIf(sRes <> "", разделитель, "") & sTmpStr(lr) Next lr End If СцепитьМного = sRes End Function |
Однако в таком случае слегка изменится и синтаксис - такие диапазоны обязательно надо будет записывать в скобках:
Синтаксис функции:
Иначе функция просто не сработает и выдаст ошибку
И еще одна реализация - в ней допускается указывать не только отдельные диапазоны, но и вообще все что угодно(ячейки, отдельный текст, числа и т.п.). Единственная проблема - в этой функции иначе организован порядок аргументов: сначала указывается разделитель, а уже потом значения для сцепления. Более подробно эта функция рассмотрена в статье Что такое функция пользователя(UDF)?. Так же эта функция не убирает дубли, что впрочем, не так сложно добавить, ориентируясь на функции выше.
Function ОбъединитьВсеСРазделителем(Разделитель As String, ParamArray Значения()) As String Dim result As String, arg, x, rc As Range For Each arg In Значения Select Case TypeName(arg) Case "Range" 'это диапазон 'цикл по всем ячейкам For Each rc In arg.Cells If result = "" Then result = rc.Value Else result = result & Разделитель & rc.Value End If Next Case "Variant()" 'это произвольный массив({"а";"б";"в"}) 'цикл по всем ячейкам For Each x In arg If result = "" Then result = x Else result = result & Разделитель & x End If Next Case Else 'это любой другой тип 'это одно статичное значение любого типа, кроме перечисленных выше '(Integer, Long, String и т.п.) - просто сцепляем If result = "" Then result = arg Else result = result & Разделитель & arg End If End Select Next ОбъединитьВсеСРазделителем = result End Function |
Также см.:
Сцепить_МН
Как сцепить несколько значений в одну ячейку по критерию? СцепитьЕсли
Что такое функция пользователя(UDF)?
Огромное Вам спасибо!!!!
Здравствуйте. Этот вопрос уже звучал. Возможно ли с помощью этой функции выбирать неск. отдельных диапазонов или ячеек для сцепки? Спасибо
Сергей, если внимательно прочитать статью, то можно увидеть, что реализаций функции 2. И одна из них как раз для нескольких диапазонов - последняя.
P.S. теперь в статье три различных функции и последние две работают с "рваными" диапазонами. Выбирайте.
Спасибо ! Был невнимателен! )
Здравствуйте!
Помогите пожалуйста! У меня Excel 2010. Я ещё только начинающий. Как текст из нескольких ячеек перенести на другой лист и там объединить его в одной ячейке
Огромное спасибо автору. Подскажите, пожалуйста, как реализовать пропуск пустых ячеек или ячеек со значением "0"?
Виталий, для того, чтобы дать ответ на этот вопрос, надо хотя бы понимать какую именно реализацию сцепления Вы используете. Если посмотреть, то в статье не один вариант функции :)
Я использую первый вариант Вами написанной функции. Имеется список фамилий, некоторые ячейки списка имеют значение 0. Всё отлично работает, вот только 0 мне не нужен в результате.
Если первый вариант написанной именно мной(СцепитьМного), то пустые ячейки там и так отсекаются. Чтобы отсечь еще и нули надо строку:
If Len(avData(lr, lc)) Then
If Len(avData(lr, lc))>0 And avData(lr, lc) <> 0 Then
заменить на такую:
Большое спасибо!
Добрый день!
Дмитрий, подскажите пожалуйста, как в функцию "ОбъединитьВсеСРазделителем" реализовать пропуск пустых ячеек или ячеек со значением "0"?
Проверкой аргументов перед сцеплением. На примере Case "Range":
по аналогии для остальных типов аргументов.
Добрый день! Большое спасибо, очень полезный скрипт! Подскажите пожалуйста, что в нём поменять чтобы сцепка сначала шла построчно, а не по столбцам ? Например если в диапазоне A1:C3 написать построчно 123 456 789 , то он соберёт числа в 147258369 пройдя по столбцам, а хотелось бы построчно в 123456789.
Fyodor, для начала неплохо бы уточнить, какую именно реализацию кода используете. В статьи их ТРИ. Для первых двух достаточно поменять вот эти две строки местами:
только не забудьте для Next lr и Next lc тоже поменять указатели или поменять строки местами, чтобы для каждого For был свой Next.
Использовал на первом коде, получилось и отлично работает! Спасибо и с наступающим Новым Годом!