Isso pode ser feito sem qualquer VBA usando a função TEXTJOIN()
introduzida no Excel 2016. Se você não tiver essa versão do Excel, poderá instalar uma UDF de preenchimento de polimento. Eu forneci um básico no final desta resposta.
Matriz:insiraaseguintefórmulaemE2
:
{=TEXTJOIN(", ",TRUE,IFERROR(INDEX(A1:A5,N(IF(1,SMALL(IFERROR(1/(1/((B1:B5=D2)*ROW(B1:B5))),FALSE),ROW(INDEX(E:E,1):INDEX(E:E,ROWS(B1:B5))))))),""))}
A fórmula prettificada é a seguinte:
{=
TEXTJOIN(
", ",
TRUE,
IFERROR(
INDEX(
A1:A5,
N(IF(1,
SMALL(
IFERROR(1/(1/((B1:B5=D2)*ROW(B1:B5))),FALSE),
ROW(INDEX(E:E,1):INDEX(E:E,ROWS(B1:B5)))
)
))
),
""
)
)}
Notas:
- A fórmula prettificada realmente funciona se inserida.
Minha versão do UDF de% de preenchimento de TEXTJOIN()
:
'============================================================================================
' Module : <any standard module>
' Version : 0.1.1
' Part : 1 of 1
' References : Optional - Microsoft VBScript Regular Expressions 5.5 [VBScript_RegExp_55]
' Source : https://superuser.com/a/1331555/763880
'============================================================================================
Public Function TEXTJOIN( _
ByRef delimiter As String, _
ByRef ignore_empty As Boolean, _
ByRef text1 As Variant _
) _
As String
Dim ƒ As Excel.WorksheetFunction: Set ƒ = Excel.WorksheetFunction
Const DELIMITER_ As String = "#"
Const PATTERN_ As String = "^(?:#)+|(?:#)+$|(#){2,}"
Static rexDelimiterEscaper As Object ' VBScript_RegExp_55.RegExp ' ## Object
Static rexEmptyIgnorer As Object ' VBScript_RegExp_55.RegExp ' ## Object
If rexEmptyIgnorer Is Nothing _
Then
Set rexEmptyIgnorer = CreateObject("VBScript.RegExp") ' New VBScript_RegExp_55.RegExp ' ## CreateObject("VBScript.RegExp")
With rexEmptyIgnorer
.Global = True
.Pattern = PATTERN_ ' Replacement = "$1"
End With
Set rexDelimiterEscaper = CreateObject("VBScript.RegExp") ' New VBScript_RegExp_55.RegExp ' ## CreateObject("VBScript.RegExp")
With rexDelimiterEscaper
.Global = True
.Pattern = "(.)" ' Replacement = "\"
End With
End If
Dim varText1 As Variant
Select Case TypeName(text1)
Case "Range":
varText1 = ƒ.Transpose(text1.Value2)
If text1.Rows.Count = 1 Then
varText1 = ƒ.Transpose(varText1)
If text1.Columns.Count = 1 Then varText1 = Array(varText1)
End If
Case "Variant()":
On Error Resume Next
If LBound(text1, 2) <> LBound(text1, 2) Then
varText1 = text1
Else
varText1 = ƒ.Transpose(text1)
End If
On Error GoTo 0
Case Else:
varText1 = Array(text1)
End Select
If ignore_empty _
Then
With rexEmptyIgnorer
.Pattern = Replace(PATTERN_, DELIMITER_, rexDelimiterEscaper.Replace(delimiter, "\"))
TEXTJOIN = .Replace(Join(varText1, delimiter), "$1")
End With
Else
TEXTJOIN = Join(varText1, delimiter)
End If
End Function
Notas:
- Isso não é um preenchimento de polietileno adequado:
- Os dois primeiros argumentos não são opcionais;
- Se você não deseja usar um delimitador, você deve passar uma string vazia como o primeiro parâmetro.
- Existe apenas um outro argumento (também obrigatório) permitido.
- Você pode passar qualquer coisa para o terceiro argumento, exceto um array / intervalo de várias dimensões. Isso resultará em um erro
#VALUE!
. - Deve ser muito rápido, especialmente para grandes entradas, pois não usa loops. Se você não estiver ignorando valores vazios, será muito rápido. Ignorá-los será mais lento como um par de expressões regulares e uma manipulação extra de string também deve ser usada.